mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
17891: Merged DEV_TEMPORARY to V3.2 17873: ETHREEOH-3810: WCM - Recursion detector erroring 18032: Merged V3.1 to V3.2 18030: Merged V2.2 to V3.1 17683: Merged DEV_TEMPORARY to V2.2 (back-port of fix) 17677: ETHREEOH-2778: davfs2 is not working correctly with Alfresco 17880: Merged DEV_TEMPORARY to V2.2 (record-only as fix is already applied to 3.1 branch) 17845: ETWOTWO-1289: My Web Files (Forms) dashlets: XSS Attck can be made when web project's details has been edited 18062: Merged DEV_TEMPORARY to V3.2 18036: ETHREEOH-1844: Text field (areas) became non-editable if user use navigate-remove combination for repeatable elements on Create Web content based on web form screen 18205: Merged V3.1 to V3.2 (record-only) *RECORD ONLY* Merged DEV/TEMPORARY to 3.1 17837: ETHREEOH-3801: Creating users via the api does not add them to the user store 18277: Merged DEV_TEMPORARY to V3.2 18178: ETHREEOH-3222: ERROR [org.alfresco.webdav.protocol] WebDAV method not implemented - PROPPATCH 18311: Fix for ETHREEOH-3872: forms32 examples not working 18317: Remaining fixes to forms samples (ETHREEOH-3872) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18318 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
4865 lines
160 KiB
JavaScript
4865 lines
160 KiB
JavaScript
/*
|
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// XForms user interface
|
|
//
|
|
// This script communicates with the XFormBean to produce and manage an xform.
|
|
//
|
|
// This script requires mootools.js, dojo.js, tiny_mce.js,
|
|
// tiny_mce_wcm_extensions.js, and upload_helper.js to be loaded in advance.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// initialization
|
|
//
|
|
// Initiliaze dojo requirements, tinymce, and add a hook to load the xform.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
djConfig.parseWidgets = false;
|
|
dojo.require("dojo.lfx.html");
|
|
alfresco.log = alfresco.constants.DEBUG ? log : Class.empty;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// constants
|
|
//
|
|
// These are the client side declared constants. Others relating to namespaces
|
|
// and the webapp context path are expected to be provided by the jsp including
|
|
// this script.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
alfresco.xforms.constants.XFORMS_ERROR_DIV_ID = "alfresco-xforms-error";
|
|
|
|
alfresco.xforms.constants.EXPANDED_IMAGE = new Image();
|
|
alfresco.xforms.constants.EXPANDED_IMAGE.src =
|
|
alfresco.constants.WEBAPP_CONTEXT + "/images/icons/expanded.gif";
|
|
|
|
alfresco.xforms.constants.COLLAPSED_IMAGE = new Image();
|
|
alfresco.xforms.constants.COLLAPSED_IMAGE.src =
|
|
alfresco.constants.WEBAPP_CONTEXT + "/images/icons/collapsed.gif";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// widgets
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Base class for all xforms widgets. Each widget has a set of common properties,
|
|
* particularly a corresponding xforms node, a node within the browser DOM,
|
|
* a parent widget, and state variables.
|
|
*/
|
|
alfresco.xforms.Widget = new Class({
|
|
initialize: function(xform, xformsNode, parentWidget, domNode)
|
|
{
|
|
this.xform = xform;
|
|
this.xformsNode = xformsNode;
|
|
this.parentWidget = parentWidget;
|
|
this.id = this.xformsNode.getAttribute("id");
|
|
this._modified = false;
|
|
this._valid = true;
|
|
var b = this.xform.getBinding(this.xformsNode);
|
|
if (b)
|
|
{
|
|
alfresco.log("adding " + this.id + " to binding " + b.id);
|
|
b.widgets[this.id] = this;
|
|
}
|
|
else
|
|
{
|
|
alfresco.log("no binding found for " + this.id);
|
|
}
|
|
this.domNode = domNode || new Element("div");
|
|
this.domNode.setAttribute("id", this.id + "-domNode");
|
|
this.domNode.widget = this;
|
|
this.domNode.addClass("xformsItem");
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** A reference to the xform. */
|
|
xform: null,
|
|
|
|
/** The xformsNode managed by this widget. */
|
|
xformsNode: null,
|
|
|
|
/** The dom node containing the label for this widget. */
|
|
labelNode: null,
|
|
|
|
/** The parent widget, or null if this is the root widget. */
|
|
parentWidget: null,
|
|
|
|
/** The dom node for this widget. */
|
|
domNode: null,
|
|
|
|
/** The dom node containing this widget. */
|
|
domContainer: null,
|
|
|
|
/** The parent widget which is using this as a composite. */
|
|
_compositeParent: null,
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** Sets the widget's modified state, as indicated by an XFormsEvent. */
|
|
setModified: function(b)
|
|
{
|
|
if (this._modified != b)
|
|
{
|
|
this._modified = b;
|
|
this._updateDisplay(false);
|
|
if (this.isValidForSubmit())
|
|
{
|
|
this.hideAlert();
|
|
}
|
|
}
|
|
},
|
|
|
|
/** Sets the widget's valid state, as indicated by an XFormsEvent */
|
|
setValid: function(b)
|
|
{
|
|
if (this._valid != b)
|
|
{
|
|
this._valid = b;
|
|
this._updateDisplay(false);
|
|
if (this.isValidForSubmit())
|
|
{
|
|
this.hideAlert();
|
|
}
|
|
else
|
|
{
|
|
this.showAlert();
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Heuristic approach to determine if the widget is valid for submit or
|
|
* if it's causing an xforms-error.
|
|
*/
|
|
isValidForSubmit: function()
|
|
{
|
|
if (typeof this._valid != "undefined" && !this._valid)
|
|
{
|
|
alfresco.log(this.id + " is invalid");
|
|
return false;
|
|
}
|
|
if (!this._modified &&
|
|
this.isRequired() &&
|
|
this.getInitialValue() == null)
|
|
{
|
|
alfresco.log(this.id + " is unmodified and required and empty");
|
|
return false;
|
|
}
|
|
if (this.isRequired() && this.getValue() == null)
|
|
{
|
|
alfresco.log(this.id + " is required and empty");
|
|
return false;
|
|
}
|
|
alfresco.log(this.id + " is valid: {" +
|
|
"modified: " + this._modified +
|
|
", required: " + this.isRequired() +
|
|
", initial_value: " + this.getInitialValue() +
|
|
", value: " + this.getValue() + "}");
|
|
return true;
|
|
},
|
|
|
|
/** Returns the depth of the widget within the widget heirarchy. */
|
|
getDepth: function()
|
|
{
|
|
var result = 1;
|
|
var p = this.parentWidget;
|
|
while (p)
|
|
{
|
|
result++;
|
|
p = p.parentWidget;
|
|
}
|
|
return result;
|
|
},
|
|
|
|
/** Returns the root group element */
|
|
getViewRoot: function()
|
|
{
|
|
var p = this;
|
|
while (p.parentWidget)
|
|
{
|
|
p = p.parentWidget;
|
|
}
|
|
if (! (p instanceof alfresco.xforms.ViewRoot))
|
|
{
|
|
throw new Error("expected root widget " + p + " to be a view root");
|
|
}
|
|
return p;
|
|
},
|
|
|
|
/** Returns true if the parent is an ancestor of the given parent */
|
|
isAncestorOf: function(parentWidget)
|
|
{
|
|
var p = this;
|
|
while (p.parentWidget)
|
|
{
|
|
if (p.parentWidget == parentWidget)
|
|
{
|
|
return true;
|
|
}
|
|
p = p.parentWidget;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
/** Sets the widget's enabled state, as indicated by an XFormsEvent */
|
|
setEnabled: function(enabled)
|
|
{
|
|
},
|
|
|
|
/** Returns the widget's enabled state */
|
|
isEnabled: function()
|
|
{
|
|
return true;
|
|
},
|
|
|
|
/** Sets the widget's required state, as indicated by an XFormsEvent */
|
|
setRequired: function(b)
|
|
{
|
|
if (this._required != b)
|
|
{
|
|
this._required = b;
|
|
this._updateDisplay(false);
|
|
}
|
|
},
|
|
|
|
/** Indicates if a value is required for the widget. */
|
|
isRequired: function()
|
|
{
|
|
if (typeof this._required != "undefined")
|
|
{
|
|
return this._required;
|
|
}
|
|
var binding = this.xform.getBinding(this.xformsNode);
|
|
return binding && binding.isRequired();
|
|
},
|
|
|
|
/** Sets the widget's readonly state, as indicated by an XFormsEvent */
|
|
setReadonly: function(readonly)
|
|
{
|
|
this._readonly = readonly;
|
|
},
|
|
|
|
/** Indicates if the widget's value is readonly. */
|
|
isReadonly: function()
|
|
{
|
|
if (typeof this._readonly != "undefined")
|
|
{
|
|
return this._readonly;
|
|
}
|
|
var binding = this.xform.getBinding(this.xformsNode);
|
|
return binding && binding.isReadonly();
|
|
},
|
|
|
|
isVisible: function()
|
|
{
|
|
return true;
|
|
},
|
|
|
|
/** Commits the changed value to the server */
|
|
_commitValueChange: function(value)
|
|
{
|
|
if (this._compositeParent)
|
|
{
|
|
this._compositeParent._commitValueChange(value);
|
|
}
|
|
else
|
|
{
|
|
this.xform.setXFormsValue(this.id, value || this.getValue());
|
|
}
|
|
},
|
|
|
|
/** Sets the value contained by the widget */
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (forceCommit)
|
|
{
|
|
this.xform.setXFormsValue(this.id, value);
|
|
}
|
|
},
|
|
|
|
/** Returns the value contained by the widget, or null if none is set */
|
|
getValue: function()
|
|
{
|
|
return null;
|
|
},
|
|
|
|
/** Sets the widget's initial value. */
|
|
setInitialValue: function(value, forceCommit)
|
|
{
|
|
this._initialValue =
|
|
(typeof value == "string" && value.length == 0 ? null : value);
|
|
if (forceCommit)
|
|
{
|
|
this.xform.setXFormsValue(this.id, value);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Returns the widget's local value, either with a local variable, or by
|
|
* looking it up within the model section.
|
|
*/
|
|
getInitialValue: function()
|
|
{
|
|
if (typeof this._initialValue != "undefined")
|
|
{
|
|
return this._initialValue;
|
|
}
|
|
|
|
var xpath = this._getXPathInInstanceDocument();
|
|
var d = this.xformsNode.ownerDocument;
|
|
var contextNode = this.xform.getInstance();
|
|
alfresco.log("locating " + xpath + " in " + contextNode.nodeName);
|
|
this._initialValue = _evaluateXPath("/" + xpath,
|
|
this.xform.getInstance(),
|
|
XPathResult.FIRST_ORDERED_NODE_TYPE);
|
|
if (!this._initialValue)
|
|
{
|
|
alfresco.log("unable to resolve xpath /" + xpath + " for " + this.id);
|
|
this._initialValue = null;
|
|
}
|
|
else
|
|
{
|
|
var getNodeText = function(xmlNode)
|
|
{
|
|
if(xmlNode)
|
|
{
|
|
if (xmlNode.firstChild)
|
|
{
|
|
return (typeof(xmlNode.textContent) != "undefined") ? xmlNode.textContent : xmlNode.firstChild.nodeValue;
|
|
}
|
|
else
|
|
{
|
|
return (typeof(xmlNode.textContent) != "undefined") ? xmlNode.textContent : xmlNode.nodeValue;
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
this._initialValue = (this._initialValue.nodeType == document.ELEMENT_NODE
|
|
? (this._initialValue.firstChild
|
|
? getNodeText(this._initialValue)
|
|
: null)
|
|
: getNodeText(this._initialValue));
|
|
if (typeof this._initialValue == "string" && this._initialValue.length == 0)
|
|
{
|
|
this._initialValue = null;
|
|
}
|
|
alfresco.log("resolved xpath " + xpath + " to " + this._initialValue);
|
|
}
|
|
return this._initialValue;
|
|
},
|
|
|
|
/** Produces an xpath to the model node within the instance data document. */
|
|
_getXPathInInstanceDocument: function()
|
|
{
|
|
var binding = this.xform.getBinding(this.xformsNode);
|
|
var xpath = '';
|
|
var repeatIndices = this.getRepeatIndices();
|
|
do
|
|
{
|
|
var s = binding.nodeset;
|
|
if (binding.nodeset == '.')
|
|
{
|
|
binding = binding.parentBinding;
|
|
}
|
|
if (binding.nodeset.match(/.+\[.+\]/))
|
|
{
|
|
s = binding.nodeset.replace(/([^\[]+)\[.*/, "$1");
|
|
s += '[' + (repeatIndices.shift().index) + ']';
|
|
}
|
|
xpath = s + (xpath.length != 0 ? '/' + xpath : "");
|
|
binding = binding.parentBinding;
|
|
}
|
|
while (binding);
|
|
return xpath;
|
|
},
|
|
|
|
/** Returns a child node by name within the xform. */
|
|
_getChildXFormsNode: function(nodeName)
|
|
{
|
|
var x = _getElementsByTagNameNS(this.xformsNode,
|
|
alfresco.xforms.constants.XFORMS_NS,
|
|
alfresco.xforms.constants.XFORMS_PREFIX,
|
|
nodeName);
|
|
for (var i = 0; i < x.length; i++)
|
|
{
|
|
if (x[i].parentNode == this.xformsNode)
|
|
{
|
|
return x[i];
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
|
|
/** Returns the widget's label. */
|
|
getLabel: function()
|
|
{
|
|
var result = "";
|
|
var node = this._getChildXFormsNode("label");
|
|
|
|
if (node && node.firstChild !== null)
|
|
{
|
|
result = node.firstChild.nodeValue;
|
|
}
|
|
|
|
if (alfresco.constants.DEBUG)
|
|
{
|
|
result += " [" + this.id + "]";
|
|
}
|
|
return result;
|
|
},
|
|
|
|
/** Returns the widget's alert text. */
|
|
getAlert: function()
|
|
{
|
|
var result = "";
|
|
var node = this._getChildXFormsNode("alert");
|
|
|
|
if (node && node.firstChild !== null)
|
|
{
|
|
result = node.firstChild.nodeValue;
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
/** Returns the widget's alert text. */
|
|
getHint: function()
|
|
{
|
|
var result = null;
|
|
var node = this._getChildXFormsNode("hint");
|
|
|
|
if (node && node.firstChild !== null)
|
|
{
|
|
result = node.firstChild.nodeValue;
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
/** Makes the label red. */
|
|
showAlert: function()
|
|
{
|
|
if (!this.labelNode.hasClass("xformsItemLabelSubmitError"))
|
|
{
|
|
this.labelNode.addClass("xformsItemLabelSubmitError");
|
|
}
|
|
},
|
|
|
|
/** Restores the label to its original color. */
|
|
hideAlert: function()
|
|
{
|
|
if (this.labelNode.hasClass("xformsItemLabelSubmitError"))
|
|
{
|
|
this.labelNode.removeClass("xformsItemLabelSubmitError");
|
|
}
|
|
},
|
|
|
|
/** Returns the value of the appearance attribute for widget */
|
|
getAppearance: function()
|
|
{
|
|
var result = (this.xformsNode.getAttribute("appearance") ||
|
|
this.xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":appearance"));
|
|
return result == null || result.length == 0 ? null : result;
|
|
},
|
|
|
|
/** Updates the display of the widget. This is intended to be overridden. */
|
|
_updateDisplay: function(recursively)
|
|
{
|
|
},
|
|
|
|
/** Destroy the widget and any resources no longer needed. */
|
|
_destroy: function()
|
|
{
|
|
alfresco.log("destroying " + this.id);
|
|
},
|
|
|
|
/**
|
|
* Returns an array of RepeatIndexDatas corresponding to all enclosing repeats.
|
|
* The closest repeat will be at index 0.
|
|
*/
|
|
getRepeatIndices: function()
|
|
{
|
|
var result = [];
|
|
var w = this;
|
|
while (w.parentWidget)
|
|
{
|
|
if (w.parentWidget instanceof alfresco.xforms.Repeat)
|
|
{
|
|
result.push(new alfresco.xforms.RepeatIndexData(w.parentWidget,
|
|
w.parentWidget.getChildIndex(w) + 1));
|
|
}
|
|
w = w.parentWidget;
|
|
}
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
*/
|
|
getParentGroups: function(appearance)
|
|
{
|
|
var result = [];
|
|
var w = this;
|
|
while (w.parentWidget)
|
|
{
|
|
if (w.parentWidget instanceof alfresco.xforms.AbstractGroup)
|
|
{
|
|
if (appearance && w.parentWidget.getAppearance() == appearance)
|
|
{
|
|
result.push(w.parentWidget);
|
|
}
|
|
}
|
|
w = w.parentWidget;
|
|
}
|
|
return result;
|
|
}
|
|
});
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// widgets for atomic types
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/** The file picker widget which handles xforms widget xf:upload. */
|
|
alfresco.xforms.FilePicker = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget, params)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
this._selectableTypes = "selectable_types" in params ? params["selectable_types"].split(",") : null;
|
|
this._filterMimetypes = "filter_mimetypes" in params ? params["filter_mimetypes"].split(",") : [];
|
|
this._folderRestriction = "folder_restriction" in params ? params["folder_restriction"] : null;
|
|
this._configSearchName = "config_search_name" in params ? params["config_search_name"] : null;
|
|
this._layout = "layout" in params ? params["layout"] : null;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
this.domNode.addClass("xformsFilePicker");
|
|
attach_point.appendChild(this.domNode);
|
|
//XXXarielb support readonly and disabled
|
|
|
|
if (this._layout == "table")
|
|
{
|
|
this.widget = new alfresco.FilePickerWidgetTableLayout(this.id,
|
|
this.domNode,
|
|
this.getInitialValue(),
|
|
false,
|
|
this._filePicker_changeHandler.bindAsEventListener(this),
|
|
null /* cancel is ignored */,
|
|
this._filePicker_resizeHandler.bindAsEventListener(this),
|
|
this._selectableTypes,
|
|
this._filterMimetypes,
|
|
this._folderRestriction,
|
|
this._configSearchName);
|
|
}
|
|
else
|
|
{
|
|
this.widget = new alfresco.FilePickerWidget(this.id,
|
|
this.domNode,
|
|
this.getInitialValue(),
|
|
false,
|
|
this._filePicker_changeHandler.bindAsEventListener(this),
|
|
null /* cancel is ignored */,
|
|
this._filePicker_resizeHandler.bindAsEventListener(this),
|
|
this._selectableTypes,
|
|
this._filterMimetypes,
|
|
this._folderRestriction,
|
|
this._configSearchName);
|
|
}
|
|
this.widget.render();
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
return this.widget.getValue();
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
this.widget.setValue(value);
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_filePicker_changeHandler: function(fpw)
|
|
{
|
|
this._commitValueChange();
|
|
},
|
|
|
|
_filePicker_resizeHandler: function(fpw)
|
|
{
|
|
this.domContainer.style.height =
|
|
Math.max(fpw.node.offsetHeight +
|
|
this.domNode.parentNode.getStyle("margin-top").toInt() +
|
|
this.domNode.parentNode.getStyle("margin-bottom").toInt(),
|
|
20) + "px";
|
|
}
|
|
});
|
|
|
|
/** The textfield widget which handle xforms widget xf:input with any string or numerical type */
|
|
alfresco.xforms.TextField = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget, new Element("input", { type: "text" }));
|
|
this._maxLength = (_hasAttribute(this.xformsNode, alfresco.xforms.constants.ALFRESCO_PREFIX + ":maxLength")
|
|
? Number(this.xformsNode.getAttribute(alfresco.xforms.constants.ALFRESCO_PREFIX + ":maxLength"))
|
|
: -1);
|
|
this._length = (_hasAttribute(this.xformsNode, alfresco.xforms.constants.ALFRESCO_PREFIX + ":length")
|
|
? Number(this.xformsNode.getAttribute(alfresco.xforms.constants.ALFRESCO_PREFIX + ":length"))
|
|
: -1);
|
|
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
var initial_value = this.getInitialValue() || "";
|
|
attach_point.appendChild(this.domNode);
|
|
|
|
this.widget = this.domNode;
|
|
this.widget.setAttribute("value", initial_value);
|
|
if (this._maxLength >= 0)
|
|
{
|
|
this.widget.setAttribute("maxlength", this._maxLength);
|
|
}
|
|
|
|
if (this._length >= 0)
|
|
{
|
|
this.widget.style.maxWidth = "100%";
|
|
this.widget.setAttribute("size", this._length);
|
|
}
|
|
else if (this.getAppearance() == "full")
|
|
{
|
|
var borderWidth = (this.widget.offsetWidth - this.widget.clientWidth);
|
|
var marginRight = 2;
|
|
this.widget.style.marginRight = marginRight + "px";
|
|
if (attach_point.offsetWidth == 0)
|
|
{
|
|
this.widget.style.width = "100%";
|
|
}
|
|
else
|
|
{
|
|
this.widget.style.width = (((attach_point.offsetWidth - borderWidth - marginRight) / attach_point.offsetWidth) * 100) + "%";
|
|
}
|
|
this.widget.style.minWidth = "50px";
|
|
}
|
|
|
|
if (this.isReadonly())
|
|
{
|
|
this.widget.setAttribute("readonly", this.isReadonly());
|
|
this.widget.setAttribute("disabled", this.isReadonly());
|
|
}
|
|
else
|
|
{
|
|
this.widget.onblur = this._widget_changeHandler.bindAsEventListener(this);
|
|
}
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
this.widget.value = value;
|
|
}
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
return (this.widget.value != null && this.widget.value.length == 0
|
|
? null
|
|
: this.widget.value);
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_widget_changeHandler: function(event)
|
|
{
|
|
this._commitValueChange();
|
|
}
|
|
});
|
|
|
|
/** The number range widget which handle xforms widget xf:range with any numerical type */
|
|
alfresco.xforms.NumericalRange = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
dojo.require("dojo.widget.Slider");
|
|
this._fractionDigits = (_hasAttribute(this.xformsNode, alfresco.xforms.constants.ALFRESCO_PREFIX + ":fractionDigits")
|
|
? Number(this.xformsNode.getAttribute(alfresco.xforms.constants.ALFRESCO_PREFIX + ":fractionDigits"))
|
|
: -1);
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
var initial_value = this.getInitialValue() || "";
|
|
attach_point.appendChild(this.domNode);
|
|
var sliderDiv = document.createElement("div");
|
|
sliderDiv.style.fontWeight = "bold";
|
|
sliderDiv.style.marginBottom = "5px";
|
|
this.domNode.appendChild(sliderDiv);
|
|
|
|
var minimum = Number(this.xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":start"));
|
|
var maximum = Number(this.xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":end"));
|
|
var snapValues = 0;
|
|
if (this._fractionDigits == 0)
|
|
{
|
|
snapValues = maximum - minimum + 1;
|
|
}
|
|
sliderDiv.appendChild(document.createTextNode(minimum));
|
|
|
|
var sliderWidgetDiv = document.createElement("div");
|
|
sliderDiv.appendChild(sliderWidgetDiv);
|
|
this.widget = dojo.widget.createWidget("SliderHorizontal",
|
|
{
|
|
initialValue: initial_value,
|
|
minimumX: minimum,
|
|
maximumX: maximum,
|
|
showButtons: false,
|
|
activeDrag: false,
|
|
snapValues: snapValues
|
|
},
|
|
sliderWidgetDiv);
|
|
sliderDiv.appendChild(document.createTextNode(maximum));
|
|
|
|
this.currentValueDiv = document.createElement("div");
|
|
this.domNode.appendChild(this.currentValueDiv);
|
|
this.currentValueDiv.appendChild(document.createTextNode("Value: " + initial_value));
|
|
|
|
dojo.event.connect(this.widget,
|
|
"onValueChanged",
|
|
this,
|
|
this._hSlider_valueChangedHandler);
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
this.widget.setValue(value);
|
|
}
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
return this.widget.getValue();
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_hSlider_valueChangedHandler: function(value)
|
|
{
|
|
if (this._fractionDigits >= 0)
|
|
{
|
|
value = Math.round(value * Math.pow(10, this._fractionDigits)) / Math.pow(10, this._fractionDigits);
|
|
}
|
|
this.currentValueDiv.replaceChild(document.createTextNode("Value: " + value),
|
|
this.currentValueDiv.firstChild);
|
|
if (!this.widget._isDragInProgress)
|
|
{
|
|
this._commitValueChange();
|
|
}
|
|
}
|
|
});
|
|
|
|
/** The text area widget handles xforms widget xf:textarea with appearance minimal */
|
|
alfresco.xforms.PlainTextEditor = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget, new Element("textarea"));
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
attach_point.appendChild(this.domNode);
|
|
this.domNode.addClass("xformsTextArea");
|
|
var initialValue = this.getInitialValue() || "";
|
|
this.widget = this.domNode;
|
|
this.widget.appendChild(document.createTextNode(initialValue));
|
|
if (this.isReadonly())
|
|
{
|
|
this.widget.setAttribute("readonly", this.isReadonly());
|
|
}
|
|
var borderWidth = (this.widget.offsetWidth - this.widget.clientWidth);
|
|
var marginRight = 2;
|
|
this.widget.style.marginRight = marginRight + "px";
|
|
this.widget.style.width = (((attach_point.offsetWidth - borderWidth - marginRight) / attach_point.offsetWidth) * 100) + "%";
|
|
this.widget.onchange =this._textarea_changeHandler.bindAsEventListener(this);
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
this.widget.value = value;
|
|
}
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
return this.widget.value;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_textarea_changeHandler: function(event)
|
|
{
|
|
this._commitValueChange();
|
|
}
|
|
});
|
|
|
|
/** The textfield widget which handle xforms widget xf:textarea. with appearance full or compact */
|
|
alfresco.xforms.RichTextEditor = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget, params)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
this._focused = false;
|
|
this._params = params;
|
|
this._oldValue = null;
|
|
this._created = false;
|
|
if (!document.getElementById('xformsRichTextEditorHoverLayer'))
|
|
{
|
|
alfresco.xforms.RichTextEditor.clickMask = new Element("div");
|
|
alfresco.xforms.RichTextEditor.clickMask.addClass("xformsRichTextEditorHoverLayer");
|
|
alfresco.xforms.RichTextEditor.clickMask.setText(alfresco.resources["click_to_edit"]);
|
|
alfresco.xforms.RichTextEditor.clickMask.id = 'xformsRichTextEditorHoverLayer';
|
|
alfresco.xforms.RichTextEditor.clickMask.style.display='none';
|
|
document.body.appendChild(alfresco.xforms.RichTextEditor.clickMask);
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_removeTinyMCE: function()
|
|
{
|
|
var value = this.getValue(); //tinyMCE.getContent(this.id);
|
|
if (value != this._oldValue)
|
|
{
|
|
alfresco.log("commitValueChange from _removeTinyMCE [" + value + "]");
|
|
this._commitValueChange(value);
|
|
this._oldValue = value;
|
|
}
|
|
tinyMCE.get(this.widget.id).hide();
|
|
this._focused = false;
|
|
},
|
|
|
|
_createTinyMCE:function()
|
|
{
|
|
for (var i in alfresco.constants.TINY_MCE_DEFAULT_SETTINGS)
|
|
{
|
|
if (!(i in this._params))
|
|
{
|
|
this._params[i] = alfresco.constants.TINY_MCE_DEFAULT_SETTINGS[i];
|
|
}
|
|
}
|
|
|
|
for (var i in this._params)
|
|
{
|
|
if (i in tinyMCE.settings)
|
|
{
|
|
alfresco.log("setting tinyMCE.settings[" + i + "] = " + this._params[i]);
|
|
tinyMCE.settings[i] = this._params[i];
|
|
}
|
|
}
|
|
tinyMCE.settings.height = (this._params["height"]>0) ? parseInt(this._params["height"]) : this.widget.style.height;
|
|
tinyMCE.settings.width = (this._params["width"]>0) ? parseInt(this._params["width"]) : this.widget.style.width;
|
|
|
|
tinyMCE.settings.auto_focus = this.widget.id;
|
|
tinyMCE.execCommand("mceAddControl", false, this.widget.id)
|
|
var editorDocument = tinyMCE.get(this.widget.id).getDoc();
|
|
editorDocument.widget = this;
|
|
tinymce.dom.Event.add(editorDocument,window.ie ? "beforedeactivate" : "blur",
|
|
this._tinyMCE_blurHandler);
|
|
tinymce.dom.Event.add(editorDocument, "focus", this._tinyMCE_focusHandler);
|
|
this._created = true;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
attach_point.appendChild(this.domNode);
|
|
this.domNode.addClass("xformsTextArea");
|
|
if (this._params.height)
|
|
{
|
|
this.domNode.setStyle("height", parseInt(this._params["height"]) + "px");
|
|
}
|
|
this.widget = new Element("div");
|
|
this.domNode.appendChild(this.widget);
|
|
this.widget.addClass("xformsTextArea");
|
|
|
|
if (this._params["height"])
|
|
{
|
|
this.widget.setStyle("height", parseInt(this._params["height"]) + "px");
|
|
}
|
|
this.widget.style.border = "2px inset #f0f0f0";
|
|
this.widget.style.marginRight = "2px";
|
|
this.widget.style.overflow = "auto";
|
|
this._oldValue = this.getInitialValue() || "";
|
|
this.widget.innerHTML = this._oldValue;
|
|
this.widget.id = this.id+'-editorWidget';
|
|
$each(this.widget.getElementsByTagName("img"),
|
|
function(img, index)
|
|
{
|
|
|
|
var href = img.getAttribute("src");
|
|
//Fix for ETHREEOH-1211
|
|
if (navigator.appName == "Microsoft Internet Explorer" || tinyMCE.isMSIE)
|
|
{
|
|
var server = document.location.protocol + "//" + document.location.host;
|
|
if (href.startsWith(server))
|
|
{
|
|
href = href.substring(server.length);
|
|
}
|
|
}
|
|
|
|
if (href && href.match("^/"))
|
|
{
|
|
img.setAttribute("src", alfresco.constants.AVM_WEBAPP_URL + href);
|
|
}
|
|
});
|
|
|
|
if (!this.isReadonly())
|
|
{
|
|
this.domNode.onmouseover = this._div_mouseoverHandler.bindAsEventListener(this);
|
|
}
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (value != this._oldValue || forceCommit)
|
|
{
|
|
if (alfresco.xforms.RichTextEditor.currentInstance == this)
|
|
{
|
|
tinyMCE.selectedInstance = tinyMCE.get(this.id);
|
|
try
|
|
{
|
|
tinyMCE.activeEditor.setContent(value);
|
|
}
|
|
catch (e)
|
|
{
|
|
//XXXarielb figure this out - getting intermittent errors in IE.
|
|
alfresco.log(e);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.widget.innerHTML = value;
|
|
}
|
|
}
|
|
this.parent(value, forceCommit);
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
var result = (alfresco.xforms.RichTextEditor.currentInstance == this
|
|
? tinyMCE.get(this.widget.id).getContent()
|
|
: this.widget.innerHTML);
|
|
result = result.replace(new RegExp(alfresco.constants.AVM_WEBAPP_URL, "g"), "");
|
|
return result;
|
|
},
|
|
|
|
setReadonly: function(readonly)
|
|
{
|
|
this.parent(readonly);
|
|
if (readonly && alfresco.xforms.RichTextEditor.currentInstance == this)
|
|
{
|
|
this._removeTinyMCE();
|
|
}
|
|
},
|
|
|
|
_destroy: function()
|
|
{
|
|
this.parent();
|
|
if (!this.isReadonly())
|
|
{
|
|
alfresco.log("removing mce control " + this.id);
|
|
// tinyMCE.removeMCEControl(this.id);
|
|
tinyMCE.execCommand('mceRemoveControl', false, this.widget.id);
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_tinyMCE_blurHandler: function(event)
|
|
{
|
|
if (event.type == "beforedeactivate")
|
|
{
|
|
event.target = event.srcElement.ownerDocument;
|
|
}
|
|
var widget = event.target.widget;
|
|
var value = widget.getValue();
|
|
if (value != widget._oldValue)
|
|
{
|
|
alfresco.log("commitValueChange from _tinyMCE_blurHandler [" + value + "]");
|
|
widget._commitValueChange(value);
|
|
widget._oldValue = value;
|
|
}
|
|
widget._focused = false;
|
|
},
|
|
|
|
_tinyMCE_focusHandler: function(event)
|
|
{
|
|
var widget = event.target.widget;
|
|
var repeatIndices = widget.getRepeatIndices();
|
|
if (repeatIndices.length != 0 && !widget._focused)
|
|
{
|
|
var r = repeatIndices[repeatIndices.length - 1].repeat;
|
|
var p = widget;
|
|
while (p && p.parentWidget != r)
|
|
{
|
|
if (p.parentWidget instanceof alfresco.xforms.Repeat)
|
|
{
|
|
throw new Error("unexpected parent repeat " + p.parentWidget.id);
|
|
}
|
|
p = p.parentWidget;
|
|
}
|
|
if (!p)
|
|
{
|
|
throw new Error("unable to find parent repeat " + r.id +
|
|
" of " + widget.id);
|
|
}
|
|
repeatIndices[repeatIndices.length - 1].repeat.setFocusedChild(p);
|
|
}
|
|
widget._focused = true;
|
|
},
|
|
|
|
_div_mouseoverHandler: function(event)
|
|
{
|
|
var target = event.target || event.srcElement;
|
|
if (target)
|
|
{
|
|
if (target.className.indexOf('xformsTextArea')==-1)
|
|
{
|
|
do
|
|
{
|
|
target=target.parentNode;
|
|
}
|
|
while(target && target.className!='xformsTextArea');
|
|
}
|
|
if (target && target.className=='xformsTextArea' && (alfresco.xforms.RichTextEditor.currentInstance != this))
|
|
{
|
|
alfresco.xforms.RichTextEditor.clickMask.style.display='block';
|
|
alfresco.xforms.RichTextEditor.clickMask.style.top=target.getTop()+'px';
|
|
alfresco.xforms.RichTextEditor.clickMask.style.left=target.getLeft()+'px';
|
|
alfresco.xforms.RichTextEditor.clickMask.style.width=target.offsetWidth+'px';
|
|
alfresco.xforms.RichTextEditor.clickMask.style.height=target.offsetHeight+'px';
|
|
alfresco.xforms.RichTextEditor.clickMask.style.lineHeight = alfresco.xforms.RichTextEditor.clickMask.offsetHeight + "px";
|
|
alfresco.xforms.RichTextEditor.clickMask.setOpacity(.8);
|
|
|
|
alfresco.xforms.RichTextEditor.clickMask.onclick = this._hoverLayer_clickHandler.bindAsEventListener(this);
|
|
alfresco.xforms.RichTextEditor.clickMask.onmouseout = this._hoverLayer_mouseoutHandler.bindAsEventListener(this);
|
|
|
|
}
|
|
}
|
|
},
|
|
|
|
_hoverLayer_mouseoutHandler: function(event)
|
|
{
|
|
var relatedTarget = (event.relatedTarget) ? event.relatedTarget : event.toElement;
|
|
if (relatedTarget && relatedTarget.id!=alfresco.xforms.RichTextEditor.clickMask.id)
|
|
{
|
|
alfresco.xforms.RichTextEditor.clickMask.style.display='none'
|
|
document.body.appendChild(alfresco.xforms.RichTextEditor.clickMask);
|
|
}
|
|
},
|
|
|
|
_hoverLayer_clickHandler: function(event)
|
|
{
|
|
alfresco.xforms.RichTextEditor.clickMask.style.display='none'
|
|
document.body.appendChild(alfresco.xforms.RichTextEditor.clickMask);
|
|
if (alfresco.xforms.RichTextEditor.currentInstance &&
|
|
alfresco.xforms.RichTextEditor.currentInstance != this)
|
|
{
|
|
alfresco.xforms.RichTextEditor.currentInstance._removeTinyMCE();
|
|
}
|
|
if (this._created===false)
|
|
{
|
|
this._createTinyMCE();
|
|
}
|
|
else
|
|
{
|
|
tinyMCE.get(this.widget.id).show();
|
|
}
|
|
alfresco.xforms.RichTextEditor.currentInstance = this;
|
|
alfresco.xforms.RichTextEditor.clickMask.style.display='none'
|
|
document.body.appendChild(alfresco.xforms.RichTextEditor.clickMask);
|
|
}
|
|
});
|
|
|
|
/** The currently rendered rich text editor instance */
|
|
alfresco.xforms.RichTextEditor.currentInstance = null;
|
|
|
|
/**
|
|
* Reads the widget configuration to determine which plugins will
|
|
* be needed by tinymce. All plugins must be loaded into tinymce at
|
|
* startup so they must be accumulated in advance.
|
|
*/
|
|
alfresco.xforms.RichTextEditor.determineNecessaryTinyMCEPlugins = function(config)
|
|
{
|
|
var result = [];
|
|
for (var widget in config)
|
|
{
|
|
for (var schemaType in config[widget])
|
|
{
|
|
for (var appearance in config[widget][schemaType])
|
|
{
|
|
if (config[widget][schemaType][appearance].className == "alfresco.xforms.RichTextEditor" &&
|
|
config[widget][schemaType][appearance].params &&
|
|
config[widget][schemaType][appearance].params.plugins)
|
|
{
|
|
alfresco.log("found plugins definition " + config[widget][schemaType][appearance].params.plugins +
|
|
" for text editor at config[" + widget + "][" + schemaType + "][" + appearance + "]");
|
|
var plugins = config[widget][schemaType][appearance].params.plugins.split(",");
|
|
for (var p = 0; p < plugins.length; p++)
|
|
{
|
|
if (result.indexOf(plugins[p]) < 0)
|
|
{
|
|
result.push(plugins[p]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result.join(",");
|
|
}
|
|
|
|
/** Base class for all select widgets. */
|
|
alfresco.xforms.AbstractSelectWidget = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget, domNode)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget, domNode);
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Returns the possible item values for the select control as an array
|
|
* of anonymous objects with properties id, label, value, and valid.
|
|
*/
|
|
_getItemValues: function()
|
|
{
|
|
var binding = this.xform.getBinding(this.xformsNode);
|
|
var values = _getElementsByTagNameNS(this.xformsNode,
|
|
alfresco.xforms.constants.XFORMS_NS,
|
|
alfresco.xforms.constants.XFORMS_PREFIX,
|
|
"item");
|
|
var result = [];
|
|
for (var i = 0; i < values.length; i++)
|
|
{
|
|
var label = _getElementsByTagNameNS(values[i],
|
|
alfresco.xforms.constants.XFORMS_NS,
|
|
alfresco.xforms.constants.XFORMS_PREFIX,
|
|
"label")[0];
|
|
label = label.firstChild === null ? "" : label.firstChild.nodeValue;
|
|
var value = _getElementsByTagNameNS(values[i],
|
|
alfresco.xforms.constants.XFORMS_NS,
|
|
alfresco.xforms.constants.XFORMS_PREFIX,
|
|
"value")[0];
|
|
var valueText = value.firstChild === null ? "" : value.firstChild.nodeValue;
|
|
var itemId = value.getAttribute("id");
|
|
var valid = true;
|
|
if (binding.constraint)
|
|
{
|
|
if (!window.ie)
|
|
{
|
|
valid = _evaluateXPath(binding.constraint, value, XPathResult.BOOLEAN_TYPE);
|
|
if (alfresco.constants.DEBUG)
|
|
{
|
|
alfresco.log("evaludated constraint " + binding.constraint +
|
|
" on " + value + " to " + valid);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
valid = !(valueText == label && valueText.match(/^\[.+\]$/));
|
|
}
|
|
}
|
|
result.push({
|
|
id: itemId,
|
|
label: valid ? label : "",
|
|
value: valid ? valueText : "_invalid_value_",
|
|
valid: valid
|
|
});
|
|
|
|
if (alfresco.constants.DEBUG)
|
|
{
|
|
alfresco.log("values["+ i + "] = {id: " + result[i].id +
|
|
",label: " + result[i].label + ",value: " + result[i].value +
|
|
",valid: " + result[i].valid + "}");
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Handles xforms widget xf:select. Produces either a multiselect list or a set of
|
|
* checkboxes depending on the number of inputs.
|
|
*/
|
|
alfresco.xforms.CheckboxSelect = alfresco.xforms.AbstractSelectWidget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
var values = this._getItemValues();
|
|
var initial_value = this.getInitialValue();
|
|
initial_value = initial_value ? initial_value.split(' ') : [];
|
|
this._selectedValues = [];
|
|
this.widget = this.domNode;
|
|
attach_point.appendChild(this.domNode);
|
|
for (var i = 0; i < values.length; i++)
|
|
{
|
|
var checkboxDiv = document.createElement("div");
|
|
checkboxDiv.style.lineHeight = "16px";
|
|
this.widget.appendChild(checkboxDiv);
|
|
|
|
var checkbox = new Element("input");
|
|
checkbox.setAttribute("id", this.id + "_" + i + "-widget");
|
|
checkbox.setAttribute("name", this.id + "_" + i + "-widget");
|
|
checkbox.setAttribute("type", "checkbox");
|
|
checkbox.setAttribute("value", values[i].value);
|
|
checkboxDiv.appendChild(checkbox);
|
|
if (initial_value.indexOf(values[i].value) != -1)
|
|
{
|
|
this._selectedValues.push(values[i].value);
|
|
checkbox.checked = true;
|
|
}
|
|
checkboxDiv.appendChild(document.createTextNode(values[i].label));
|
|
checkbox.onclick = this._checkbox_clickHandler.bindAsEventListener(this);
|
|
}
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
this._selectedValues = value.split(' ');
|
|
var checkboxes = this.widget.getElementsByTagName("input");
|
|
for (var i = 0; i < checkboxes.length; i++)
|
|
{
|
|
checkboxes[i].checked =
|
|
this._selectedValues.indexOf(checkboxes[i].getAttribute("value")) != -1;
|
|
}
|
|
}
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
return this._selectedValues.length == 0 ? null : this._selectedValues.join(" ");
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_checkbox_clickHandler: function(event)
|
|
{
|
|
this._selectedValues = [];
|
|
var all_checkboxes = this.widget.getElementsByTagName("input");
|
|
for (var i = 0; i < all_checkboxes.length; i++)
|
|
{
|
|
if (all_checkboxes[i] && all_checkboxes[i].checked)
|
|
{
|
|
this._selectedValues.push(all_checkboxes[i].getAttribute("value"));
|
|
}
|
|
}
|
|
this._commitValueChange();
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Handles xforms widget xf:select. Produces either a multiselect list or a set of
|
|
* checkboxes depending on the number of inputs.
|
|
*/
|
|
alfresco.xforms.ListSelect = alfresco.xforms.AbstractSelectWidget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget, new Element("select"));
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
var values = this._getItemValues();
|
|
var initial_value = this.getInitialValue();
|
|
initial_value = initial_value ? initial_value.split(' ') : [];
|
|
this._selectedValues = [];
|
|
attach_point.appendChild(this.domNode);
|
|
this.widget = this.domNode;
|
|
this.widget.setAttribute("multiple", true);
|
|
attach_point.appendChild(this.widget);
|
|
for (var i = 0; i < values.length; i++)
|
|
{
|
|
var option = document.createElement("option");
|
|
option.appendChild(document.createTextNode(values[i].label));
|
|
option.setAttribute("value", values[i].value);
|
|
if (initial_value.indexOf(values[i].value) != -1)
|
|
{
|
|
this._selectedValues.push(values[i].value);
|
|
option.selected = true;
|
|
}
|
|
this.widget.appendChild(option);
|
|
}
|
|
this.widget.onblur = this._list_changeHandler.bindAsEventListener(this);
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
this._selectedValues = value.split(' ');
|
|
var options = this.widget.getElementsByTagName("option");
|
|
for (var i = 0; i < options.length; i++)
|
|
{
|
|
options[i].selected =
|
|
this._selectedValues.indexOf(options[i].getAttribute("value")) != -1;
|
|
}
|
|
}
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
return this._selectedValues.length == 0 ? null : this._selectedValues.join(" ");
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_list_changeHandler: function(event)
|
|
{
|
|
var target;
|
|
|
|
if (window.ie)
|
|
{
|
|
target = window.event.srcElement;
|
|
}
|
|
else
|
|
{
|
|
target = event.target;
|
|
}
|
|
|
|
this._selectedValues = [];
|
|
for (var i = 0; i < target.options.length; i++)
|
|
{
|
|
if (target.options[i].selected)
|
|
{
|
|
this._selectedValues.push(target.options[i].getAttribute("value"));
|
|
}
|
|
}
|
|
this._commitValueChange();
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Handles xforms widget xf:select1. Produces either a combobox or a set of
|
|
* radios depending on the number of inputs.
|
|
*/
|
|
alfresco.xforms.RadioSelect1 = alfresco.xforms.AbstractSelectWidget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
var values = this._getItemValues();
|
|
var initial_value = this.getInitialValue();
|
|
this.widget = this.domNode;
|
|
attach_point.appendChild(this.domNode);
|
|
for (var i = 0; i < values.length; i++)
|
|
{
|
|
if (!values[i].valid)
|
|
{
|
|
// always skip the invalid values for radios
|
|
continue;
|
|
}
|
|
|
|
var radio_div = document.createElement("div");
|
|
radio_div.style.lineHeight = "16px";
|
|
this.widget.appendChild(radio_div);
|
|
var radio = new Element("input");
|
|
radio.setAttribute("id", this.id + "-widget");
|
|
radio.setAttribute("name", this.id + "-widget");
|
|
radio.setAttribute("type", "radio");
|
|
radio_div.appendChild(radio);
|
|
radio_div.appendChild(document.createTextNode(values[i].label));
|
|
|
|
radio.setAttribute("value", values[i].value);
|
|
if (values[i].value == initial_value)
|
|
{
|
|
this._selectedValue = initial_value;
|
|
radio.checked = true;
|
|
}
|
|
if (this.isReadonly())
|
|
{
|
|
radio.setAttribute("disabled", true);
|
|
}
|
|
radio.onclick = this._radio_clickHandler.bindAsEventListener(this);
|
|
}
|
|
this.widget.style.height = this.widget.offsetHeight + "px";
|
|
},
|
|
|
|
/** */
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
this._selectedValue = value;
|
|
var radios = this.widget.getElementsByTagName("input");
|
|
for (var i = 0; i < radios.length; i++)
|
|
{
|
|
radios[i].checked = radios[i].getAttribute("value") == this._selectedValue;
|
|
}
|
|
}
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
return this._selectedValue;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_radio_clickHandler: function(event)
|
|
{
|
|
var target;
|
|
|
|
if (window.ie)
|
|
{
|
|
target = window.event.srcElement;
|
|
}
|
|
else
|
|
{
|
|
target = event.target;
|
|
}
|
|
|
|
if (!target.checked)
|
|
{
|
|
var all_radios = this.widget.getElementsByTagName("input");
|
|
for (var i = 0; i < all_radios.length; i++)
|
|
{
|
|
if (all_radios[i].name == target.name)
|
|
{
|
|
all_radios[i].checked = target == all_radios[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
this._selectedValue = target.value;
|
|
this._commitValueChange();
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Handles xforms widget xf:select1. Produces either a combobox or a set of
|
|
* radios depending on the number of inputs.
|
|
*/
|
|
alfresco.xforms.ComboboxSelect1 = alfresco.xforms.AbstractSelectWidget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget, new Element("select"));
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
var values = this._getItemValues();
|
|
var initial_value = this.getInitialValue();
|
|
this.domNode = new Element("select");
|
|
attach_point.appendChild(this.domNode);
|
|
this.widget = this.domNode;
|
|
for (var i = 0; i < values.length; i++)
|
|
{
|
|
if (initial_value && !values[i].valid)
|
|
{
|
|
// skip the invalid value if we have a default value
|
|
continue;
|
|
}
|
|
var option = new Element("option");
|
|
this.widget.appendChild(option);
|
|
option.appendChild(document.createTextNode(values[i].label));
|
|
option.setAttribute("value", values[i].value);
|
|
if (values[i].value == initial_value)
|
|
{
|
|
this._selectedValue = initial_value;
|
|
option.selected = true;
|
|
}
|
|
|
|
if (this.isReadonly())
|
|
{
|
|
this.widget.setAttribute("disabled", true);
|
|
}
|
|
}
|
|
this.widget.onchange = this._combobox_changeHandler.bindAsEventListener(this);
|
|
},
|
|
|
|
/** */
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
this._selectedValue = value;
|
|
var options = this.widget.getElementsByTagName("option");
|
|
for (var i = 0; i < options.length; i++)
|
|
{
|
|
options[i].selected = options[i].getAttribute("value") == this._selectedValue;
|
|
}
|
|
}
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
return this._selectedValue;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_combobox_changeHandler: function(event)
|
|
{
|
|
var target;
|
|
|
|
if (window.ie)
|
|
{
|
|
target = window.event.srcElement;
|
|
}
|
|
else
|
|
{
|
|
target = event.target;
|
|
}
|
|
|
|
this._selectedValue = target.options[target.selectedIndex].value;
|
|
this._commitValueChange();
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Handles xforms widget xf:select1 with a type of boolean.
|
|
*/
|
|
alfresco.xforms.Checkbox = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform,
|
|
xformsNode, parentWidget,
|
|
new Element("input", { type: "checkbox" }));
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
var initial_value = this.getInitialValue() == "true";
|
|
attach_point.appendChild(this.domNode);
|
|
this.widget = this.domNode;
|
|
|
|
if (initial_value)
|
|
{
|
|
this.widget.setAttribute("checked", true);
|
|
}
|
|
if (this.isReadonly())
|
|
{
|
|
this.widget.setAttribute("disabled", true);
|
|
}
|
|
this.widget.onclick = this._checkbox_clickHandler.bindAsEventListener(this);
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
this.widget.checked = value == "true";
|
|
}
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
return this.widget.checked;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_checkbox_clickHandler: function(event)
|
|
{
|
|
this._commitValueChange();
|
|
}
|
|
});
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// widgets for date types
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/** The date picker widget which handles xforms widget xf:input with type xf:date */
|
|
alfresco.xforms.DatePicker = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
this._minInclusive = (_hasAttribute(this.xformsNode, alfresco.xforms.constants.ALFRESCO_PREFIX + ":minInclusive")
|
|
? this.xformsNode.getAttribute(alfresco.xforms.constants.ALFRESCO_PREFIX + ":minInclusive")
|
|
: null);
|
|
this._maxInclusive = (_hasAttribute(this.xformsNode, alfresco.xforms.constants.ALFRESCO_PREFIX + ":maxInclusive")
|
|
? this.xformsNode.getAttribute(alfresco.xforms.constants.ALFRESCO_PREFIX + ":maxInclusive")
|
|
: null);
|
|
|
|
dojo.require("dojo.date.format");
|
|
// XXXarielb - change to a static
|
|
this._noValueSet = (alfresco.resources["eg"] + " " +
|
|
dojo.date.format(new Date(),
|
|
{datePattern: alfresco.xforms.constants.DATE_FORMAT,
|
|
selector: 'dateOnly'}));
|
|
},
|
|
|
|
_createPicker: function()
|
|
{
|
|
dojo.require("dojo.widget.DatePicker");
|
|
var datePickerDiv = document.createElement("div");
|
|
this.domNode.parentNode.appendChild(datePickerDiv);
|
|
|
|
var dp_initial_value = this.getValue() || null; //dojo.date.toRfc3339(new Date());
|
|
var datePickerProperties = { value: dp_initial_value };
|
|
if (this._minInclusive)
|
|
{
|
|
datePickerProperties.startDate = this._minInclusive;
|
|
}
|
|
if (this._maxInclusive)
|
|
{
|
|
datePickerProperties.endDate = this._maxInclusive;
|
|
}
|
|
|
|
this.widget.picker = dojo.widget.createWidget("DatePicker",
|
|
datePickerProperties,
|
|
datePickerDiv);
|
|
this.domContainer.style.height =
|
|
Math.max(this.widget.picker.domNode.offsetHeight +
|
|
this.widget.offsetHeight +
|
|
this.domNode.parentNode.getStyle("margin-top").toInt() +
|
|
this.domNode.parentNode.getStyle("margin-bottom").toInt(),
|
|
20) + "px";
|
|
|
|
dojo.event.connect(this.widget.picker,
|
|
"onValueChanged",
|
|
this,
|
|
this._datePicker_valueChangedHandler);
|
|
},
|
|
|
|
_destroyPicker: function()
|
|
{
|
|
if (this.widget.picker)
|
|
{
|
|
this.domNode.parentNode.removeChild(this.widget.picker.domNode);
|
|
this.widget.picker = null;
|
|
this.domContainer.style.height =
|
|
Math.max(this.widget.offsetHeight +
|
|
this.domNode.parentNode.getStyle("margin-bottom").toInt() +
|
|
this.domNode.parentNode.getStyle("margin-top").toInt(),
|
|
20) + "px";
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
var initial_value = this.getInitialValue();
|
|
attach_point.appendChild(this.domNode);
|
|
this.widget = new Element("input", { "id": this.id + "-widget", "type": "text"});
|
|
if (initial_value)
|
|
{
|
|
var jsDate = dojo.date.fromRfc3339(initial_value);
|
|
this.widget.setAttribute("value",
|
|
dojo.date.format(jsDate,
|
|
{datePattern: alfresco.xforms.constants.DATE_FORMAT,
|
|
selector: 'dateOnly'}));
|
|
}
|
|
else
|
|
{
|
|
this.widget.setAttribute("value", this._noValueSet);
|
|
this.widget.addClass("xformsGhostText");
|
|
}
|
|
if (this.isReadonly())
|
|
{
|
|
this.widget.setAttribute("disabled", true);
|
|
}
|
|
this.domNode.appendChild(this.widget);
|
|
|
|
var expandoImage = new Element("img");
|
|
expandoImage.setAttribute("src", alfresco.constants.WEBAPP_CONTEXT + "/images/icons/action.gif");
|
|
expandoImage.align = "absmiddle";
|
|
expandoImage.style.margin = "0px 5px";
|
|
|
|
this.domNode.appendChild(expandoImage);
|
|
|
|
if (!this.isReadonly())
|
|
{
|
|
expandoImage.onclick = this._expando_clickHandler.bindAsEventListener(this);
|
|
this.widget.onfocus = this._dateTextBox_focusHandler.bindAsEventListener(this);
|
|
this.widget.onchange = this._dateTextBox_changeHandler.bindAsEventListener(this);
|
|
}
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
var jsDate = dojo.date.fromRfc3339(value);
|
|
this.widget.value = dojo.date.format(jsDate,
|
|
{datePattern: alfresco.xforms.constants.DATE_FORMAT,
|
|
selector: 'dateOnly'});
|
|
this.widget.removeClass("xformsGhostText");
|
|
}
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
if (this.widget.value == null ||
|
|
this.widget.value.length == 0 ||
|
|
this.widget.value == this._noValueSet)
|
|
{
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
var jsDate = dojo.date.parse(this.widget.value,
|
|
{datePattern: alfresco.xforms.constants.DATE_FORMAT,
|
|
selector: 'dateOnly'});
|
|
return dojo.date.toRfc3339(jsDate, "dateOnly");
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_dateTextBox_focusHandler: function(event)
|
|
{
|
|
this._destroyPicker();
|
|
},
|
|
|
|
_dateTextBox_changeHandler: function(event)
|
|
{
|
|
this._commitValueChange();
|
|
},
|
|
|
|
_datePicker_valueChangedHandler: function(date)
|
|
{
|
|
var rfcDate = dojo.date.toRfc3339(date, "dateOnly");
|
|
this._destroyPicker();
|
|
this.setValue(rfcDate);
|
|
this._commitValueChange();
|
|
},
|
|
|
|
_expando_clickHandler: function()
|
|
{
|
|
if (this.widget.picker)
|
|
{
|
|
this._destroyPicker();
|
|
}
|
|
else
|
|
{
|
|
this._createPicker();
|
|
}
|
|
}
|
|
});
|
|
|
|
/** The date picker widget which handles xforms widget xf:input with type xf:date */
|
|
alfresco.xforms.TimePicker = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
dojo.require("dojo.date.format");
|
|
this._noValueSet = (alfresco.resources["eg"] + " " +
|
|
dojo.date.format(new Date(),
|
|
{timePattern: alfresco.xforms.constants.TIME_FORMAT,
|
|
selector: "timeOnly"}));
|
|
this._xformsFormat = new Array("HH:mm:ss.S", "HH:mm:ss");
|
|
},
|
|
|
|
_parseTime: function(timeValue)
|
|
{
|
|
var resDate = null;
|
|
for (i = 0; i < this._xformsFormat.length; i++)
|
|
{
|
|
resDate = dojo.date.parse(timeValue, {timePattern: this._xformsFormat[i],
|
|
selector: "timeOnly"});
|
|
if (resDate != null)
|
|
{
|
|
return resDate;
|
|
}
|
|
}
|
|
return resDate;
|
|
},
|
|
|
|
/** */
|
|
_createPicker: function()
|
|
{
|
|
dojo.require("dojo.widget.TimePicker");
|
|
var timePickerDiv = document.createElement("div");
|
|
this.domNode.appendChild(timePickerDiv);
|
|
var jsDate = (this.getValue()
|
|
? this._parseTime(this.getValue())
|
|
: new Date());
|
|
this.widget.picker = dojo.widget.createWidget("TimePicker",
|
|
{
|
|
value: jsDate
|
|
},
|
|
timePickerDiv);
|
|
this.widget.picker.anyTimeContainerNode.innerHTML = "";
|
|
|
|
// don't let it float - it screws up layout somehow
|
|
this.widget.picker.domNode.style.cssFloat = "none";
|
|
this.domContainer.style.height =
|
|
Math.max(this.widget.picker.domNode.offsetHeight +
|
|
this.widget.offsetHeight +
|
|
this.domNode.parentNode.getStyle("margin-top").toInt() +
|
|
this.domNode.parentNode.getStyle("margin-bottom").toInt(),
|
|
20) + "px";
|
|
dojo.event.connect(this.widget.picker,
|
|
"onValueChanged",
|
|
this,
|
|
this._timePicker_valueChangedHandler);
|
|
},
|
|
|
|
_destroyPicker: function()
|
|
{
|
|
if (this.widget.picker)
|
|
{
|
|
this.domNode.removeChild(this.widget.picker.domNode);
|
|
this.widget.picker = null;
|
|
this.domContainer.style.height =
|
|
Math.max(this.widget.offsetHeight +
|
|
this.domNode.parentNode.getStyle("margin-top").toInt() +
|
|
this.domNode.parentNode.getStyle("margin-bottom").toInt(),
|
|
20) + "px";
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
var initial_value = this.getInitialValue();
|
|
|
|
attach_point.appendChild(this.domNode);
|
|
this.widget = new Element("input", { "id": this.id + "-widget", "type": "text" });
|
|
if (initial_value)
|
|
{
|
|
var jsDate = this._parseTime(initial_value);
|
|
this.widget.setAttribute("value",
|
|
dojo.date.format(jsDate,
|
|
{timePattern: alfresco.xforms.constants.TIME_FORMAT,
|
|
selector: "timeOnly"}));
|
|
}
|
|
else
|
|
{
|
|
this.widget.setAttribute("value", this._noValueSet);
|
|
this.widget.addClass("xformsGhostText");
|
|
}
|
|
if (this.isReadonly())
|
|
{
|
|
this.widget.setAttribute("disabled", true);
|
|
}
|
|
this.domNode.appendChild(this.widget);
|
|
|
|
var expandoImage = new Element("img");
|
|
expandoImage.setAttribute("src", alfresco.constants.WEBAPP_CONTEXT + "/images/icons/action.gif");
|
|
expandoImage.align = "absmiddle";
|
|
expandoImage.style.margin = "0px 5px";
|
|
|
|
this.domNode.appendChild(expandoImage);
|
|
|
|
if (!this.isReadonly())
|
|
{
|
|
expandoImage.onclick = this._expando_clickHandler.bindAsEventListener(this);
|
|
this.widget.onfocus = this._timeTextBox_focusHandler.bindAsEventListener(this);
|
|
this.widget.onchange = this._timeTextBox_changeHandler.bindAsEventListener(this);
|
|
}
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
var jsDate = this._parseTime(value);
|
|
this.widget.value = dojo.date.format(jsDate,
|
|
{timePattern: alfresco.xforms.constants.TIME_FORMAT,
|
|
selector: "timeOnly"});
|
|
this.widget.removeClass("xformsghosttext");
|
|
}
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
if (this.widget.value == null ||
|
|
this.widget.value.length == 0 ||
|
|
this.widget.value == this._noValueSet)
|
|
{
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
var jsDate = dojo.date.parse(this.widget.value,
|
|
{timePattern: alfresco.xforms.constants.TIME_FORMAT,
|
|
selector: "timeOnly"});
|
|
return dojo.date.format(jsDate, {timePattern: this._xformsFormat[0], selector: "timeOnly"});
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_timeTextBox_focusHandler: function(event)
|
|
{
|
|
this._destroyPicker();
|
|
},
|
|
|
|
_timeTextBox_changeHandler: function(event)
|
|
{
|
|
this._commitValueChange();
|
|
},
|
|
|
|
_timePicker_valueChangedHandler: function(date)
|
|
{
|
|
var xfDate = dojo.date.format(date, {timePattern: this._xformsFormat[0], selector: "timeOnly"});
|
|
this.setValue(xfDate);
|
|
this._commitValueChange();
|
|
},
|
|
|
|
_expando_clickHandler: function()
|
|
{
|
|
if (this.widget.picker)
|
|
{
|
|
this._destroyPicker();
|
|
}
|
|
else
|
|
{
|
|
this._createPicker();
|
|
}
|
|
}
|
|
});
|
|
|
|
/** The date time picker widget which handles xforms widget xf:input with type xf:datetime */
|
|
alfresco.xforms.DateTimePicker = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
dojo.require("dojo.date.format");
|
|
this._noValueSet = (alfresco.resources["eg"] + " " +
|
|
dojo.date.format(new Date(),
|
|
{datePattern: alfresco.xforms.constants.DATE_TIME_FORMAT,
|
|
selector: "dateOnly"}));
|
|
},
|
|
|
|
/** */
|
|
_createPicker: function()
|
|
{
|
|
dojo.require("dojo.widget.DatePicker");
|
|
dojo.require("dojo.widget.TimePicker");
|
|
|
|
this._pickerDiv = document.createElement("div");
|
|
this._pickerDiv.style.position = "relative";
|
|
this._pickerDiv.style.width = this.widget.offsetWidth + "px";
|
|
this.domNode.appendChild(this._pickerDiv);
|
|
|
|
var datePickerDiv = document.createElement("div");
|
|
datePickerDiv.style.position = "absolute";
|
|
datePickerDiv.style.left = "0px";
|
|
datePickerDiv.style.top = "0px";
|
|
this._pickerDiv.appendChild(datePickerDiv);
|
|
|
|
var dp_initial_value = this.getValue() || dojo.date.toRfc3339(new Date());
|
|
this.widget.datePicker = dojo.widget.createWidget("DatePicker",
|
|
{
|
|
value: dp_initial_value
|
|
},
|
|
datePickerDiv);
|
|
var timePickerDiv = document.createElement("div");
|
|
timePickerDiv.style.position = "absolute";
|
|
timePickerDiv.style.right = "0px";
|
|
timePickerDiv.style.top = "0px";
|
|
this._pickerDiv.appendChild(timePickerDiv);
|
|
|
|
var jsDate = this.getValue() ? dojo.date.fromRfc3339(this.getValue()) : new Date();
|
|
this.widget.timePicker = dojo.widget.createWidget("TimePicker",
|
|
{
|
|
value: jsDate
|
|
},
|
|
timePickerDiv);
|
|
this.widget.timePicker.anyTimeContainerNode.innerHTML = "";
|
|
|
|
// don't let it float - it screws up layout somehow
|
|
this.widget.timePicker.domNode.style.cssFloat = "none";
|
|
this._pickerDiv.style.height = Math.max(this.widget.timePicker.domNode.offsetHeight,
|
|
this.widget.datePicker.domNode.offsetHeight);
|
|
this.domContainer.style.height =
|
|
Math.max(this._pickerDiv.offsetHeight +
|
|
this.widget.offsetHeight +
|
|
this.domNode.parentNode.getStyle("margin-top").toInt() +
|
|
this.domNode.parentNode.getStyle("margin-bottom").toInt(),
|
|
20) + "px";
|
|
dojo.event.connect(this.widget.datePicker,
|
|
"onValueChanged",
|
|
this,
|
|
this._datePicker_valueChangedHandler);
|
|
dojo.event.connect(this.widget.timePicker,
|
|
"onValueChanged",
|
|
this,
|
|
this._timePicker_valueChangedHandler);
|
|
},
|
|
|
|
_destroyPicker: function()
|
|
{
|
|
if (this._pickerDiv)
|
|
{
|
|
this.domNode.removeChild(this._pickerDiv);
|
|
this.widget.datePicker = null;
|
|
this.widget.timePicker = null;
|
|
this._pickerDiv = null;
|
|
this.domContainer.style.height =
|
|
Math.max(this.widget.offsetHeight +
|
|
this.domNode.parentNode.getStyle("margin-top").toInt() +
|
|
this.domNode.parentNode.getStyle("margin-bottom").toInt(),
|
|
20) + "px";
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
var initial_value = this.getInitialValue();
|
|
|
|
attach_point.appendChild(this.domNode);
|
|
this.widget = new Element("input", { "id": this.id + "-widget", "type": "text" });
|
|
if (initial_value)
|
|
{
|
|
var jsDate = dojo.date.fromRfc3339(initial_value);
|
|
this.widget.setAttribute("value",
|
|
dojo.date.format(jsDate,
|
|
{timePattern: alfresco.xforms.constants.DATE_TIME_FORMAT,
|
|
selector: "timeOnly"}));
|
|
}
|
|
else
|
|
{
|
|
this.widget.setAttribute("value", this._noValueSet);
|
|
this.widget.addClass("xformsGhostText");
|
|
}
|
|
this.domNode.appendChild(this.widget);
|
|
this.widget.style.width = (3 * this.widget.offsetWidth) + "px";
|
|
|
|
var expandoImage = new Element("img");
|
|
expandoImage.setAttribute("src", alfresco.constants.WEBAPP_CONTEXT + "/images/icons/action.gif");
|
|
expandoImage.align = "absmiddle";
|
|
expandoImage.style.margin = "0px 5px";
|
|
|
|
this.domNode.appendChild(expandoImage);
|
|
|
|
expandoImage.onclick = this._expando_clickHandler.bindAsEventListener(this);
|
|
this.widget.onfocus = this._dateTimeTextBox_focusHandler.bindAsEventListener(this);
|
|
this.widget.onchange = this._dateTimeTextBox_changeHandler.bindAsEventListener(this);
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
if (!this.widget)
|
|
{
|
|
this.setInitialValue(value, forceCommit);
|
|
}
|
|
else
|
|
{
|
|
this.parent(value, forceCommit);
|
|
var jsDate = dojo.date.fromRfc3339(value);
|
|
this.widget.value = dojo.date.format(jsDate,
|
|
{datePattern: alfresco.xforms.constants.DATE_TIME_FORMAT,
|
|
selector: "dateOnly"});
|
|
this.widget.removeClass("xformsGhostText");
|
|
}
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
if (this.widget.value == null ||
|
|
this.widget.value.length == 0 ||
|
|
this.widget.value == this._noValueSet)
|
|
{
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
var jsDate = dojo.date.parse(this.widget.value,
|
|
{datePattern: alfresco.xforms.constants.DATE_TIME_FORMAT,
|
|
selector: "dateOnly"});
|
|
return dojo.date.toRfc3339(jsDate);
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_dateTimeTextBox_focusHandler: function(event)
|
|
{
|
|
this._destroyPicker();
|
|
},
|
|
|
|
_dateTimeTextBox_changeHandler: function(event)
|
|
{
|
|
this._commitValueChange();
|
|
},
|
|
|
|
_timePicker_valueChangedHandler: function(date)
|
|
{
|
|
var value = this.getValue() ? dojo.date.fromRfc3339(this.getValue()) : new Date();
|
|
value.setHours(date.getHours());
|
|
value.setMinutes(date.getMinutes());
|
|
value = dojo.date.toRfc3339(value);
|
|
this.setValue(value);
|
|
this._commitValueChange();
|
|
},
|
|
|
|
_datePicker_valueChangedHandler: function(date)
|
|
{
|
|
var value = this.getValue() ? dojo.date.fromRfc3339(this.getValue()) : new Date();
|
|
value.setYear(date.getYear());
|
|
value.setMonth(date.getMonth());
|
|
value.setDate(date.getDate());
|
|
value = dojo.date.toRfc3339(value);
|
|
this.setValue(value);
|
|
this._commitValueChange();
|
|
},
|
|
|
|
_expando_clickHandler: function()
|
|
{
|
|
if (this._pickerDiv)
|
|
{
|
|
this._destroyPicker();
|
|
}
|
|
else
|
|
{
|
|
this._createPicker();
|
|
}
|
|
}
|
|
});
|
|
|
|
/** The year picker handles xforms widget xf:input with a gYear type */
|
|
alfresco.xforms.YearPicker = alfresco.xforms.TextField.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
},
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
render: function(attach_point)
|
|
{
|
|
this.parent(attach_point);
|
|
this.widget.size = "4";
|
|
this.widget.setAttribute("maxlength", "4");
|
|
},
|
|
|
|
getInitialValue: function()
|
|
{
|
|
var result = this.parent();
|
|
return result ? result.replace(/^0*([^0]+)$/, "$1") : result;
|
|
},
|
|
|
|
setValue: function(value, forceCommit)
|
|
{
|
|
this.parent((value
|
|
? value.replace(/^0*([^0]+)$/, "$1")
|
|
: null),
|
|
forceCommit);
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
var result = this.parent();
|
|
return result ? dojo.string.padLeft(result, 4, "0") : null;
|
|
}
|
|
});
|
|
|
|
/** The day picker widget which handles xforms widget xf:input with type xf:gDay */
|
|
alfresco.xforms.DayPicker = alfresco.xforms.ComboboxSelect1.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
_getItemValues: function()
|
|
{
|
|
var result = [];
|
|
result.push({id: "day_empty", label: "", value: "", valid: false});
|
|
for (var i = 1; i <= 31; i++)
|
|
{
|
|
result.push({
|
|
id: "day_" + i,
|
|
label: i,
|
|
value: "---" + (i < 10 ? "0" + i : i),
|
|
valid: true
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
});
|
|
|
|
/** The month picker widget which handles xforms widget xf:input with type xf:gMonth */
|
|
alfresco.xforms.MonthPicker = alfresco.xforms.ComboboxSelect1.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
dojo.require("dojo.date.format");
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
_getItemValues: function()
|
|
{
|
|
var result = [];
|
|
result.push({id: "month_empty", label: "", value: "", valid: false});
|
|
for (var i = 0; i < 12; i++)
|
|
{
|
|
var d = new Date();
|
|
d.setMonth(i);
|
|
result.push({
|
|
id: "month_" + i,
|
|
label: dojo.date.getMonthName(d),
|
|
value: "--" + (i + 1 < 10 ? "0" + (i + 1) : i + 1),
|
|
valid: true
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
});
|
|
|
|
/** The month day picker widget which handles xforms widget xf:input with type xf:gMonthDay */
|
|
alfresco.xforms.MonthDayPicker = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
this.monthPicker = new alfresco.xforms.MonthPicker(xform, xformsNode);
|
|
this.monthPicker._compositeParent = this;
|
|
|
|
this.dayPicker = new alfresco.xforms.DayPicker(xform, xformsNode);
|
|
this.dayPicker._compositeParent = this;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
render: function(attach_point)
|
|
{
|
|
this.setValue(this.getInitialValue());
|
|
attach_point.appendChild(this.domNode);
|
|
this.dayPicker.render(this.domNode);
|
|
this.dayPicker.widget.style.marginRight = "10px";
|
|
this.monthPicker.render(this.domNode);
|
|
this.domNode.style.width = this.monthPicker.domNode.offsetWidth + this.dayPicker.domNode.offsetWidth + 10 + "px";
|
|
},
|
|
|
|
setValue: function(value)
|
|
{
|
|
this.monthPicker.setValue(value ? value.match(/^--[^-]+/)[0] : null);
|
|
this.dayPicker.setValue(value ? "---" + value.replace(/^--[^-]+-/, "") : null);
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
// format is --MM-DD
|
|
var day = this.dayPicker.getValue();
|
|
var month = this.monthPicker.getValue();
|
|
return month && day ? day.replace(/^--/, month) : null;
|
|
}
|
|
});
|
|
|
|
/** The year month picker widget which handles xforms widget xf:input with type xf:gYearMonth */
|
|
alfresco.xforms.YearMonthPicker = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
this.yearPicker = new alfresco.xforms.YearPicker(xform, xformsNode);
|
|
this.yearPicker._compositeParent = this;
|
|
|
|
this.monthPicker = new alfresco.xforms.MonthPicker(xform, xformsNode);
|
|
this.monthPicker._compositeParent = this;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
render: function(attach_point)
|
|
{
|
|
this.setValue(this.getInitialValue());
|
|
attach_point.appendChild(this.domNode);
|
|
this.monthPicker.render(this.domNode);
|
|
this.monthPicker.widget.style.marginRight = "10px";
|
|
this.yearPicker.domNode.style.display = "inline";
|
|
this.yearPicker.render(this.domNode);
|
|
this.domNode.style.width = this.yearPicker.domNode.offsetWidth + this.monthPicker.domNode.offsetWidth + 10 + "px";
|
|
},
|
|
|
|
setValue: function(value)
|
|
{
|
|
this.monthPicker.setValue(value ? value.replace(/^[^-]+-/, "--") : null);
|
|
this.yearPicker.setValue(value ? value.match(/^[^-]+/)[0] : null);
|
|
},
|
|
|
|
getValue: function()
|
|
{
|
|
// format is CCYY-MM
|
|
var year = this.yearPicker.getValue();
|
|
var month = this.monthPicker.getValue();
|
|
return year && month ? month.replace(/^-/, year) : null;
|
|
}
|
|
});
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// widgets for group types
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Handles xforms widget xf:group. A group renders and manages a set of children
|
|
* and provides a header for expanding and collapsing the group. A group header
|
|
* is shown for all group that don't have xf:appearance set to 'repeated' and
|
|
* that are not the root group.
|
|
*/
|
|
alfresco.xforms.AbstractGroup = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget, domNode)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget, domNode);
|
|
this._children = [];
|
|
this.domNode.removeClass("xformsItem");
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** Returns the child at the specified index or null if the index is out of range. */
|
|
getChildAt: function(index)
|
|
{
|
|
return index < this._children.length ? this._children[index] : null;
|
|
},
|
|
|
|
/** Returns the index of a particular child or -1 if the child was not found. */
|
|
getChildIndex: function(child)
|
|
{
|
|
for (var i = 0; i < this._children.length; i++)
|
|
{
|
|
if (alfresco.constants.DEBUG)
|
|
{
|
|
alfresco.log(this.id + "[" + i + "]: " +
|
|
" is " + this._children[i].id +
|
|
" the same as " + child.id + "?");
|
|
}
|
|
if (this._children[i] == child)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
},
|
|
|
|
/** Adds the child to end of the list of children. */
|
|
addChild: function(child)
|
|
{
|
|
return this._insertChildAt(child, this._children.length);
|
|
},
|
|
|
|
_isIndented: function()
|
|
{
|
|
return !(this.parentWidget instanceof alfresco.xforms.ViewRoot) && this._children.length > 1;
|
|
},
|
|
|
|
/** Inserts a child at the specified position. */
|
|
_insertChildAt: function(child, position, nodeName, attach_point)
|
|
{
|
|
alfresco.log(this.id + "._insertChildAt(" + child.id + ", " + position + ")");
|
|
child.parentWidget = this;
|
|
|
|
child.domContainer = new Element($pick(nodeName, "div"));
|
|
child.domContainer.setAttribute("id", child.id + "-domContainer");
|
|
child.domContainer.addClass("xformsItemDOMContainer");
|
|
|
|
if (position == this._children.length)
|
|
{
|
|
$pick(attach_point, this.domNode.childContainerNode).appendChild(child.domContainer);
|
|
this._children.push(child);
|
|
}
|
|
else
|
|
{
|
|
$pick(attach_point, this.domNode.childContainerNode).insertBefore(child.domContainer,
|
|
this.getChildAt(position).domContainer);
|
|
this._children.splice(position, 0, child);
|
|
}
|
|
return child.domContainer;
|
|
},
|
|
|
|
/** Removes the child at the specified position. */
|
|
_removeChildAt: function(position)
|
|
{
|
|
var child = this.getChildAt(position);
|
|
if (!child)
|
|
{
|
|
throw new Error("unable to find child at " + position);
|
|
}
|
|
|
|
this._children.splice(position, 1);
|
|
child.domContainer.group = this;
|
|
var anim = dojo.lfx.html.fadeOut(child.domContainer, 500);
|
|
anim.onEnd = function()
|
|
{
|
|
child.domContainer.style.display = "none";
|
|
child._destroy();
|
|
|
|
child.domContainer.remove();
|
|
|
|
child.domContainer.group._updateDisplay(false);
|
|
};
|
|
anim.play();
|
|
|
|
this._childRemoved(child);
|
|
|
|
return child;
|
|
},
|
|
|
|
/** Event handler for when a child has been added. */
|
|
_childAdded: function(child) { },
|
|
|
|
/** Event handler for when a child has been removed. */
|
|
_childRemoved: function(child) { },
|
|
|
|
/** Utility function to create the a label container */
|
|
_createLabelContainer: function(child, nodeName, attach_point)
|
|
{
|
|
var labelNode = new Element($pick(nodeName, "div"),
|
|
{
|
|
id: child.id + "-label",
|
|
"class": "xformsItemLabelContainer"
|
|
});
|
|
var requiredImage = new Element("img", { "class": "xformsItemRequiredImage" });
|
|
requiredImage.src = alfresco.xforms.AbstractGroup._requiredImage.src;
|
|
|
|
labelNode.appendChild(requiredImage);
|
|
|
|
if (!child.isRequired())
|
|
{
|
|
requiredImage.style.visibility = "hidden";
|
|
}
|
|
var label = child.getLabel();
|
|
if (label)
|
|
{
|
|
child.labelNode = labelNode;
|
|
child.labelNode.appendChild(document.createTextNode(label));
|
|
}
|
|
var hint = child.getHint();
|
|
if (hint)
|
|
{
|
|
labelNode.setAttribute("title", hint);
|
|
requiredImage.setAttribute("alt", hint);
|
|
}
|
|
labelNode.style.width = "0px";
|
|
$pick(attach_point, child.domContainer).appendChild(labelNode);
|
|
labelNode.style.width = labelNode.scrollWidth + "px";
|
|
return labelNode;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
isValidForSubmit: function()
|
|
{
|
|
return true;
|
|
},
|
|
|
|
/** Iterates all children a produces an array of widgets which are invalid for submit. */
|
|
getWidgetsInvalidForSubmit: function()
|
|
{
|
|
var result = [];
|
|
for (var i = 0; i < this._children.length; i++)
|
|
{
|
|
if (this._children[i] instanceof alfresco.xforms.AbstractGroup)
|
|
{
|
|
result = result.concat(this._children[i].getWidgetsInvalidForSubmit());
|
|
}
|
|
else if (!this._children[i].isValidForSubmit())
|
|
{
|
|
result.push(this._children[i]);
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
/** Recusively destroys all children. */
|
|
_destroy: function()
|
|
{
|
|
this.parent();
|
|
this._children.each(function(c) { c._destroy() });
|
|
},
|
|
|
|
setReadonly: function(readonly)
|
|
{
|
|
this.parent(readonly);
|
|
this._children.each(function(c) { c.setReadonly(readonly); });
|
|
},
|
|
|
|
render: function(attach_point)
|
|
{
|
|
this.domNode.widget = this;
|
|
return this.domNode;
|
|
},
|
|
|
|
_updateDisplay: function(recursively)
|
|
{
|
|
if (recursively)
|
|
{
|
|
this._children.each(function(c) { c._updateDisplay(recursively); });
|
|
}
|
|
},
|
|
|
|
showAlert: function()
|
|
{
|
|
this._children.each(function(c) { c.showAlert(); });
|
|
},
|
|
|
|
hideAlert: function()
|
|
{
|
|
this._children.each(function(c) { c.hideAlert(); });
|
|
}
|
|
});
|
|
|
|
alfresco.xforms.AbstractGroup._requiredImage = new Image();
|
|
alfresco.xforms.AbstractGroup._requiredImage.src = alfresco.constants.WEBAPP_CONTEXT + "/images/icons/required_field.gif";
|
|
|
|
/**
|
|
* Handles xforms widget xf:group. A group renders and manages a set of children
|
|
* and provides a header for expanding and collapsing the group. A group header
|
|
* is shown for all group that don't have xf:appearance set to 'repeated' and
|
|
* that are not the root group.
|
|
*/
|
|
alfresco.xforms.VGroup = alfresco.xforms.AbstractGroup.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_groupHeaderNode: null,
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** Inserts a child at the specified position. */
|
|
_insertChildAt: function(child, position)
|
|
{
|
|
if (!this.domNode.childContainerNode.parentNode)
|
|
{
|
|
// only add this to the dom once we're adding a child
|
|
this.domNode.appendChild(this.domNode.childContainerNode);
|
|
this._contentDivs = {};
|
|
}
|
|
|
|
child.domContainer = this.parent(child, position);
|
|
|
|
if (this.parentWidget && this.parentWidget.domNode)
|
|
{
|
|
child.domContainer.style.top = this.parentWidget.domNode.style.bottom;
|
|
}
|
|
|
|
function shouldInsertDivider(group, child, position)
|
|
{
|
|
if (group.getAppearance() != "full")
|
|
{
|
|
return false;
|
|
}
|
|
if (group instanceof alfresco.xforms.Repeat)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!child.isVisible())
|
|
{
|
|
return false;
|
|
}
|
|
if (group._children[position - 1] instanceof alfresco.xforms.AbstractGroup)
|
|
{
|
|
return true;
|
|
}
|
|
if (child instanceof alfresco.xforms.AbstractGroup)
|
|
{
|
|
for (var i = position - 1; i > 0; i--)
|
|
{
|
|
if (group._children[i].isVisible())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (shouldInsertDivider(this, child, position))
|
|
{
|
|
var divider = new Element("div", { "class": "xformsGroupDivider"});
|
|
this.domNode.childContainerNode.insertBefore(divider,
|
|
child.domContainer);
|
|
}
|
|
|
|
var contentDiv = new Element("div", { "id": child.id + "-content", "class": "xformsGroupItem"});
|
|
this._contentDivs[child.id] = contentDiv;
|
|
if (!(child instanceof alfresco.xforms.AbstractGroup))
|
|
{
|
|
contentDiv.labelNode = this._createLabelContainer(child);
|
|
child.domContainer.appendChild(contentDiv.labelNode);
|
|
}
|
|
|
|
child.domContainer.appendChild(contentDiv);
|
|
contentDiv.style.left = (child instanceof alfresco.xforms.AbstractGroup
|
|
? "0px"
|
|
: "30%");
|
|
|
|
var contentDivWidth = "100%";
|
|
// the following does avoid devision by zero ... in contentDiv.offsetLeft / child.domContainer.offsetWidth
|
|
if (!(child instanceof alfresco.xforms.AbstractGroup) && child.domContainer.offsetWidth != 0)
|
|
{
|
|
contentDivWidth = ((1 - (contentDiv.offsetLeft / child.domContainer.offsetWidth)) * 100) + "%";
|
|
}
|
|
contentDiv.style.width = contentDivWidth;
|
|
child.render(contentDiv);
|
|
if (!(child instanceof alfresco.xforms.AbstractGroup))
|
|
{
|
|
child.domContainer.style.height =
|
|
Math.max(contentDiv.offsetHeight +
|
|
contentDiv.getStyle("margin-top").toInt() +
|
|
contentDiv.getStyle("margin-bottom").toInt(),
|
|
20) + "px";
|
|
}
|
|
|
|
alfresco.log(contentDiv.getAttribute("id") + " offsetTop is " + contentDiv.offsetTop);
|
|
contentDiv.style.top = "-" + Math.max(0, contentDiv.offsetTop - contentDiv.getStyle("margin-top").toInt()) + "px";
|
|
if (contentDiv.labelNode)
|
|
{
|
|
// contentDiv.labelNode.style.top = (contentDiv.offsetTop + ((.5 * contentDiv.offsetHeight) -
|
|
// (.5 * contentDiv.labelNode.offsetHeight))) + "px";
|
|
contentDiv.labelNode.style.position = "relative";
|
|
contentDiv.labelNode.style.top = contentDiv.offsetTop + "px";
|
|
contentDiv.labelNode.style.height = contentDiv.offsetHeight + "px";
|
|
contentDiv.labelNode.style.lineHeight = contentDiv.labelNode.style.height;
|
|
|
|
}
|
|
contentDiv.widget = child;
|
|
|
|
// Glen.Johnson@alfresco.com - for each child added to a VGroup,
|
|
// the method call below (commented out) recalculates the layout and
|
|
// updates the display for each of its siblings (already displayed
|
|
// above it). This is extremely expensive in terms of processing time.
|
|
// Commenting out the method call below drastically improves form rendering
|
|
// time for forms containing lots of VGroup widgets.
|
|
// See JIRA issue WCM-629
|
|
//
|
|
// this._updateDisplay(false);
|
|
|
|
this._childAdded(child);
|
|
return child.domContainer;
|
|
},
|
|
|
|
render: function(attach_point)
|
|
{
|
|
this.domNode.widget = this;
|
|
|
|
if (this.getAppearance() == "full")
|
|
{
|
|
this.domNode.addClass("xformsGroup");
|
|
this.domNode.style.position = "relative";
|
|
this.domNode.style.marginRight = (this.domNode.getStyle("margin-left").toInt() / 3) + "px";
|
|
if (window.ie)
|
|
{
|
|
this.domNode.style.width = "100%";
|
|
}
|
|
else
|
|
{
|
|
var x = ((this.domNode.offsetWidth - this.domNode.clientWidth) +
|
|
this.domNode.getStyle("margin-left").toFloat() +
|
|
this.domNode.getStyle("margin-right").toFloat());
|
|
this.domNode.style.width = (1 - (x / attach_point.offsetWidth)) * 100 + "%";
|
|
}
|
|
|
|
this._groupHeaderNode = new Element("div",
|
|
{
|
|
"id": this.id + "-groupHeaderNode",
|
|
"class": "xformsGroupHeader"
|
|
});
|
|
this.domNode.appendChild(this._groupHeaderNode);
|
|
|
|
this.toggleExpandedImage = new Element("img",
|
|
{
|
|
"align": "absmiddle",
|
|
"styles": { "margin": "0px 5px" },
|
|
"src": alfresco.xforms.constants.EXPANDED_IMAGE.src
|
|
});
|
|
this._groupHeaderNode.appendChild(this.toggleExpandedImage);
|
|
this.toggleExpandedImage.onclick = this._toggleExpanded_clickHandler.bindAsEventListener(this);
|
|
|
|
this._groupHeaderNode.appendChild(document.createTextNode(this.getLabel()));
|
|
}
|
|
attach_point.appendChild(this.domNode);
|
|
this.domNode.childContainerNode = new Element("div",
|
|
{
|
|
"id": this.id + "-childContainerNode",
|
|
"styles": { "position": "relative", "width": "100%" }
|
|
});
|
|
return this.domNode;
|
|
},
|
|
|
|
/** Indicates if the group is expanded. */
|
|
isExpanded: function()
|
|
{
|
|
return (this.toggleExpandedImage.getAttribute("src") ==
|
|
alfresco.xforms.constants.EXPANDED_IMAGE.src);
|
|
},
|
|
|
|
/**
|
|
* Sets the expanded state of the widget. If collapsed, everything but the header
|
|
* will be hidden.
|
|
*/
|
|
setExpanded: function(expanded)
|
|
{
|
|
if (expanded != this.isExpanded())
|
|
{
|
|
this.toggleExpandedImage.src =
|
|
(expanded
|
|
? alfresco.xforms.constants.EXPANDED_IMAGE.src
|
|
: alfresco.xforms.constants.COLLAPSED_IMAGE.src);
|
|
this.domNode.childContainerNode.style.display = expanded ? "block" : "none";
|
|
}
|
|
},
|
|
|
|
_updateDisplay: function(recursively)
|
|
{
|
|
this.domNode.style.width = "100%";
|
|
if (!window.ie)
|
|
{
|
|
if (this._isIndented())
|
|
{
|
|
this.domNode.style.marginLeft = 10 + "px";
|
|
this.domNode.style.marginRight = 5 + "px";
|
|
|
|
this.domNode.style.width = (((this.domNode.offsetWidth - 15) / this.domNode.offsetWidth) * 100) + "%";
|
|
}
|
|
// var x = ((this.domNode.offsetWidth - this.domNode.clientWidth) +
|
|
// this.domNode.getStyle("margin-left").toFloat() +
|
|
// this.domNode.getStyle("margin-right").toFloat());
|
|
// this.domNode.style.width = (1 - (x / this.domNode.parentNode.offsetWidth)) * 100 + "%";
|
|
}
|
|
|
|
for (var i = 0; i < this._children.length; i++)
|
|
{
|
|
if (!this._children[i].isVisible())
|
|
{
|
|
continue;
|
|
}
|
|
var contentDiv = this._contentDivs[this._children[i].id];
|
|
|
|
contentDiv.style.position = "static";
|
|
contentDiv.style.top = "0px";
|
|
contentDiv.style.left = "0px";
|
|
|
|
contentDiv.style.position = "relative";
|
|
contentDiv.style.left = (this._children[i] instanceof alfresco.xforms.AbstractGroup
|
|
? "0px"
|
|
: "30%");
|
|
if (this._children[i].domContainer.parentNode.offsetWidth != 0)
|
|
{
|
|
contentDiv.style.width = (this._children[i] instanceof alfresco.xforms.AbstractGroup
|
|
? "100%"
|
|
: (1 - (contentDiv.offsetLeft /
|
|
this._children[i].domContainer.parentNode.offsetWidth)) * 100 + "%");
|
|
}
|
|
else
|
|
{
|
|
contentDiv.style.width = "100%";
|
|
}
|
|
|
|
if (recursively)
|
|
{
|
|
this._children[i]._updateDisplay(recursively);
|
|
}
|
|
|
|
if (!(this._children[i] instanceof alfresco.xforms.AbstractGroup))
|
|
{
|
|
this._children[i].domContainer.style.height =
|
|
Math.max(contentDiv.offsetHeight +
|
|
contentDiv.getStyle("margin-top").toInt() +
|
|
contentDiv.getStyle("margin-bottom").toInt(),
|
|
20) + "px";
|
|
}
|
|
|
|
contentDiv.style.top = "-" + Math.max(0, contentDiv.offsetTop - contentDiv.getStyle("margin-top").toInt()) + "px";
|
|
|
|
var labelNode = contentDiv.labelNode;
|
|
if (labelNode)
|
|
{
|
|
// labelNode.style.position = "static";
|
|
// labelNode.style.top = "0px";
|
|
// labelNode.style.left = "0px";
|
|
// labelNode.style.position = "relative";
|
|
|
|
// labelNode.style.top = (contentDiv.offsetTop + ((.5 * contentDiv.offsetHeight) -
|
|
// (.5 * labelNode.offsetHeight))) + "px";
|
|
}
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_toggleExpanded_clickHandler: function(event)
|
|
{
|
|
this.setExpanded(!this.isExpanded());
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Handles xforms widget xf:group. A group renders and manages a set of children
|
|
* and provides a header for expanding and collapsing the group. A group header
|
|
* is shown for all group that don't have xf:appearance set to 'repeated' and
|
|
* that are not the root group.
|
|
*/
|
|
alfresco.xforms.HGroup = alfresco.xforms.AbstractGroup.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget, new Element("table"));
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** a map of child ids to contentDivs */
|
|
_contentDivs: {},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_isIndented: function()
|
|
{
|
|
return false;
|
|
},
|
|
|
|
/** Inserts a child at the specified position. */
|
|
_insertChildAt: function(child, position)
|
|
{
|
|
var labelCell = new Element("td");
|
|
this.domNode.childContainerNode.appendChild(labelCell);
|
|
var labelNode = this._createLabelContainer(child, "div", labelCell);
|
|
labelNode.style.minWidth = "40px";
|
|
labelCell.style.width = labelNode.style.width;
|
|
|
|
child.parentWidget = this;
|
|
|
|
var contentCell = new Element("td");
|
|
this.domNode.childContainerNode.appendChild(contentCell);
|
|
child.domContainer = this.parent(child, position, null, contentCell);
|
|
child.domContainer.style.position = "static";
|
|
|
|
var contentDiv = new Element("div", { id: child.id + "-content", "class": "xformsGroupItem" });
|
|
child.domContainer.appendChild(contentDiv);
|
|
this._contentDivs[child.id] = contentDiv;
|
|
|
|
contentDiv.labelNode = labelNode;
|
|
child.render(contentDiv);
|
|
|
|
var w = child.domNode.style.width;
|
|
if (!w || w[w.length - 1] != "%")
|
|
{
|
|
contentCell.style.width = child.domNode.offsetWidth + "px";
|
|
}
|
|
contentDiv.widget = child;
|
|
this._childAdded(child);
|
|
return child.domContainer;
|
|
},
|
|
|
|
render: function(attach_point)
|
|
{
|
|
this.domNode.widget = this;
|
|
this.domNode.style.width = "100%";
|
|
attach_point.appendChild(this.domNode);
|
|
|
|
var tbody = new Element("tbody");
|
|
this.domNode.appendChild(tbody);
|
|
this.domNode.childContainerNode = new Element("tr");
|
|
tbody.appendChild(this.domNode.childContainerNode);
|
|
return this.domNode;
|
|
},
|
|
|
|
_updateDisplay: function(recursively)
|
|
{
|
|
this._children.each(function(child, index)
|
|
{
|
|
if (recursively)
|
|
{
|
|
child._updateDisplay(recursively);
|
|
}
|
|
}.bind(this));
|
|
}
|
|
});
|
|
|
|
alfresco.xforms.SwitchGroup = alfresco.xforms.VGroup.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
if (this.getInitialValue())
|
|
{
|
|
var initialValueTrigger = this._getCaseToggleTriggerByTypeValue(this.getInitialValue());
|
|
this._selectedCaseId = initialValueTrigger.getActions()["toggle"].properties["case"];
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** triggers that belong to the current switch */
|
|
triggers: null,
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_getCaseToggleTriggers: function()
|
|
{
|
|
var bw = this.xform.getBinding(this.xformsNode).widgets;
|
|
var result = [];
|
|
var cases = [];
|
|
for (var i in bw)
|
|
{
|
|
if (! (bw[i] instanceof alfresco.xforms.Trigger))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var action = bw[i].getActions()["toggle"];
|
|
var currentCase = cases[action.properties["case"]]
|
|
if (action && (!currentCase || eval(bw[i].id.replace('C', '')) > eval(currentCase.id.replace('C', ''))))
|
|
{
|
|
cases[action.properties["case"]] = bw[i];
|
|
}
|
|
}
|
|
for (var j in cases)
|
|
{
|
|
if (cases[j] instanceof alfresco.xforms.Trigger)
|
|
{
|
|
result.push(cases[j]);
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
_getCaseToggleTriggerByCaseId: function(caseId)
|
|
{
|
|
var bw = this.triggers;
|
|
for (var i in bw)
|
|
{
|
|
if (! (bw[i] instanceof alfresco.xforms.Trigger))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var action = bw[i].getActions()["toggle"];
|
|
if (!action)
|
|
{
|
|
continue;
|
|
}
|
|
if (action.properties["case"] == caseId)
|
|
{
|
|
return bw[i];
|
|
}
|
|
}
|
|
throw new Error("unable to find trigger " + type +
|
|
", properties " + properties +
|
|
" for " + this.id);
|
|
|
|
},
|
|
|
|
_getCaseToggleTriggerByTypeValue: function(typeValue)
|
|
{
|
|
var bw = this.xform.getBinding(this.xformsNode).widgets;
|
|
for (var i in bw)
|
|
{
|
|
if (! (bw[i] instanceof alfresco.xforms.Trigger))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var action = bw[i].getActions()["setvalue"];
|
|
if (!action)
|
|
{
|
|
continue;
|
|
}
|
|
if (action.properties["value"] == typeValue)
|
|
{
|
|
return bw[i];
|
|
}
|
|
}
|
|
throw new Error("unable to find toggle trigger for type value " + typeValue +
|
|
" for " + this.id);
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** */
|
|
_insertChildAt: function(child, position)
|
|
{
|
|
var childDomContainer = this.parent(child, position);
|
|
|
|
if (child.id == this._selectedCaseId)
|
|
{
|
|
this._getCaseToggleTriggerByCaseId(this._selectedCaseId).fire();
|
|
}
|
|
|
|
return childDomContainer;
|
|
},
|
|
|
|
render: function(attach_point)
|
|
{
|
|
this.parent(attach_point);
|
|
var cases = this._getCaseToggleTriggers();
|
|
this.triggers = cases;
|
|
var caseToggleSelect = new Element("select",
|
|
{
|
|
"id": this.id + "-toggle-select",
|
|
"styles": { "position": "absolute", "right": "0px", "top": "0px" }
|
|
});
|
|
this._groupHeaderNode.appendChild(caseToggleSelect);
|
|
for (var i = 0; i < cases.length; i++)
|
|
{
|
|
var option = document.createElement("option");
|
|
caseToggleSelect.appendChild(option);
|
|
var caseId = cases[i].getActions()["toggle"].properties["case"];
|
|
option.setAttribute("value", caseId);
|
|
option.appendChild(document.createTextNode(cases[i].getLabel()));
|
|
if (cases[i].getActions()["toggle"].properties["case"] == this._selectedCaseId)
|
|
{
|
|
option.selected = true;
|
|
}
|
|
}
|
|
caseToggleSelect.onchange = this._caseToggleSelect_changeHandler.bindAsEventListener(this);
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// XForms event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** */
|
|
handleSwitchToggled: function(selectedCaseId, deselectedCaseId)
|
|
{
|
|
alfresco.log(this.id + ".handleSwitchToggled(" + selectedCaseId +
|
|
", " + deselectedCaseId + ")");
|
|
this._selectedCaseId = selectedCaseId;
|
|
for (var i = 0; i < this._children.length; i++)
|
|
{
|
|
if (this._children[i].id == selectedCaseId)
|
|
{
|
|
this._children[i].domContainer.style.display = "block";
|
|
}
|
|
else if (this._children[i].id == deselectedCaseId)
|
|
{
|
|
this._children[i].domContainer.style.display = "none";
|
|
}
|
|
}
|
|
this._updateDisplay(true);
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_caseToggleSelect_changeHandler: function(event)
|
|
{
|
|
if (event.stopPropagation)
|
|
{
|
|
event.stopPropagation();
|
|
var t = this._getCaseToggleTriggerByCaseId(event.target.value);
|
|
t.fire();
|
|
}
|
|
else if (window.event)
|
|
{
|
|
window.event.cancelBubble = true;
|
|
var t = this._getCaseToggleTriggerByCaseId(window.event.srcElement.value);
|
|
t.fire();
|
|
}
|
|
}
|
|
});
|
|
|
|
/** */
|
|
alfresco.xforms.CaseGroup = alfresco.xforms.VGroup.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Handles xforms widget xf:group for the root group. Does some special rendering
|
|
* to present a title rather than a group header.
|
|
*/
|
|
alfresco.xforms.ViewRoot = alfresco.xforms.VGroup.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
this.focusedRepeat = null;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_isIndented: function()
|
|
{
|
|
return false;
|
|
},
|
|
|
|
render: function(attach_point)
|
|
{
|
|
this.domNode.widget = this;
|
|
this.domNode.style.position = "relative";
|
|
this.domNode.style.width = "100%";
|
|
this.domNode.addClass("xformsViewRoot");
|
|
|
|
this._groupHeaderNode = new Element("div",
|
|
{
|
|
"id": this.id + "-groupHeaderNode",
|
|
"class": "xformsViewRootHeader"
|
|
});
|
|
this.domNode.appendChild(this._groupHeaderNode);
|
|
|
|
var icon = document.createElement("img");
|
|
this._groupHeaderNode.appendChild(icon);
|
|
icon.setAttribute("src", alfresco.constants.WEBAPP_CONTEXT + "/images/icons/file_large.gif");
|
|
icon.align = "absmiddle";
|
|
icon.style.margin = "0px 5px";
|
|
this._groupHeaderNode.appendChild(document.createTextNode(this.getLabel()));
|
|
attach_point.appendChild(this.domNode);
|
|
|
|
this.domNode.childContainerNode = new Element("div",
|
|
{
|
|
"id": this.id + "-childContainerNode",
|
|
"styles": {"position": "relative", "width": "100%"}
|
|
});
|
|
return this.domNode;
|
|
},
|
|
|
|
/** */
|
|
getLabel: function()
|
|
{
|
|
return this.parent() + " " + alfresco.xforms.constants.FORM_INSTANCE_DATA_NAME;
|
|
}
|
|
});
|
|
|
|
/** A struct for providing repeat index data. */
|
|
alfresco.xforms.RepeatIndexData = function(repeat, index)
|
|
{
|
|
this.repeat = repeat;
|
|
this.index = index;
|
|
this.toString = function()
|
|
{
|
|
return "{" + this.repeat.id + " = " + this.index + "}";
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Handles xforms widget xf:repeat.
|
|
*/
|
|
alfresco.xforms.Repeat = alfresco.xforms.VGroup.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
this._repeatControls = [];
|
|
this._selectedIndex = -1;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Indicates whether or not this repeat can insert more children based
|
|
* on the alf:maximum restriction.
|
|
*/
|
|
isInsertRepeatItemEnabled: function()
|
|
{
|
|
var maximum = this.xform.getBinding(this.xformsNode).maximum;
|
|
maximum = isNaN(maximum) ? Number.MAX_VALUE : maximum;
|
|
return this._children.length < maximum;
|
|
},
|
|
|
|
/**
|
|
* Indicates whether or not this repeat can removed children based
|
|
* on the alf:minimum restriction.
|
|
*/
|
|
isRemoveRepeatItemEnabled: function()
|
|
{
|
|
var minimum = this.xform.getBinding(this.xformsNode).minimum;
|
|
minimum = isNaN(minimum) ? this.isRequired() ? 1 : 0 : minimum;
|
|
return this._children.length > minimum;
|
|
},
|
|
|
|
/**
|
|
* Returns the currently selected index or -1 if this repeat has no repeat items.
|
|
*/
|
|
getSelectedIndex: function()
|
|
{
|
|
this._selectedIndex = Math.min(this._children.length, this._selectedIndex);
|
|
if (this._children.length == 0)
|
|
{
|
|
this._selectedIndex = -1;
|
|
}
|
|
return this._selectedIndex;
|
|
},
|
|
|
|
/**
|
|
* Helper function to locate the appropriate repeat item trigger for this repeat.
|
|
* This is done by locating all related widgets via binding, and selecting the
|
|
* Trigger who's action type is the type provided and where the properties
|
|
* provided are the same for that action. This approach is used rather than simply
|
|
* looking up the trigger by id since the id isn't known for nested repeats as
|
|
* chiba modifies them.
|
|
*/
|
|
_getRepeatItemTrigger: function(type, properties)
|
|
{
|
|
var bw = this.xform.getBinding(this.xformsNode).widgets;
|
|
for (var i in bw)
|
|
{
|
|
if (! (bw[i] instanceof alfresco.xforms.Trigger))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var action = bw[i].getActions()[type];
|
|
if (!action)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var propertiesEqual = true;
|
|
for (var p in properties)
|
|
{
|
|
if (!(p in action.properties) ||
|
|
action.properties[p] != properties[p])
|
|
{
|
|
propertiesEqual = false;
|
|
break;
|
|
}
|
|
}
|
|
if (propertiesEqual)
|
|
{
|
|
return bw[i];
|
|
}
|
|
}
|
|
throw new Error("unable to find trigger " + type +
|
|
", properties " + properties +
|
|
" for " + this.id);
|
|
|
|
},
|
|
|
|
/**
|
|
* Sets the currently selected child by calliing XFormsBean.setRepeatIndeces.
|
|
* If the child provided is null, the index is set to 0.
|
|
*/
|
|
setFocusedChild: function(child)
|
|
{
|
|
var oldFocusedRepeat = this.getViewRoot().focusedRepeat;
|
|
this.getViewRoot().focusedRepeat = this;
|
|
if (oldFocusedRepeat != null && oldFocusedRepeat != this)
|
|
{
|
|
if (!oldFocusedRepeat.isAncestorOf(this))
|
|
{
|
|
oldFocusedRepeat._selectedIndex = -1;
|
|
}
|
|
oldFocusedRepeat._updateDisplay(false);
|
|
}
|
|
|
|
var repeatIndices = this.getRepeatIndices();
|
|
if (!child)
|
|
{
|
|
repeatIndices.push(new alfresco.xforms.RepeatIndexData(this, 0));
|
|
this.xform.setRepeatIndeces(repeatIndices);
|
|
}
|
|
else
|
|
{
|
|
var index = this.getChildIndex(child);
|
|
if (index < 0)
|
|
{
|
|
throw new Error("unable to find child " + child.id + " in " + this.id);
|
|
}
|
|
|
|
repeatIndices.push(new alfresco.xforms.RepeatIndexData(this, index + 1));
|
|
// xforms repeat indexes are 1-based
|
|
this.xform.setRepeatIndeces(repeatIndices);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Calls swapRepeatItems on the XFormsBean which will produce the event log
|
|
* to insert and remove the appropriate repeat items.
|
|
*/
|
|
_swapChildren: function(fromIndex, toIndex)
|
|
{
|
|
alfresco.log(this.id + ".swapChildren(" + fromIndex + ", " + toIndex + ")");
|
|
var fromChild = this.getChildAt(fromIndex);
|
|
var toChild = this.getChildAt(toIndex);
|
|
this.xform.swapRepeatItems(fromChild, toChild);
|
|
|
|
// set tinymce current instance to null
|
|
alfresco.xforms.RichTextEditor.currentInstance = null;
|
|
|
|
var anim = dojo.lfx.html.fadeOut(fromChild.domContainer, 500);
|
|
anim.onEnd = function()
|
|
{
|
|
fromChild.domContainer.style.display = "none";
|
|
};
|
|
anim.play();
|
|
},
|
|
|
|
/**
|
|
* Updates the repeat controls by changing the opacity on the image based on
|
|
* whether or not the action is enabled.
|
|
*/
|
|
_updateRepeatControls: function()
|
|
{
|
|
var insertEnabled = this.isInsertRepeatItemEnabled();
|
|
var removeEnabled = this.isRemoveRepeatItemEnabled();
|
|
for (var i = 0; i < this._repeatControls.length; i++)
|
|
{
|
|
this._repeatControls[i].moveRepeatItemUpImage.setOpacity(i == 0 ? .3 : 1);
|
|
this._repeatControls[i].moveRepeatItemDownImage.setOpacity(i == this._repeatControls.length - 1 ? .3 : 1);
|
|
this._repeatControls[i].insertRepeatItemImage.setOpacity(insertEnabled ? 1 : .3);
|
|
this._repeatControls[i].removeRepeatItemImage.setOpacity(removeEnabled ? 1 : .3);
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** When debugging, insert the id into the label. */
|
|
getLabel: function()
|
|
{
|
|
var label = this.parentWidget.getLabel();
|
|
if (alfresco.constants.DEBUG)
|
|
{
|
|
label += "[" + this.id + "]";
|
|
}
|
|
return label;
|
|
},
|
|
|
|
/** Overrides _insertChildAt in Group to provide repeater controls. */
|
|
_insertChildAt: function(child, position)
|
|
{
|
|
this._repeatControls.splice(position, 0, new Element("div"));
|
|
var images =
|
|
[
|
|
{ name: "insertRepeatItemImage", src: "plus", action: this._insertRepeatItemAfter_handler },
|
|
{ name: "moveRepeatItemUpImage", src: "arrow_up", action: this._moveRepeatItemUp_handler },
|
|
{ name: "moveRepeatItemDownImage", src: "arrow_down", action: this._moveRepeatItemDown_handler },
|
|
{ name: "removeRepeatItemImage", src: "minus", action: this._removeRepeatItem_handler }
|
|
];
|
|
var _repeatControlsWidth = 0;
|
|
for (var i = 0; i < images.length; i++)
|
|
{
|
|
var img = new Element("img",
|
|
{
|
|
"src": (alfresco.constants.WEBAPP_CONTEXT + "/images/icons/" +
|
|
images[i].src + ".gif"),
|
|
"styles": { "width" : "16px", "height" : "16px" }
|
|
});
|
|
this._repeatControls[position][images[i].name] = img;
|
|
var imgMargin = [2, 5, 2, (i == 0 ? 5 : 0) ];
|
|
img.style.margin = imgMargin.join("px ") + "px";
|
|
_repeatControlsWidth += (parseInt(img.style.width) + imgMargin[1] + imgMargin[3]);
|
|
this._repeatControls[position].appendChild(img);
|
|
img.onclick = images[i].action.bindAsEventListener(this);
|
|
}
|
|
|
|
var result = this.parent(child, position);
|
|
child.repeat = this;
|
|
result.onclick = function(event)
|
|
{
|
|
event = new Event(event);
|
|
child.repeat.setFocusedChild(child);
|
|
event.stopPropagation();
|
|
};
|
|
result.addClass("xformsRepeatItem");
|
|
if (result.nextSibling)
|
|
{
|
|
result.parentNode.insertBefore(this._repeatControls[position],
|
|
result.nextSibling);
|
|
}
|
|
else
|
|
{
|
|
result.parentNode.appendChild(this._repeatControls[position]);
|
|
}
|
|
|
|
this._repeatControls[position].addClass("xformsRepeatControls");
|
|
this._repeatControls[position].style.width = _repeatControlsWidth + "px";
|
|
this._repeatControls[position].style.backgroundColor = result.getStyle("background-color");
|
|
this._repeatControls[position].style.overflow = "hidden";
|
|
|
|
result.style.paddingBottom = (.5 * this._repeatControls[position].offsetHeight) + "px";
|
|
|
|
// this._repeatControls[position].style.top = -((.5 * this._repeatControls[position].offsetHeight) +
|
|
// result.getStyle("margin-bottom").toInt() +
|
|
// result.getStyle("border-bottom").toInt()) + "px";
|
|
// may need to use this for centering repeat controls in quirks mode on IE
|
|
// this._repeatControls[position].style.margin = "0px " + Math.floor(100 * ((result.offsetWidth -
|
|
// this._repeatControls[position].offsetWidth) /
|
|
// (result.offsetWidth * 2)))+ "%";
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Overrides _removeChildAt in Group to remove the repeat controls associated with
|
|
* the repeat item.
|
|
*/
|
|
_removeChildAt: function(position)
|
|
{
|
|
this._repeatControls[position].style.display = "none";
|
|
this._repeatControls[position].remove();
|
|
this._repeatControls.splice(position, 1);
|
|
return this.parent(position);
|
|
},
|
|
|
|
/** Disables insert before. */
|
|
_childAdded: function(child)
|
|
{
|
|
this.headerInsertRepeatItemImage.setOpacity(.3);
|
|
this._updateRepeatControls();
|
|
},
|
|
|
|
/** Reenables insert before if there are no children left. */
|
|
_childRemoved: function(child)
|
|
{
|
|
if (this._children.length == 0)
|
|
{
|
|
this.headerInsertRepeatItemImage.setOpacity(1);
|
|
}
|
|
this._updateRepeatControls();
|
|
},
|
|
|
|
_isIndented: function()
|
|
{
|
|
return false;
|
|
},
|
|
|
|
render: function(attach_point)
|
|
{
|
|
this.domNode = this.parent(attach_point);
|
|
this.domNode.addClass("xformsRepeat");
|
|
|
|
// clear the border bottom for the group header since we'll be getting it
|
|
// from the repeat item border
|
|
this._groupHeaderNode.style.borderBottomWidth = "0px";
|
|
|
|
this._groupHeaderNode.repeat = this;
|
|
this._groupHeaderNode.onclick = function(event)
|
|
{
|
|
if ((typeof(event) != 'undefined') && (typeof(event.target) != 'undefined') && (event.target == event.currentTarget))
|
|
{
|
|
event.currentTarget.repeat.setFocusedChild(null);
|
|
}
|
|
};
|
|
|
|
this.headerInsertRepeatItemImage =
|
|
new Element("img",
|
|
{
|
|
"align": "absmiddle",
|
|
"src": alfresco.constants.WEBAPP_CONTEXT + "/images/icons/plus.gif",
|
|
"styles": { "margin-left": "5px", "width": "16px", "height": "16px" }
|
|
});
|
|
|
|
this.headerInsertRepeatItemImage.repeat = this;
|
|
this._groupHeaderNode.appendChild(this.headerInsertRepeatItemImage);
|
|
|
|
this.headerInsertRepeatItemImage.onclick =
|
|
this._headerInsertRepeatItemBefore_handler.bindAsEventListener(this);
|
|
|
|
return this.domNode;
|
|
},
|
|
|
|
_updateDisplay: function(recursively)
|
|
{
|
|
this.parent(recursively);
|
|
if (this.getViewRoot().focusedRepeat != null &&
|
|
(this.getViewRoot().focusedRepeat == this ||
|
|
this.getViewRoot().focusedRepeat.isAncestorOf(this)))
|
|
{
|
|
this._groupHeaderNode.addClass("xformsRepeatFocusedHeader");
|
|
}
|
|
else
|
|
{
|
|
this._groupHeaderNode.removeClass("xformsRepeatFocusedHeader");
|
|
}
|
|
for (var i = 0; i < this._children.length; i++)
|
|
{
|
|
var domContainerClasses = this._children[i].domContainer.getProperty("class").split(" ");
|
|
if (i + 1 == this.getSelectedIndex() && this.getViewRoot().focusedRepeat == this)
|
|
{
|
|
domContainerClasses.remove("xformsRowOdd");
|
|
domContainerClasses.remove("xformsRowEven");
|
|
domContainerClasses.include("xformsRepeatItemSelected");
|
|
}
|
|
else
|
|
{
|
|
domContainerClasses.remove("xformsRepeatItemSelected");
|
|
domContainerClasses.remove("xformsRow" + (i % 2 ? "Odd" : "Even"));
|
|
domContainerClasses.include("xformsRow" + (i % 2 ? "Even" : "Odd"));
|
|
}
|
|
this._children[i].domContainer.setProperty("class", domContainerClasses.join(" "));
|
|
|
|
this._repeatControls[i].style.backgroundColor = this._children[i].domContainer.getStyle("background-color");
|
|
|
|
if (window.navigator.appName == "Microsoft Internet Explorer")
|
|
{
|
|
this._children[i]._updateDisplay(true);
|
|
}
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Event handler for insert after. If insert is enabled, causes a setRepeatIndeces
|
|
* and an insert.
|
|
*/
|
|
_insertRepeatItemAfter_handler: function(event)
|
|
{
|
|
event = new Event(event);
|
|
event.stopPropagation();
|
|
if (this.isInsertRepeatItemEnabled())
|
|
{
|
|
var index = this._repeatControls.indexOf(event.target.parentNode);
|
|
var repeatItem = this.getChildAt(index);
|
|
this.setFocusedChild(repeatItem);
|
|
var trigger = this._getRepeatItemTrigger("insert", { position: "after" });
|
|
trigger.fire();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Event handler for insert before. If insert is enabled, causes a setRepeatIndeces
|
|
* and an insert.
|
|
*/
|
|
_headerInsertRepeatItemBefore_handler: function(event)
|
|
{
|
|
event = new Event(event);
|
|
if (this._children.length == 0)
|
|
{
|
|
event.stopPropagation();
|
|
if (this.isInsertRepeatItemEnabled())
|
|
{
|
|
// set tinymce current instance to null
|
|
alfresco.xforms.RichTextEditor.currentInstance = null;
|
|
|
|
this.setFocusedChild(null);
|
|
var trigger = this._getRepeatItemTrigger("insert", { position: "before" });
|
|
trigger.fire();
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Event handler for remove. If remove is enabled, causes a setRepeatIndeces
|
|
* and an delete.
|
|
*/
|
|
_removeRepeatItem_handler: function(event)
|
|
{
|
|
event = new Event(event);
|
|
event.stopPropagation();
|
|
if (this.isRemoveRepeatItemEnabled())
|
|
{
|
|
// set tinymce current instance to null
|
|
alfresco.xforms.RichTextEditor.currentInstance = null;
|
|
|
|
var index = this._repeatControls.indexOf(event.target.parentNode);
|
|
var repeatItem = this.getChildAt(index);
|
|
this.setFocusedChild(repeatItem);
|
|
var trigger = this._getRepeatItemTrigger("delete", {});
|
|
trigger.fire();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Event handler for move up. Calls swap children with the child before
|
|
* if the current select child is not the first child.
|
|
*/
|
|
_moveRepeatItemUp_handler: function(event)
|
|
{
|
|
event = new Event(event);
|
|
event.stopPropagation();
|
|
var index = this._repeatControls.indexOf(event.target.parentNode);
|
|
if (index != 0 && this._children.length != 1)
|
|
{
|
|
var repeatItem = this.getChildAt(index);
|
|
this.setFocusedChild(repeatItem);
|
|
this._swapChildren(index, index - 1);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Event handler for move down. Calls swap children with the child after
|
|
* if the current select child is not the last child.
|
|
*/
|
|
_moveRepeatItemDown_handler: function(event)
|
|
{
|
|
event = new Event(event);
|
|
event.stopPropagation();
|
|
var index = this._repeatControls.indexOf(event.target.parentNode);
|
|
if (index != this._children.length - 1 && this._children.length != 1)
|
|
{
|
|
var repeatItem = this.getChildAt(index);
|
|
this.setFocusedChild(repeatItem);
|
|
this._swapChildren(index, index + 1);
|
|
}
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// XForms event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** Sets the selected index. */
|
|
handleIndexChanged: function(index)
|
|
{
|
|
alfresco.log(this.id + ".handleIndexChanged(" + index + ")");
|
|
this._selectedIndex = index;
|
|
this._updateDisplay(false);
|
|
},
|
|
|
|
/** Returns a clone of the specified prototype id. */
|
|
handlePrototypeCloned: function(prototypeId)
|
|
{
|
|
alfresco.log(this.id + ".handlePrototypeCloned("+ prototypeId +")");
|
|
var chibaData = _getElementsByTagNameNS(this.xformsNode,
|
|
alfresco.xforms.constants.CHIBA_NS,
|
|
alfresco.xforms.constants.CHIBA_PREFIX,
|
|
"data");
|
|
chibaData = chibaData[chibaData.length - 1];
|
|
var prototypeToClone = dojo.dom.firstElement(chibaData);
|
|
if (prototypeToClone.getAttribute("id") != prototypeId)
|
|
{
|
|
throw new Error("unable to locate " + prototypeId +
|
|
" in " + this.id);
|
|
}
|
|
return prototypeToClone.cloneNode(true);
|
|
},
|
|
|
|
/** Inserts the clonedPrototype at the specified position. */
|
|
handleItemInserted: function(clonedPrototype, position)
|
|
{
|
|
alfresco.log(this.id + ".handleItemInserted(" + clonedPrototype.nodeName +
|
|
", " + position + ")");
|
|
var w = this.xform.createWidget(clonedPrototype, this);
|
|
this._insertChildAt(w, position);
|
|
this.xform.loadWidgets(w.xformsNode, w);
|
|
},
|
|
|
|
/** Deletes the item at the specified position. */
|
|
handleItemDeleted: function(position)
|
|
{
|
|
alfresco.log(this.id + ".handleItemDeleted(" + position + ")");
|
|
this._removeChildAt(position);
|
|
}
|
|
});
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// trigger widgets
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Handles xforms widget xf:trigger.
|
|
*/
|
|
alfresco.xforms.Trigger = alfresco.xforms.Widget.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget, new Element("input", { type: "submit" }));
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// methods & properties
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** TODO: DOCUMENT */
|
|
getActions: function()
|
|
{
|
|
if (typeof this._actions == "undefined")
|
|
{
|
|
var actionNode = _getElementsByTagNameNS(this.xformsNode,
|
|
alfresco.xforms.constants.XFORMS_NS,
|
|
alfresco.xforms.constants.XFORMS_PREFIX,
|
|
"action")[0];
|
|
this._actions = {};
|
|
for (var i = 0; i < actionNode.childNodes.length; i++)
|
|
{
|
|
if (actionNode.childNodes[i].nodeType != document.ELEMENT_NODE)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var a = new alfresco.xforms.XFormsAction(this.xform, actionNode.childNodes[i]);
|
|
this._actions[a.getType()] = a;
|
|
}
|
|
}
|
|
return this._actions;
|
|
},
|
|
|
|
/** fires the xforms action associated with the trigger */
|
|
fire: function(asynchronous)
|
|
{
|
|
this.xform.fireAction(this.id, asynchronous);
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// overridden methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
isValidForSubmit: function()
|
|
{
|
|
return true;
|
|
},
|
|
|
|
isVisible: function()
|
|
{
|
|
return false;
|
|
},
|
|
|
|
render: function(attach_point)
|
|
{
|
|
attach_point.appendChild(this.domNode);
|
|
this.widget = this.domNode;
|
|
this.widget.value = this.getLabel() + " " + this.id;
|
|
this.widget.onclick = this._clickHandler.bindAsEventListener(this);
|
|
this.domContainer.style.display = "none";
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
_clickHandler: function(event)
|
|
{
|
|
this.fire();
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Handles xforms widget xf:submit.
|
|
*/
|
|
alfresco.xforms.Submit = alfresco.xforms.Trigger.extend({
|
|
initialize: function(xform, xformsNode, parentWidget)
|
|
{
|
|
this.parent(xform, xformsNode, parentWidget);
|
|
var submit_buttons = (this.id == "submit"
|
|
? _xforms_getSubmitButtons()
|
|
: (this.id == "save-draft"
|
|
? _xforms_getSaveDraftButtons()
|
|
: null));
|
|
if (submit_buttons == null)
|
|
{
|
|
throw new Error("unknown submit button " + this.id);
|
|
}
|
|
submit_buttons.each(function(b)
|
|
{
|
|
alfresco.log("adding submit handler for " + b.getAttribute('id'));
|
|
$(b).onclick = this._submitButton_clickHandler.bindAsEventListener(this);
|
|
}.bind(this));
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// DOM event handlers
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
_clickHandler: function(event)
|
|
{
|
|
this.done = false;
|
|
_hide_errors();
|
|
this.fire();
|
|
},
|
|
|
|
/** */
|
|
_submitButton_clickHandler: function(event)
|
|
{
|
|
event = new Event(event);
|
|
var result;
|
|
if (this.xform.submitWidget && this.xform.submitWidget.done)
|
|
{
|
|
alfresco.log("done - doing base click on " + this.xform.submitWidget.currentButton.id);
|
|
this.xform.submitWidget.currentButton = null;
|
|
this.xform.submitWidget = null;
|
|
result = true;
|
|
}
|
|
else
|
|
{
|
|
alfresco.log("triggering submit from handler " + event.target.id);
|
|
event.stopPropagation();
|
|
_hide_errors();
|
|
this.xform.submitWidget = this;
|
|
this.xform.submitWidget.currentButton = event.target;
|
|
this.xform.submitWidget.fire(true);
|
|
result = false;
|
|
}
|
|
alfresco.log("submit click handler exit " + event.target.id + " with result " + result);
|
|
return result;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* A struct describing an xforms action block.
|
|
*/
|
|
alfresco.xforms.XFormsAction = new Class({
|
|
initialize: function(xform, xformsNode)
|
|
{
|
|
this.xform = xform;
|
|
this.xformsNode = xformsNode;
|
|
/** All properties of the action as map of key value pairs */
|
|
this.properties = [];
|
|
for (var i = 0; i < this.xformsNode.attributes.length; i++)
|
|
{
|
|
var attr = this.xformsNode.attributes[i];
|
|
if (attr.nodeName.match(new RegExp("^" + alfresco.xforms.constants.XFORMS_PREFIX + ":")))
|
|
{
|
|
this.properties[attr.nodeName.substring((alfresco.xforms.constants.XFORMS_PREFIX + ":").length)] =
|
|
attr.nodeValue;
|
|
}
|
|
}
|
|
if (this.getType() == "setvalue" && !this.properties["value"])
|
|
{
|
|
this.properties["value"] = this.xformsNode.firstChild.nodeValue;
|
|
}
|
|
},
|
|
|
|
/** Returns the action type. */
|
|
getType: function()
|
|
{
|
|
return this.xformsNode.nodeName.substring((alfresco.xforms.constants.XFORMS_PREFIX + ":").length);
|
|
}
|
|
});
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// xforms data model
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* An xforms event. A log of events is returned by any xforms action and
|
|
* is used to update the UI appropriately.
|
|
*/
|
|
alfresco.xforms.XFormsEvent = new Class({
|
|
initialize: function(node)
|
|
{
|
|
this.type = node.nodeName;
|
|
this.targetId = node.getAttribute("targetId");
|
|
this.targetName = node.getAttribute("targetName");
|
|
this.properties = {};
|
|
for (var i = 0; i < node.childNodes.length; i++)
|
|
{
|
|
if (node.childNodes[i].nodeType == document.ELEMENT_NODE)
|
|
{
|
|
this.properties[node.childNodes[i].getAttribute("name")] =
|
|
node.childNodes[i].getAttribute("value");
|
|
}
|
|
}
|
|
},
|
|
|
|
/** Returns the widget managing the specified target id. */
|
|
getTarget: function()
|
|
{
|
|
var targetDomNode = document.getElementById(this.targetId + "-content");
|
|
if (!targetDomNode)
|
|
{
|
|
throw new Error("unable to find node " + this.targetId + "-content");
|
|
}
|
|
return targetDomNode.widget;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* A parsed xf:bind.
|
|
*/
|
|
alfresco.xforms.Binding = new Class({
|
|
initialize: function(xformsNode, parentBinding)
|
|
{
|
|
this.xformsNode = xformsNode;
|
|
this.id = this.xformsNode.getAttribute("id");
|
|
this.nodeset = this.xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":nodeset");
|
|
this._readonly =
|
|
(_hasAttribute(this.xformsNode, alfresco.xforms.constants.XFORMS_PREFIX + ":readonly")
|
|
? this.xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":readonly") == "true()"
|
|
: null);
|
|
this._required =
|
|
(_hasAttribute(this.xformsNode, alfresco.xforms.constants.XFORMS_PREFIX + ":required")
|
|
? this.xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":required") == "true()"
|
|
: null);
|
|
this._type =
|
|
(_hasAttribute(this.xformsNode, alfresco.xforms.constants.XFORMS_PREFIX + ":type")
|
|
? this.xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":type")
|
|
: null);
|
|
this._builtInType =
|
|
(_hasAttribute(this.xformsNode, alfresco.xforms.constants.ALFRESCO_PREFIX + ":builtInType")
|
|
? this.xformsNode.getAttribute(alfresco.xforms.constants.ALFRESCO_PREFIX + ":builtInType")
|
|
: null);
|
|
this.constraint =
|
|
(_hasAttribute(this.xformsNode, alfresco.xforms.constants.XFORMS_PREFIX + ":constraint")
|
|
? this.xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":constraint")
|
|
: null);
|
|
this.maximum = this.xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":maxOccurs");
|
|
this.maximum = this.maximum == "unbounded" ? Number.MAX_VALUE : parseInt(this.maximum);
|
|
this.minimum = parseInt(this.xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":minOccurs"));
|
|
this.parentBinding = parentBinding;
|
|
this.widgets = {};
|
|
},
|
|
|
|
/** Returns the expected schema type for this binding. */
|
|
getType: function()
|
|
{
|
|
return (this._type != null
|
|
? this._type
|
|
: (this.parentBinding != null ? this.parentBinding.getType() : null));
|
|
},
|
|
|
|
/** Returns the expected built in schema type for this binding. */
|
|
getBuiltInType: function()
|
|
{
|
|
return (this._builtInType != null
|
|
? this._builtInType
|
|
: (this.parentBinding != null ? this.parentBinding.getBuiltInType() : null));
|
|
},
|
|
|
|
/** Returns true if a node bound by this binding has a readonly value */
|
|
isReadonly: function()
|
|
{
|
|
return (this._readonly != null ? this._readonly :
|
|
(this.parentBinding != null ? this.parentBinding.isReadonly() : false));
|
|
},
|
|
|
|
/** Returns true if a node bound by this binding has a required value */
|
|
isRequired: function()
|
|
{
|
|
return (this._required != null ? this._required :
|
|
(this.parentBinding != null ? this.parentBinding.isRequired() : false));
|
|
},
|
|
|
|
toString: function()
|
|
{
|
|
return ("{id: " + this.id +
|
|
",type: " + this.getType() +
|
|
",builtInType: " + this.getBuiltInType() +
|
|
",required: " + this.isRequired() +
|
|
",readonly: " + this.isReadonly() +
|
|
",nodeset: " + this.nodeset + "}");
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Manages the xforms document.
|
|
*/
|
|
alfresco.xforms.XForm = new Class({
|
|
|
|
/** Makes a request to the XFormsBean to load the xforms document. */
|
|
initialize: function()
|
|
{
|
|
alfresco.AjaxHelper.sendRequest("XFormsBean.getXForm",
|
|
null,
|
|
true,
|
|
this._loadHandler.bindAsEventListener(this));
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// Initialization
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** Parses the xforms document and produces the widget tree. */
|
|
_loadHandler: function(xformDocument)
|
|
{
|
|
this.xformDocument = xformDocument;
|
|
this.xformsNode = xformDocument.documentElement;
|
|
this._bindings = this._loadBindings(this.getModel());
|
|
|
|
var bindings = this.getBindings();
|
|
var alfUI = document.getElementById(alfresco.xforms.constants.XFORMS_UI_DIV_ID);
|
|
alfUI.style.width = "100%";
|
|
var rootGroup = _getElementsByTagNameNS(this.getBody(),
|
|
alfresco.xforms.constants.XFORMS_NS,
|
|
alfresco.xforms.constants.XFORMS_PREFIX,
|
|
"group")[0];
|
|
|
|
this.rootWidget = new alfresco.xforms.ViewRoot(this, rootGroup);
|
|
this.rootWidget.render(alfUI);
|
|
|
|
this.loadWidgets(rootGroup, this.rootWidget);
|
|
},
|
|
|
|
/** Creates the widget for the provided xforms node. */
|
|
createWidget: function(xformsNode, parentWidget)
|
|
{
|
|
var appearance = (xformsNode.getAttribute("appearance") ||
|
|
xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":appearance"));
|
|
appearance = appearance == null || appearance.length == 0 ? null : appearance;
|
|
|
|
var xformsType = xformsNode.nodeName.toLowerCase();
|
|
var binding = this.getBinding(xformsNode);
|
|
var schemaType = binding ? binding.getType() : null;
|
|
var builtInSchemaType = binding ? binding.getBuiltInType() : null;
|
|
|
|
alfresco.log("creating widget for xforms type " + xformsType +
|
|
" schema type " + schemaType +
|
|
" built in schema type " + builtInSchemaType +
|
|
" with appearance " + appearance);
|
|
var x = alfresco.xforms.widgetConfig[xformsType];
|
|
if (!x)
|
|
{
|
|
throw new Error("unknown type " + xformsNode.nodeName);
|
|
}
|
|
x = schemaType in x ? x[schemaType] : builtInSchemaType in x ? x[builtInSchemaType] : x["*"];
|
|
x = appearance in x ? x[appearance] : x["*"];
|
|
// alfresco.log(xformsType + ":" + schemaType + ":" + appearance + " =>" + x);
|
|
if (x === undefined)
|
|
{
|
|
throw new Error("unable to find widget for xforms type " + xformsType +
|
|
" schemaType " + schemaType +
|
|
" appearance " + appearance);
|
|
}
|
|
if (x == null || typeof x.className == "undefined")
|
|
{
|
|
return null;
|
|
}
|
|
var cstr = eval(x.className);
|
|
if (!cstr)
|
|
{
|
|
throw new Error("unable to load constructor " + x.className +
|
|
" for xforms type " + xformsType +
|
|
" schemaType " + schemaType +
|
|
" appearance " + appearance);
|
|
}
|
|
var result = new cstr(this, xformsNode, parentWidget, $merge({}, x.params));
|
|
if (result instanceof alfresco.xforms.Widget)
|
|
{
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
throw new Error("constructor for widget " + x +
|
|
" for xforms type " + xformsType +
|
|
" schemaType " + schemaType +
|
|
" appearance " + appearance +
|
|
" is not an alfresco.xforms.Widget");
|
|
}
|
|
},
|
|
|
|
/** Loads all widgets for the provided xforms node's children. */
|
|
loadWidgets: function(xformsNode, parentWidget)
|
|
{
|
|
for (var i = 0; i < xformsNode.childNodes.length; i++)
|
|
{
|
|
if (xformsNode.childNodes[i].nodeType != document.ELEMENT_NODE)
|
|
{
|
|
// fix for ETWOTWO-490, hide elements after rendering (Mozila/Firefox)
|
|
if ((i == (xformsNode.childNodes.length - 1)) &&
|
|
(parentWidget instanceof alfresco.xforms.SwitchGroup))
|
|
{
|
|
for (var x = 0; x < parentWidget._children.length; x++)
|
|
{
|
|
if (parentWidget.triggers[x].getActions()["toggle"].properties["case"] != parentWidget._selectedCaseId)
|
|
{
|
|
parentWidget._children[x].domContainer.style.display = "none";
|
|
}
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
alfresco.log("loading " + xformsNode.childNodes[i].nodeName +
|
|
" into " + parentWidget.id);
|
|
if (xformsNode.childNodes[i].getAttribute(alfresco.xforms.constants.ALFRESCO_PREFIX +
|
|
":prototype") == "true")
|
|
{
|
|
alfresco.log(xformsNode.childNodes[i].getAttribute("id") +
|
|
" is a prototype, ignoring");
|
|
continue;
|
|
}
|
|
|
|
var w = this.createWidget(xformsNode.childNodes[i], parentWidget);
|
|
if (w != null)
|
|
{
|
|
alfresco.log("created " + w.id + " for " + xformsNode.childNodes[i].nodeName);
|
|
parentWidget.addChild(w);
|
|
if (w instanceof alfresco.xforms.AbstractGroup)
|
|
{
|
|
this.loadWidgets(xformsNode.childNodes[i], w);
|
|
}
|
|
}
|
|
|
|
// fix for ETWOTWO-490, hide elements after rendering (Internet Explorer)
|
|
if ((i == (xformsNode.childNodes.length - 1)) &&
|
|
(parentWidget instanceof alfresco.xforms.SwitchGroup))
|
|
{
|
|
for (var x = 0; x < parentWidget._children.length; x++)
|
|
{
|
|
if (parentWidget.triggers[x].getActions()["toggle"].properties["case"] != parentWidget._selectedCaseId)
|
|
{
|
|
parentWidget._children[x].domContainer.style.display = "none";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
/** Loads all bindings from the xforms document. */
|
|
_loadBindings: function(bind, parentBinding, result)
|
|
{
|
|
result = result || [];
|
|
for (var i = 0; i < bind.childNodes.length; i++)
|
|
{
|
|
if (bind.childNodes[i].nodeName.toLowerCase() ==
|
|
alfresco.xforms.constants.XFORMS_PREFIX + ":bind")
|
|
{
|
|
var b = new alfresco.xforms.Binding(bind.childNodes[i], parentBinding);
|
|
result[b.id] = b;
|
|
alfresco.log("loaded binding " + b);
|
|
this._loadBindings(bind.childNodes[i], result[b.id], result);
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// XForms model properties & methods
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** Returns the model section of the xforms document. */
|
|
getModel: function()
|
|
{
|
|
return _getElementsByTagNameNS(this.xformsNode,
|
|
alfresco.xforms.constants.XFORMS_NS,
|
|
alfresco.xforms.constants.XFORMS_PREFIX,
|
|
"model")[0];
|
|
},
|
|
|
|
/** Returns the instance section of the xforms document. */
|
|
getInstance: function()
|
|
{
|
|
return _getElementsByTagNameNS(this.getModel(),
|
|
alfresco.xforms.constants.XFORMS_NS,
|
|
alfresco.xforms.constants.XFORMS_PREFIX,
|
|
"instance")[0];
|
|
},
|
|
|
|
/** Returns the body section of the xforms document. */
|
|
getBody: function()
|
|
{
|
|
var b = _getElementsByTagNameNS(this.xformsNode,
|
|
alfresco.xforms.constants.XHTML_NS,
|
|
alfresco.xforms.constants.XHTML_PREFIX,
|
|
"body");
|
|
return b[b.length - 1];
|
|
},
|
|
|
|
/** Returns the binding corresponding to the provided xforms node. */
|
|
getBinding: function(xformsNode)
|
|
{
|
|
return this._bindings[xformsNode.getAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":bind")];
|
|
},
|
|
|
|
/** Returns all parsed bindings. */
|
|
getBindings: function()
|
|
{
|
|
return this._bindings;
|
|
},
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// XFormsBean interaction
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** swaps the specified repeat items by calling XFormsBean.swapRepeatItems. */
|
|
swapRepeatItems: function(fromChild, toChild)
|
|
{
|
|
var params =
|
|
{
|
|
fromItemId: fromChild.xformsNode.getAttribute("id"),
|
|
toItemId: toChild.xformsNode.getAttribute("id"),
|
|
instanceId: this.getInstance().getAttribute("id")
|
|
};
|
|
|
|
alfresco.AjaxHelper.sendRequest("XFormsBean.swapRepeatItems",
|
|
params,
|
|
false,
|
|
this._handleEventLog.bindAsEventListener(this));
|
|
},
|
|
|
|
/** sets the repeat indexes by calling XFormsBean.setRepeatIndeces. */
|
|
setRepeatIndeces: function(repeatIndeces)
|
|
{
|
|
// The following debug statement is causing performance and rendering issues (ETWOTWO-1006,
|
|
// ETHREEOH-3155 & ETHREEOH-2653), only uncomment this line if necessary for fault finding.
|
|
// alfresco.log("setting repeat indeces [" + repeatIndeces.join(", ") + "]");
|
|
|
|
var params = { };
|
|
params["repeatIds"] = [];
|
|
for (var i = 0; i < repeatIndeces.length; i++)
|
|
{
|
|
params.repeatIds.push(repeatIndeces[i].repeat.id);
|
|
params[repeatIndeces[i].repeat.id] = repeatIndeces[i].index;
|
|
}
|
|
params.repeatIds = params.repeatIds.join(",");
|
|
alfresco.AjaxHelper.sendRequest("XFormsBean.setRepeatIndeces",
|
|
params,
|
|
false,
|
|
this._handleEventLog.bindAsEventListener(this));
|
|
},
|
|
|
|
/** Fires an action specified by the id by calling XFormsBean.fireAction. */
|
|
fireAction: function(id, asynchronous)
|
|
{
|
|
alfresco.log("fireAction(" + id + ")");
|
|
alfresco.AjaxHelper.sendRequest("XFormsBean.fireAction",
|
|
{ id: id },
|
|
$pick(asynchronous, false),
|
|
this._handleEventLog.bindAsEventListener(this));
|
|
},
|
|
|
|
/** Sets the value of the specified control id by calling XFormsBean.setXFormsValue. */
|
|
setXFormsValue: function(id, value)
|
|
{
|
|
value = value == null ? "" : value.toString();
|
|
alfresco.log("setting value " + id + " = " + value);
|
|
alfresco.AjaxHelper.sendRequest("XFormsBean.setXFormsValue",
|
|
{ id: id, value: value },
|
|
true,
|
|
this._handleEventLog.bindAsEventListener(this));
|
|
},
|
|
|
|
/** Handles the xforms event log resulting from a call to the XFormsBean. */
|
|
_handleEventLog: function(events)
|
|
{
|
|
events = events.documentElement;
|
|
var prototypeClones = [];
|
|
var generatedIds = null;
|
|
for (var i = 0; i < events.childNodes.length; i++)
|
|
{
|
|
if (events.childNodes[i].nodeType != document.ELEMENT_NODE)
|
|
{
|
|
continue;
|
|
}
|
|
var xfe = new alfresco.xforms.XFormsEvent(events.childNodes[i]);
|
|
alfresco.log("parsing " + xfe.type +
|
|
"(" + xfe.targetId + ", " + xfe.targetName + ")");
|
|
switch (xfe.type)
|
|
{
|
|
case "chiba-index-changed":
|
|
{
|
|
var index = Number(xfe.properties["index"]);
|
|
try
|
|
{
|
|
xfe.getTarget().handleIndexChanged(index);
|
|
}
|
|
catch (e)
|
|
{
|
|
alfresco.log(e);
|
|
}
|
|
break;
|
|
}
|
|
case "chiba-state-changed":
|
|
{
|
|
alfresco.log("handleStateChanged(" + xfe.targetId + ")");
|
|
xfe.getTarget().setModified(true);
|
|
if ("valid" in xfe.properties)
|
|
{
|
|
xfe.getTarget().setValid(xfe.properties["valid"] == "true");
|
|
}
|
|
if ("required" in xfe.properties)
|
|
{
|
|
xfe.getTarget().setRequired(xfe.properties["required"] == "true");
|
|
}
|
|
if ("readonly" in xfe.properties)
|
|
{
|
|
xfe.getTarget().setReadonly(xfe.properties["readonly"] == "true");
|
|
}
|
|
if ("enabled" in xfe.properties)
|
|
{
|
|
xfe.getTarget().setEnabled(xfe.properties["enabled"] == "true");
|
|
}
|
|
if ("value" in xfe.properties)
|
|
{
|
|
alfresco.log("setting " + xfe.getTarget().id + " = " + xfe.properties["value"]);
|
|
xfe.getTarget().setValue(xfe.properties["value"]);
|
|
}
|
|
break;
|
|
}
|
|
case "chiba-prototype-cloned":
|
|
{
|
|
var prototypeId = xfe.properties["prototypeId"];
|
|
var originalId = xfe.properties["originalId"];
|
|
alfresco.log("handlePrototypeCloned(" + xfe.targetId +
|
|
", " + originalId +
|
|
", " + prototypeId + ")");
|
|
var clone = null;
|
|
var prototypeNode = _findElementById(this.xformsNode, prototypeId);
|
|
if (prototypeNode)
|
|
{
|
|
alfresco.log("cloning prototype " + prototypeNode.getAttribute("id"));
|
|
clone = prototypeNode.cloneNode(true);
|
|
}
|
|
else
|
|
{
|
|
alfresco.log("cloning prototype " + originalId);
|
|
var prototypeNode = _findElementById(this.xformsNode, originalId);
|
|
//clone = prototypeNode.cloneNode(true);
|
|
clone = prototypeNode.ownerDocument.createElement(alfresco.xforms.constants.XFORMS_PREFIX + ":group");
|
|
clone.setAttribute(alfresco.xforms.constants.XFORMS_PREFIX + ":appearance", "repeated");
|
|
for (var j = 0; j < prototypeNode.childNodes.length; j++)
|
|
{
|
|
clone.appendChild(prototypeNode.childNodes[j].cloneNode(true));
|
|
}
|
|
clone.setAttribute("id", prototypeId);
|
|
}
|
|
|
|
if (clone == null)
|
|
{
|
|
throw new Error("unable to clone prototype " + prototypeId);
|
|
}
|
|
|
|
alfresco.log("created clone " + clone.getAttribute("id") +
|
|
" nodeName " + clone.nodeName +
|
|
" parentClone " + (prototypeClones.length != 0
|
|
? prototypeClones.peek().getAttribute("id")
|
|
: null));
|
|
prototypeClones.push(clone);
|
|
break;
|
|
}
|
|
case "chiba-id-generated":
|
|
{
|
|
var originalId = xfe.properties["originalId"];
|
|
|
|
alfresco.log("handleIdGenerated(" + xfe.targetId + ", " + originalId + ")");
|
|
var node = _findElementById(prototypeClones.peek(), originalId);
|
|
if (!node)
|
|
{
|
|
throw new Error("unable to find " + originalId +
|
|
" in clone " + dojo.dom.innerXML(clone));
|
|
}
|
|
alfresco.log("applying id " + xfe.targetId +
|
|
" to " + node.nodeName + "(" + originalId + ")");
|
|
node.setAttribute("id", xfe.targetId);
|
|
generatedIds = generatedIds || new Object();
|
|
generatedIds[xfe.targetId] = originalId;
|
|
if (prototypeClones.length != 1)
|
|
{
|
|
var e = _findElementById(prototypeClones[prototypeClones.length - 2], originalId);
|
|
if (e)
|
|
{
|
|
e.setAttribute(alfresco.xforms.constants.ALFRESCO_PREFIX + ":prototype", "true");
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case "chiba-item-inserted":
|
|
{
|
|
var position = Number(xfe.properties["position"]) - 1;
|
|
var originalId = xfe.properties["originalId"];
|
|
var clone = prototypeClones.pop();
|
|
// walk all nodes of the clone and ensure that they have generated ids.
|
|
// those that do not are nested repeats that should not be added
|
|
if ((clone.getAttribute("id") in generatedIds) == false)
|
|
{
|
|
throw new Error("expected clone id " + clone.getAttribute("id") +
|
|
" to be a generated id");
|
|
}
|
|
|
|
function _removeNonGeneratedChildNodes(node, ids)
|
|
{
|
|
var child = node.firstChild;
|
|
while (child)
|
|
{
|
|
var next = child.nextSibling;
|
|
if (child.nodeType == document.ELEMENT_NODE)
|
|
{
|
|
if (child.getAttribute("id") in ids)
|
|
{
|
|
_removeNonGeneratedChildNodes(child, ids);
|
|
}
|
|
else
|
|
{
|
|
node.removeChild(child);
|
|
}
|
|
}
|
|
child = next;
|
|
}
|
|
};
|
|
_removeNonGeneratedChildNodes(clone, generatedIds);
|
|
|
|
if (prototypeClones.length != 0)
|
|
{
|
|
alfresco.log("using parentClone " + prototypeClones.peek().getAttribute("id") +
|
|
" of " + clone.getAttribute("id"));
|
|
var parentRepeat = _findElementById(prototypeClones.peek(), xfe.targetId);
|
|
parentRepeat.appendChild(clone);
|
|
}
|
|
else
|
|
{
|
|
alfresco.log("no parentClone found, directly insert " + clone.getAttribute("id") +
|
|
" on " + xfe.targetId);
|
|
xfe.getTarget().handleItemInserted(clone, position);
|
|
}
|
|
break;
|
|
}
|
|
case "chiba-item-deleted":
|
|
{
|
|
var position = Number(xfe.properties["position"]) - 1;
|
|
xfe.getTarget().handleItemDeleted(position);
|
|
break;
|
|
}
|
|
case "chiba-replace-all":
|
|
{
|
|
if (this.submitWidget)
|
|
{
|
|
this.submitWidget.done = true;
|
|
this.submitWidget.currentButton.click();
|
|
}
|
|
break;
|
|
}
|
|
case "chiba-switch-toggled":
|
|
{
|
|
var switchElement = xfe.getTarget();
|
|
switchElement.handleSwitchToggled(xfe.properties["selected"],
|
|
xfe.properties["deselected"]);
|
|
}
|
|
case "xforms-valid":
|
|
{
|
|
xfe.getTarget().setValid(true);
|
|
xfe.getTarget().setModified(true);
|
|
break;
|
|
}
|
|
case "xforms-invalid":
|
|
{
|
|
xfe.getTarget().setValid(false);
|
|
xfe.getTarget().setModified(true);
|
|
break;
|
|
}
|
|
case "xforms-required":
|
|
{
|
|
xfe.getTarget().setRequired(true);
|
|
break;
|
|
}
|
|
case "xforms-optional":
|
|
{
|
|
xfe.getTarget().setRequired(false);
|
|
break;
|
|
}
|
|
case "xforms-submit-error":
|
|
{
|
|
this.submitWidget = null;
|
|
var invalid_widgets = this.rootWidget.getWidgetsInvalidForSubmit();
|
|
_show_error(document.createTextNode(alfresco.resources["validation_provide_values_for_required_fields"]));
|
|
var error_list = document.createElement("ul");
|
|
invalid_widgets.each(function(invalid)
|
|
{
|
|
var error_item = document.createElement("li");
|
|
error_item.appendChild(document.createTextNode(invalid.getAlert()));
|
|
error_list.appendChild(error_item);
|
|
invalid.showAlert();
|
|
});
|
|
_show_error(error_list);
|
|
break;
|
|
}
|
|
case "xforms-readonly":
|
|
{
|
|
xfe.getTarget().setReadonly(true);
|
|
break;
|
|
}
|
|
case "xforms-readwrite":
|
|
{
|
|
xfe.getTarget().setReadonly(false);
|
|
break;
|
|
}
|
|
case "xforms-submit":
|
|
case "xforms-submit-done":
|
|
case "xforms-enabled":
|
|
case "xforms-disabled":
|
|
break;
|
|
default:
|
|
{
|
|
alfresco.log("unhandled event " + events.childNodes[i].nodeName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// error message display management
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/** hides the error message display. */
|
|
function _hide_errors()
|
|
{
|
|
var errorDiv = $(alfresco.xforms.constants.XFORMS_ERROR_DIV_ID);
|
|
if (errorDiv)
|
|
{
|
|
errorDiv.empty();
|
|
errorDiv.style.display = "none";
|
|
}
|
|
}
|
|
|
|
/** shows the error message display. */
|
|
function _show_error(msg)
|
|
{
|
|
var errorDiv = $(alfresco.xforms.constants.XFORMS_ERROR_DIV_ID);
|
|
if (!errorDiv)
|
|
{
|
|
errorDiv = new Element("div", { "id": alfresco.xforms.constants.XFORMS_ERROR_DIV_ID });
|
|
errorDiv.addClass("infoText statusErrorText xformsError");
|
|
errorDiv.injectBefore($(alfresco.xforms.constants.XFORMS_UI_DIV_ID));
|
|
}
|
|
|
|
if (errorDiv.style.display == "block")
|
|
{
|
|
errorDiv.appendChild(document.createElement("br"));
|
|
}
|
|
else
|
|
{
|
|
errorDiv.style.display = "block";
|
|
}
|
|
errorDiv.appendChild(msg);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// DOM utilities - XXXarielb should be merged into common.js
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function _findElementById(node, id)
|
|
{
|
|
// alfresco.log("looking for " + id +
|
|
// " in " + (node ? node.nodeName : null) +
|
|
// "(" + (node ? node.getAttribute("id") : null) + ")");
|
|
if (node.getAttribute("id") == id)
|
|
{
|
|
return node;
|
|
}
|
|
for (var i = 0; i < node.childNodes.length; i++)
|
|
{
|
|
if (node.childNodes[i].nodeType == document.ELEMENT_NODE)
|
|
{
|
|
var n = _findElementById(node.childNodes[i], id);
|
|
if (n)
|
|
{
|
|
return n;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function _hasAttribute(node, name)
|
|
{
|
|
return (node == null
|
|
? false
|
|
: (node.hasAttribute
|
|
? node.hasAttribute(name)
|
|
: node.getAttribute(name) != null));
|
|
}
|
|
|
|
function _getElementsByTagNameNS(parentNode, ns, nsPrefix, tagName)
|
|
{
|
|
return (parentNode.getElementsByTagNameNS
|
|
? parentNode.getElementsByTagNameNS(ns, tagName)
|
|
: parentNode.getElementsByTagName(nsPrefix + ":" + tagName));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// XPath wrapper
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function _evaluateXPath(xpath, contextNode, result_type)
|
|
{
|
|
var xmlDocument = contextNode.ownerDocument;
|
|
if (alfresco.constants.DEBUG)
|
|
{
|
|
alfresco.log("evaluating xpath " + xpath +
|
|
" on node " + contextNode.nodeName +
|
|
" in document " + xmlDocument);
|
|
}
|
|
var result = null;
|
|
if (xmlDocument.evaluate)
|
|
{
|
|
var nsResolver = (xmlDocument.createNSResolver
|
|
? xmlDocument.createNSResolver(xmlDocument.documentElement)
|
|
: null);
|
|
result = xmlDocument.evaluate(xpath,
|
|
contextNode,
|
|
nsResolver,
|
|
result_type,
|
|
null);
|
|
if (result)
|
|
{
|
|
switch (result_type)
|
|
{
|
|
case XPathResult.FIRST_ORDERED_NODE_TYPE:
|
|
result = result.singleNodeValue;
|
|
break;
|
|
case XPathResult.BOOLEAN_TYPE:
|
|
result = result.booleanValue;
|
|
break;
|
|
case XPathResult.STRING_TYPE:
|
|
result = result.stringValue;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xmlDocument.setProperty("SelectionLanguage", "XPath");
|
|
var namespaces = [];
|
|
for (var i = 0; i < xmlDocument.documentElement.attributes.length; i++)
|
|
{
|
|
var attr = xmlDocument.documentElement.attributes[i];
|
|
if (attr.nodeName.match(/^xmlns:/))
|
|
{
|
|
namespaces.push(attr.nodeName + "=\'" + attr.nodeValue + "\'");
|
|
}
|
|
}
|
|
|
|
if (alfresco.constants.DEBUG)
|
|
{
|
|
alfresco.log("using namespaces " + namespaces.join(","));
|
|
}
|
|
xmlDocument.setProperty("SelectionNamespaces", namespaces.join(' '));
|
|
if (result_type == XPathResult.FIRST_ORDERED_NODE_TYPE)
|
|
{
|
|
result = xmlDocument.selectSingleNode(xpath);
|
|
}
|
|
else if (result_type == XPathResult.BOOLEAN_TYPE)
|
|
{
|
|
result = true;
|
|
}
|
|
}
|
|
alfresco.log("resolved xpath " + xpath + " to " + result);
|
|
return result;
|
|
}
|
|
|
|
if (!XPathResult)
|
|
{
|
|
var XPathResult =
|
|
{
|
|
ANY_TYPE: 0,
|
|
NUMBER_TYPE: 1,
|
|
STRING_TYPE: 2,
|
|
BOOEAN_TYPE: 3,
|
|
FIRST_ORDERED_NODE_TYPE: 9
|
|
};
|
|
}
|
|
|
|
dojo.html.toCamelCase = function(str)
|
|
{
|
|
return str.replace(/-./, function(str) { return str.charAt(1).toUpperCase(); });
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// tiny mce integration
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
alfresco.constants.TINY_MCE_DEFAULT_PLUGINS =
|
|
alfresco.xforms.RichTextEditor.determineNecessaryTinyMCEPlugins(alfresco.xforms.widgetConfig);
|
|
|
|
alfresco.constants.TINY_MCE_DEFAULT_SETTINGS =
|
|
{
|
|
theme: "advanced",
|
|
mode: "exact",
|
|
plugins: alfresco.constants.TINY_MCE_DEFAULT_PLUGINS,
|
|
width: -1,
|
|
height: -1,
|
|
auto_resize: false,
|
|
force_p_newlines: false,
|
|
forced_root_block: false,
|
|
encoding: "UTF-8",
|
|
entity_encoding: "raw",
|
|
add_unload_trigger: false,
|
|
add_form_submit_trigger: false,
|
|
theme_advanced_toolbar_location: "top",
|
|
theme_advanced_toolbar_align: "left",
|
|
theme_advanced_buttons1: "fullscreen,table",
|
|
theme_advanced_buttons2: "",
|
|
theme_advanced_buttons3: "",
|
|
urlconverter_callback: "alfresco_TinyMCE_urlconverter_callback",
|
|
file_browser_callback: "alfresco_TinyMCE_file_browser_callback",
|
|
setup : function(ed)
|
|
{
|
|
// Fix for issue in browsers where content is not saved after fullscreen mode is toggled off
|
|
ed.onSetContent.add(function(ed, o) {
|
|
//if fullscreen plugin is available and o has these values, then we're coming out of fullscreen mode only
|
|
if ((ed.settings.plugins.indexOf('fullscreen')!=-1) && o.set && o.format==='raw' && o.initial===undefined)
|
|
{
|
|
alfresco.xforms.RichTextEditor.currentInstance._commitValueChange(alfresco.xforms.RichTextEditor.currentInstance.getValue());
|
|
}
|
|
});
|
|
|
|
}
|
|
};
|
|
|
|
tinyMCE.init($extend({}, alfresco.constants.TINY_MCE_DEFAULT_SETTINGS));
|
|
|
|
window.addEvent("domready",
|
|
function()
|
|
{
|
|
document.xform = new alfresco.xforms.XForm();
|
|
});
|