bruno 2004/04/29 03:35:30
Added: src/blocks/forms/java/org/apache/cocoon/forms/flow/javascript/v3 Form.js ScriptableWidget.java Log: initial commit Revision Changes Path 1.1 cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/flow/javascript/v3/Form.js Index: Form.js =================================================================== /* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Cocoon Forms JavaScript API */ defineClass("org.apache.cocoon.forms.flow.javascript.v3.ScriptableWidget"); importClass(Packages.org.apache.cocoon.forms.FormContext); /** * Create a form, giving either: * - the URI of its definition file * - an fd:form element in the form of a org.w3c.dom.Element */ function Form(formDefinition) { var formMgr = null; var resolver = null; var src = null; try { var FormManager = Packages.org.apache.cocoon.forms.FormManager; var SourceResolver = Packages.org.apache.cocoon.environment.SourceResolver; formMgr = cocoon.getComponent(FormManager.ROLE); var form; if ((typeof formDefinition) == "string" || formDefinition instanceof String) { resolver = cocoon.getComponent(SourceResolver.ROLE); src = resolver.resolveURI(formDefinition); form = formMgr.createForm(src); } else { form = formMgr.createForm(formDefinition) } this.form = form; this.model = new Widget(form); this.bindings_ = new Object(); this.locale = java.util.Locale.getDefault(); } finally { cocoon.releaseComponent(formMgr); if (src != null) resolver.release(src); cocoon.releaseComponent(resolver); } } /** * Get a Widget (the java object) from the form. * If <code>name</code> is undefined, the form widget itself is returned. * Otherwise, the form's child widget of name <code>name</code> is returned. */ Form.prototype.getWidget = function(name) { if (name == undefined) { return this.form; } else { return this.form.getWidget(name); } } /** * Displays a form until it is valid. */ Form.prototype.showForm = function(uri, viewData, fun, ttl) { if (viewData == null) viewData = new Object(); viewData["CocoonFormsInstance"] = this.form; var webCont; var finished = false; while (!finished) { webCont = cocoon.sendPageAndWait(uri, viewData, fun, ttl); finished = this.processSubmit(); } return webCont; } Form.prototype.processSubmit = function() { var formContext = new FormContext(cocoon.request, this.locale); return this.form.process(formContext); } Form.prototype.createEmptySelectionList = function(message) { return new Packages.org.apache.cocoon.forms.datatype.EmptySelectionList(message); } Form.prototype.createBinding = function(arg1, arg2) { var name; var bindingURI; if (arguments.length == 2) { name = arg1; bindingURI = arg2; } else { name = "default"; bindingURI = arg1; } var bindingManager = null; var source = null; var resolver = null; try { var BindingManager = Packages.org.apache.cocoon.forms.binding.BindingManager; var SourceResolver = Packages.org.apache.cocoon.environment.SourceResolver; bindingManager = cocoon.getComponent(BindingManager.ROLE); resolver = cocoon.getComponent(SourceResolver.ROLE); source = resolver.resolveURI(bindingURI); this.bindings_[name] = bindingManager.createBinding(source); } finally { if (source != null) { resolver.release(source); } cocoon.releaseComponent(bindingManager); cocoon.releaseComponent(resolver); } } Form.prototype.load = function(arg1, arg2) { var name; var object; if (arguments.length == 2) { name == arg1; object = arg2; } else { name = "default"; object = arg1; } if (this.bindings_[name] == null) { throw "Binding \"" + name + "\" not configured for this form."; } this.bindings_[name].loadFormFromModel(this.getWidget(), object); } Form.prototype.save = function(arg1, arg2) { var name; var object; if (arguments.length == 2) { name = arg1; object = arg2; } else { name = "default"; object = arg1; } if (this.bindings_[name] == null) { throw "Binding \"" + name + "\" not configured for this form."; } this.bindings_[name].saveFormToModel(this.getWidget(), object); } Form.prototype.setAttribute = function(name, value) { this.form.setAttribute(name, value); } Form.prototype.getAttribute = function(name) { return this.form.getAttribute(name); } Form.prototype.removeAttribute = function(name) { this.form.removeAttribute(name); } 1.1 cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/flow/javascript/v3/ScriptableWidget.java Index: ScriptableWidget.java =================================================================== /* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.cocoon.forms.flow.javascript.v3; import org.apache.cocoon.forms.datatype.Datatype; import org.apache.cocoon.forms.datatype.SelectionList; import org.apache.cocoon.forms.event.*; import org.apache.cocoon.forms.formmodel.Action; import org.apache.cocoon.forms.formmodel.AggregateField; import org.apache.cocoon.forms.formmodel.BooleanField; import org.apache.cocoon.forms.formmodel.ContainerWidget; import org.apache.cocoon.forms.formmodel.DataWidget; import org.apache.cocoon.forms.formmodel.Field; import org.apache.cocoon.forms.formmodel.Form; import org.apache.cocoon.forms.formmodel.MultiValueField; import org.apache.cocoon.forms.formmodel.Output; import org.apache.cocoon.forms.formmodel.Repeater; import org.apache.cocoon.forms.formmodel.SelectableWidget; import org.apache.cocoon.forms.formmodel.Submit; import org.apache.cocoon.forms.formmodel.Upload; import org.apache.cocoon.forms.formmodel.Widget; import org.apache.cocoon.forms.validation.ValidationError; import org.apache.cocoon.forms.validation.ValidationErrorAware; import org.apache.cocoon.forms.validation.WidgetValidator; import org.mozilla.javascript.Context; import org.mozilla.javascript.JavaScriptException; import org.mozilla.javascript.NativeArray; import org.mozilla.javascript.Function; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; import org.mozilla.javascript.Wrapper; import java.math.BigDecimal; import java.util.List; import java.util.LinkedList; import java.util.Iterator; import java.util.Map; import java.util.HashMap; /** * @version $Id: ScriptableWidget.java,v 1.1 2004/04/29 10:35:30 bruno Exp $ * */ public class ScriptableWidget extends ScriptableObject implements ValueChangedListener, ActionListener, WidgetValidator { final static String WIDGETS_PROPERTY = "__widgets__"; Widget delegate; ScriptableWidget formWidget; private Function onChange; private Function onActivate; private Function validator; public String getClassName() { return "Widget"; } public ScriptableWidget() { } public ScriptableWidget(Object widget) { this.delegate = (Widget)unwrap(widget); if (delegate instanceof Form) { formWidget = this; Map widgetMap = new HashMap(); widgetMap.put(delegate, this); defineProperty(WIDGETS_PROPERTY, widgetMap, DONTENUM|PERMANENT); } } static private Object unwrap(Object obj) { if (obj == Undefined.instance) { return null; } if (obj instanceof Wrapper) { return ((Wrapper)obj).unwrap(); } return obj; } private void deleteWrapper(Widget w) { if (delegate instanceof Form) { Map widgetMap = (Map)super.get(WIDGETS_PROPERTY, this); widgetMap.remove(w); } } private ScriptableWidget wrap(Widget w) { if (w == null) return null; if (delegate instanceof Form) { Map widgetMap = (Map)super.get(WIDGETS_PROPERTY, this); ScriptableWidget result = null; result = (ScriptableWidget)widgetMap.get(w); if (result == null) { result = new ScriptableWidget(w); result.formWidget = this; result.setPrototype(getClassPrototype(this, getClassName())); result.setParentScope(getParentScope()); widgetMap.put(w, result); } return result; } else { return formWidget.wrap(w); } } public boolean has(String id, Scriptable start) { if (delegate != null) { if (delegate instanceof ContainerWidget) { Widget sub = ((ContainerWidget)delegate).getWidget(id); if (sub != null) { return true; } } } return super.has(id, start); } public boolean has(int index, Scriptable start) { if (super.has(index, start)) { return true; } if (delegate instanceof Repeater) { Repeater repeater = (Repeater)delegate; return index >= 0 && index < repeater.getSize(); } if (delegate instanceof MultiValueField) { Object[] values = (Object[])delegate.getValue(); return index >= 0 && index < values.length; } return false; } public Object get(String id, Scriptable start) { Object result = super.get(id, start); if (result != NOT_FOUND) { return result; } if (delegate != null && delegate instanceof ContainerWidget) { Widget sub = ((ContainerWidget)delegate).getWidget(id); if (sub != null) { return wrap(sub); } } return NOT_FOUND; } public Object get(int index, Scriptable start) { Object result = super.get(index, start); if (result != NOT_FOUND) { return result; } if (delegate instanceof Repeater) { Repeater repeater = (Repeater)delegate; if (index >= 0) { int count = index + 1 - repeater.getSize(); if (count > 0) { ScriptableWidget[] rows = new ScriptableWidget[count]; for (int i = 0; i < count; i++) { rows[i] = wrap(repeater.addRow()); } for (int i = 0; i < count; i++) { rows[i].notifyAddRow(); } } return wrap(repeater.getRow(index)); } } else if (delegate instanceof MultiValueField) { Object[] values = (Object[])delegate.getValue(); if (index >= 0 && index < values.length) { return values[index]; } } return NOT_FOUND; } public Object[] getAllIds() { Object[] result = super.getAllIds(); return addWidgetIds(result); } public Object[] getIds() { Object[] result = super.getIds(); return addWidgetIds(result); } private Object[] addWidgetIds(Object[] result) { if (delegate instanceof ContainerWidget) { Iterator iter = ((ContainerWidget)delegate).getChildren(); List list = new LinkedList(); for (int i = 0; i < result.length; i++) { list.add(result[i]); } while (iter.hasNext()) { Widget widget = (Widget)iter.next(); list.add(widget.getId()); } result = list.toArray(); } return result; } private void deleteRow(Repeater repeater, int index) { Widget row = repeater.getRow(index); ScriptableWidget s = wrap(row); s.notifyRemoveRow(); formWidget.deleteWrapper(row); repeater.removeRow(index); } private void notifyAddRow() { ScriptableWidget repeater = wrap(delegate.getParent()); Object prop = getProperty(repeater, "onAddRow"); if (prop instanceof Function) { try { Function fun = (Function)prop; Object[] args = new Object[1]; Scriptable scope = getTopLevelScope(this); Scriptable thisObj = scope; Context cx = Context.getCurrentContext(); args[0] = this; fun.call(cx, scope, thisObj, args); } catch (Exception exc) { throw Context.reportRuntimeError(exc.getMessage()); } } } private void notifyRemoveRow() { ScriptableWidget repeater = wrap(delegate.getParent()); Object prop = getProperty(repeater, "onRemoveRow"); if (prop instanceof Function) { try { Function fun = (Function)prop; Object[] args = new Object[1]; Scriptable scope = getTopLevelScope(this); Scriptable thisObj = scope; Context cx = Context.getCurrentContext(); args[0] = this; fun.call(cx, scope, thisObj, args); } catch (Exception exc) { throw Context.reportRuntimeError(exc.getMessage()); } } } public void delete(int index) { if (delegate instanceof Repeater) { Repeater repeater = (Repeater)delegate; if (index >= 0 && index < repeater.getSize()) { deleteRow(repeater, index); return; } } else if (delegate instanceof MultiValueField) { MultiValueField field = (MultiValueField)delegate; Object[] values = (Object[])field.getValue(); if (values != null && values.length > index) { Object[] newValues = new Object[values.length-1]; int i; for (i = 0; i < index; i++) { newValues[i] = values[i]; } i++; for (;i < values.length; i++) { newValues[i-1] = values[i]; } field.setValues(newValues); } return; } super.delete(index); } public Object jsGet_value() { return delegate.getValue(); } public Object jsFunction_getValue() { return jsGet_value(); } public void jsFunction_setValue(Object value) throws JavaScriptException { jsSet_value(value); } public void jsSet_length(int len) { if (delegate instanceof Repeater) { Repeater repeater = (Repeater)delegate; int size = repeater.getSize(); if (size > len) { while (repeater.getSize() > len) { deleteRow(repeater, repeater.getSize() - 1); } } else { for (int i = size; i < len; ++i) { wrap(repeater.addRow()).notifyAddRow(); } } } } public Object jsGet_length() { if (delegate instanceof Repeater) { Repeater repeater = (Repeater)delegate; return new Integer(repeater.getSize()); } return Undefined.instance; } public void jsSet_value(Object value) throws JavaScriptException { if (delegate instanceof AggregateField) { AggregateField aggregateField = (AggregateField)delegate; if (value instanceof Scriptable) { Scriptable obj = (Scriptable)value; Object[] ids = obj.getIds(); for (int i = 0; i < ids.length; i++) { String id = String.valueOf(ids[i]); Object val = getProperty(obj, id); ScriptableWidget wid = wrap(aggregateField.getWidget(id)); if (wid == null) { throw new JavaScriptException("No field \"" + id + "\" in widget \"" + aggregateField.getId() + "\""); } if (wid.delegate instanceof Field || wid.delegate instanceof BooleanField || wid.delegate instanceof Output) { if (val instanceof Scriptable) { Scriptable s = (Scriptable)val; if (s.has("value", s)) { wid.jsSet_value(s.get("value", s)); } } } else { wid.jsSet_value(val); } } aggregateField.combineFields(); return; } // fall through } if (delegate instanceof DataWidget) { value = unwrap(value); if (value != null) { // Coerce values Datatype datatype = ((DataWidget)delegate).getDatatype(); Class typeClass = datatype.getTypeClass(); if (typeClass == String.class) { value = Context.toString(value); } else if (typeClass == boolean.class || typeClass == Boolean.class) { value = Context.toBoolean(value) ? Boolean.TRUE : Boolean.FALSE; } else { if (value instanceof Double) { // make cform accept a JS Number if (typeClass == long.class || typeClass == Long.class) { value = new Long(((Number)value).longValue()); } else if (typeClass == int.class || typeClass == Integer.class) { value = new Integer(((Number)value).intValue()); } else if (typeClass == float.class || typeClass == Float.class) { value = new Float(((Number)value).floatValue()); } else if (typeClass == short.class || typeClass == Short.class) { value = new Short(((Number)value).shortValue()); } else if (typeClass == BigDecimal.class) { value = new BigDecimal(((Number)value).doubleValue()); } } } } delegate.setValue(value); } else if (delegate instanceof BooleanField) { BooleanField field = (BooleanField)delegate; field.setValue(new Boolean(Context.toBoolean(value))); } else if (delegate instanceof Repeater) { Repeater repeater = (Repeater)delegate; if (value instanceof NativeArray) { NativeArray arr = (NativeArray)value; Object length = getProperty(arr, "length"); int len = ((Number)length).intValue(); for (int i = repeater.getSize(); i >= len; --i) { deleteRow(repeater, i); } for (int i = 0; i < len; i++) { Object elemValue = getProperty(arr, i); ScriptableWidget wid = wrap(repeater.getRow(i)); wid.jsSet_value(elemValue); } } } else if (delegate instanceof Repeater.RepeaterRow) { Repeater.RepeaterRow row = (Repeater.RepeaterRow)delegate; if (value instanceof Scriptable) { Scriptable obj = (Scriptable)value; Object[] ids = obj.getIds(); for (int i = 0; i < ids.length; i++) { String id = String.valueOf(ids[i]); Object val = getProperty(obj, id); ScriptableWidget wid = wrap(row.getWidget(id)); if (wid == null) { throw new JavaScriptException("No field \"" + id + "\" in row " + i + " of repeater \"" + row.getParent().getId() + "\""); } if (wid.delegate instanceof Field || wid.delegate instanceof BooleanField || wid.delegate instanceof Output) { if (val instanceof Scriptable) { Scriptable s = (Scriptable)val; if (s.has("value", s)) { wid.jsSet_value(s.get("value", s)); } } } else { wid.jsSet_value(val); } } } else { throw new JavaScriptException("Expected an object instead of: " + Context.toString(value)); } } else if (delegate instanceof MultiValueField) { MultiValueField field = (MultiValueField)delegate; Object[] values = null; if (value instanceof NativeArray) { NativeArray arr = (NativeArray)value; Object length = getProperty(arr, "length"); int len = ((Number)length).intValue(); values = new Object[len]; for (int i = 0; i < len; i++) { Object elemValue = getProperty(arr, i); values[i] = unwrap(elemValue); } } else if (value instanceof Object[]) { values = (Object[])value; } field.setValues(values); } else { delegate.setValue(value); } } public String jsFunction_getId() { return delegate.getId(); } public ScriptableWidget jsFunction_getSubmitWidget() { return wrap(delegate.getForm().getSubmitWidget()); } public String jsFunction_getFullyQualifiedId() { return delegate.getFullyQualifiedId(); } // public String jsFunction_getNamespace() { // return delegate.getNamespace(); // } public Scriptable jsFunction_getParent() { if (delegate != null) { return wrap(delegate.getParent()); } return Undefined.instance; } public boolean jsFunction_isRequired() { return delegate.isRequired(); } public ScriptableWidget jsFunction_getForm() { return formWidget; } public boolean jsFunction_equals(Object other) { if (other instanceof ScriptableWidget) { ScriptableWidget otherWidget = (ScriptableWidget)other; return delegate.equals(otherWidget.delegate); } return false; } public ScriptableWidget jsFunction_getWidget(String id) { Widget sub = null; if (delegate instanceof ContainerWidget) sub = ((ContainerWidget)delegate).getWidget(id); return wrap(sub); } public void jsFunction_setValidationError(Object message /* null to clear error */, Object parameters) { if (delegate instanceof ValidationErrorAware) { String[] parms = null; if (parameters != null && parameters != Undefined.instance) { Scriptable obj = Context.toObject(parameters, this); int len = (int) Context.toNumber(getProperty(obj, "length")); parms = new String[len]; for (int i = 0; i < len; i++) { parms[i] = Context.toString(getProperty(obj, i)); } } ValidationError validationError = null; if (message != null) { if (parms != null && parms.length > 0) { validationError = new ValidationError(Context.toString(message), parms); } else { validationError = new ValidationError(Context.toString(message), parms != null); } } ((ValidationErrorAware)delegate).setValidationError(validationError); } } public Widget jsFunction_unwrap() { return delegate; } public ScriptableWidget jsFunction_addRow() { ScriptableWidget result = null; if (delegate instanceof Repeater) { result = wrap(((Repeater)delegate).addRow()); result.notifyAddRow(); } return result; } public ScriptableObject jsFunction_getRow(int index) { if (delegate instanceof Repeater) { return wrap(((Repeater)delegate).getRow(index)); } return null; } public void jsFunction_removeRow(Object obj) throws JavaScriptException { if (delegate instanceof Repeater) { Repeater repeater = (Repeater)delegate; if (obj instanceof Function) { Function fun = (Function)obj; int len = repeater.getSize(); boolean[] index = new boolean[len]; Object[] args = new Object[1]; Scriptable scope = getTopLevelScope(this); Scriptable thisObj = scope; Context cx = Context.getCurrentContext(); for (int i = 0; i < len; i++) { ScriptableWidget row = wrap(repeater.getRow(i)); args[0] = row; Object result = fun.call(cx, scope, thisObj, args); index[i] = Context.toBoolean(result); } for (int i = len-1; i >= 0; --i) { if (index[i]) { deleteRow(repeater, i); } } } else { int index = (int)Context.toNumber(obj); if (index >= 0 && index < repeater.getSize()) { deleteRow(repeater, index); } } } } public Object jsGet_onChange() { if (onChange != null) return onChange; else return Undefined.instance; } public Object jsGet_onActivate() { if (onActivate != null) return onActivate; else return Undefined.instance; } public void jsSet_onChange(Object value) { value = unwrap(value); if (value == null) { this.onChange = null; if (delegate instanceof ValueChangedListenerEnabled) { ((ValueChangedListenerEnabled)delegate).removeValueChangedListener(this); } return; } if (value instanceof Function) { if (delegate instanceof ValueChangedListenerEnabled) { if (this.onChange == null) ((ValueChangedListenerEnabled)delegate).addValueChangedListener(this); this.onChange = (Function)value; } } } public void jsSet_onActivate(Object value) { value = unwrap(value); if (value == null) { this.onActivate = null; if (delegate instanceof ActionListenerEnabled) { ((ActionListenerEnabled)delegate).removeActionListener(this); } return; } if (value instanceof Function) { if (delegate instanceof ActionListenerEnabled) { if (this.onActivate == null) ((ActionListenerEnabled)delegate).addActionListener(this); this.onActivate = (Function)value; } } } public void valueChanged(ValueChangedEvent event) { if (onChange != null) { try { Object[] args = new Object[2]; Scriptable scope = getTopLevelScope(this); Scriptable thisObj = scope; Context cx = Context.getCurrentContext(); args[0] = event.getOldValue(); args[1] = event.getNewValue(); onChange.call(cx, scope, thisObj, args); } catch (Exception exc) { throw Context.reportRuntimeError(exc.getMessage()); } } } public void actionPerformed(ActionEvent event) { if (onActivate != null) { try { Object[] args = new Object[1]; Scriptable scope = getTopLevelScope(this); Scriptable thisObj = scope; Context cx = Context.getCurrentContext(); args[0] = event.getActionCommand(); onActivate.call(cx, scope, thisObj, args); } catch (Exception exc) { throw Context.reportRuntimeError(exc.getMessage()); } } } public Object jsGet_validator() { if (validator != null) return validator; else return Undefined.instance; } public void jsSet_validator(Object value) { value = unwrap(value); if (value == null) { this.validator = null; delegate.removeValidator(this); return; } if (value instanceof Function) { if (delegate instanceof ValueChangedListenerEnabled) { if (this.validator == null) delegate.addValidator(this); this.validator = (Function)value; } } } public boolean validate(Widget widget) { try { Object[] args = new Object[1]; Scriptable scope = getTopLevelScope(this); Scriptable thisObj = scope; Context cx = Context.getCurrentContext(); args[0] = this; Object result = validator.call(cx, scope, thisObj, args); return Context.toBoolean(result); } catch (Exception exc) { throw Context.reportRuntimeError(exc.getMessage()); } } public void jsFunction_setSelectionList(Object arg, Object valuePathArg, Object labelPathArg) throws Exception { if (delegate instanceof SelectableWidget) { arg = unwrap(arg); if (valuePathArg != Undefined.instance && labelPathArg != Undefined.instance) { String valuePath = Context.toString(valuePathArg); String labelPath = Context.toString(labelPathArg); ((SelectableWidget)delegate).setSelectionList(arg, valuePath, labelPath); } else { if (arg instanceof SelectionList) { SelectionList selectionList = (SelectionList)arg; ((SelectableWidget)delegate).setSelectionList(selectionList); } else { String str = Context.toString(arg); ((SelectableWidget)delegate).setSelectionList(str); } } } } static final Object[] WIDGET_CLASS_MAP = { Form.class, "Form", Field.class, "Field", Action.class, "Action", Repeater.class, "Repeater", Repeater.RepeaterRow.class, "RepeaterRow", AggregateField.class, "AggregateField", BooleanField.class, "BooleanField", MultiValueField.class, "MultiValueField", Output.class, "Output", Submit.class, "Submit", Upload.class, "Upload" }; public String jsFunction_getWidgetClass() { for (int i = 0; i < WIDGET_CLASS_MAP.length; i += 2) { Class c = (Class)WIDGET_CLASS_MAP[i]; if (c.isAssignableFrom(delegate.getClass())) { return (String)WIDGET_CLASS_MAP[i + 1]; } } return "<unknown>"; } public String jsFunction_toString() { return "[object Widget (" + jsFunction_getWidgetClass() + ")]"; } }