You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by we...@apache.org on 2010/05/14 12:54:34 UTC
svn commit: r944200 [1/3] - in /myfaces/core/trunk/api/src: assembler/
main/javascript/META-INF/resources/myfaces/_impl/_util/
main/javascript/META-INF/resources/myfaces/_impl/core/
main/javascript/META-INF/resources/myfaces/_impl/xhrCore/ main/javascr...
Author: werpu
Date: Fri May 14 10:54:32 2010
New Revision: 944200
URL: http://svn.apache.org/viewvc?rev=944200&view=rev
Log:
https://issues.apache.org/jira/browse/MYFACES-2715
https://issues.apache.org/jira/browse/MYFACES-2716
Added:
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_UnitTest.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js
Modified:
myfaces/core/trunk/api/src/assembler/jsfscripts-compiler.xml
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_HtmlStripper.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_ListenerQueue.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/jsf_impl.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxRequest.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxRequestQueue.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxUtils.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_Exception.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_xhrCoreAdapter.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/api/jsf.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/api/readme.txt
Modified: myfaces/core/trunk/api/src/assembler/jsfscripts-compiler.xml
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/assembler/jsfscripts-compiler.xml?rev=944200&r1=944199&r2=944200&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/assembler/jsfscripts-compiler.xml (original)
+++ myfaces/core/trunk/api/src/assembler/jsfscripts-compiler.xml Fri May 14 10:54:32 2010
@@ -1,12 +1,34 @@
<?xml version="1.0"?>
<assembler>
<scripts>
+ <!--
+ Assembly for our javascripts
+ if you want to include them manually use:
+
+
+ <script type="text/javascript" src="./myfaces/_impl/core/_Runtime.js"></script>
+ <script type = "text/javascript" src = "myfaces/_impl/_util/_Lang.js"></script>
+ <script type = "text/javascript" src = "./myfaces/_impl/_util/_ListenerQueue.js"></script>
+ <script type = "text/javascript" src = "./myfaces/_impl/_util/_Dom.js"></script>
+ <script type = "text/javascript" src = "./myfaces/_impl/_util/_HtmlStripper.js"></script>
+
+ <script type = "text/javascript" src = "./myfaces/_impl/xhrCore/_Exception.js"></script>
+ <script type = "text/javascript" src = "./myfaces/_impl/xhrCore/_AjaxUtils.js"></script>
+ <script type = "text/javascript" src = "./myfaces/_impl/xhrCore/_AjaxRequestQueue.js"></script>
+ <script type = "text/javascript" src = "./myfaces/_impl/xhrCore/_AjaxRequest.js"></script>
+ <script type = "text/javascript" src = "./myfaces/_impl/xhrCore/_AjaxResponse.js"></script>
+ <script type = "text/javascript" src = "./myfaces/_impl/xhrCore/_xhrCoreAdapter.js"></script>
+ <script type = "text/javascript" src = "./myfaces/_impl/core/jsf_impl.js"></script>
+ <script type = "text/javascript" src = "./myfaces/api/jsf.js"></script>
+ -->
+
<script>
<fileName>jsf.js</fileName>
<includes>
- <include>**/_impl/_util/_LangUtils.js</include>
+ <include>**/_impl/core/_Runtime.js</include>
+ <include>**/_impl/_util/_Lang.js</include>
<include>**/_impl/_util/_ListenerQueue.js</include>
- <include>**/_impl/_util/_Utils.js</include>
+ <include>**/_impl/_util/_Dom.js</include>
<include>**/_impl/_util/_HtmlStripper.js</include>
<include>**/_impl/xhrCore/_Exception.js</include>
<include>**/_impl/xhrCore/_AjaxUtils.js</include>
Added: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js?rev=944200&view=auto
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js (added)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js Fri May 14 10:54:32 2010
@@ -0,0 +1,804 @@
+myfaces._impl.core._Runtime.singletonExtendClass("myfaces._impl._util._Dom", Object, {
+ _ieQuircksEvents : {
+ "onabort": true,
+ "onload":true,
+ "onunload":true,
+ "onchange": true,
+ "onsubmit": true,
+ "onreset": true,
+ "onselect": true,
+ "onblur": true,
+ "onfocus": true,
+ "onkeydown": true,
+ "onkeypress": true,
+ "onkeyup": true,
+ "onclick": true,
+ "ondblclick": true,
+ "onmousedown": true,
+ "onmousemove": true,
+ "onmouseout": true,
+ "onmouseover": true,
+ "onmouseup": true
+ },
+
+ /**
+ * Run through the given Html item and execute the inline scripts
+ * (IE doesn't do this by itself)
+ * @param {|Node|} item
+ */
+ runScripts: function(item) {
+ var childIteration = myfaces._impl._util._Lang.hitch(this, function(item) {
+ var child = item.firstChild;
+ while (child) {
+ this.runScripts(child);
+ child = child.nextSibling;
+ }
+ });
+
+ if (item.nodeType == 1) { // only if it's an element node or document fragment
+ if ('undefined' != typeof item.tagName && item.tagName.toLowerCase() == 'script') {
+
+ if (typeof item.getAttribute('src') != 'undefined'
+ && item.getAttribute('src') != null
+ && item.getAttribute('src').length > 0) {
+ // external script auto eval
+ myfaces._impl.core._Runtime.loadScript(item.getAttribute('src'), item.getAttribute('type'), false, "ISO-8859-1");
+ } else {
+ // embedded script auto eval
+ var test = item.text;
+ var go = true;
+ while (go) {
+ go = false;
+ if (test.substring(0, 1) == " ") {
+ test = test.substring(1);
+ go = true;
+ }
+ if (test.substring(0, 4) == "<!--") {
+ test = test.substring(4);
+ go = true;
+ }
+ if (test.substring(0, 11) == "//<![CDATA[") {
+ test = test.substring(11);
+ go = true;
+ }
+ }
+ // we have to run the script under a global context
+ myfaces._impl.core._Runtime.globalEval(test); // run the script
+ }
+ } else {
+ childIteration(item);
+ }
+ } else {
+ childIteration(item);
+ }
+ },
+
+ /**
+ * Simple delete on an existing item
+ */
+ deleteItem: function(request, context, itemIdToReplace) {
+ var item = document.getElementById(itemIdToReplace);
+ if (item == null) {
+ myfaces._impl._util._Lang.throwNewWarning
+ (request, context, "Utils", "deleteItem", "Unknown Html-Component-ID: " + itemIdToReplace);
+ return;
+ }
+
+ item.parentNode.removeChild(item);
+ },
+
+ /**
+ * outerHTML replacement which works cross browserlike
+ * but still is speed optimized
+ *
+ * @param item the item to be replaced
+ * @param markup the markup for the replacement
+ */
+ outerHTML : function(item, markup) {
+ markup = myfaces._impl._util._Lang.trim(markup);
+ if ('undefined' == typeof item || null == item) {
+ throw Error("myfaces._impl._util._Dom.outerHTML: item must be passed down");
+ }
+ if ('undefined' == typeof markup || null == markup) {
+ throw Error("myfaces._impl._util._Dom.outerHTML: markup must be passed down");
+ }
+
+ if (markup != "") {
+ var evalNode = null;
+
+ //w3c compliant browsers with proper contextual fragments
+ var parentNode;
+ if (typeof window.Range != 'undefined'
+ && typeof Range.prototype.createContextualFragment == 'function') {
+ var range = document.createRange();
+ range.setStartBefore(item);
+ var fragment = range.createContextualFragment(markup);
+ //special case update body, we have to replace the placeholder
+ //with the first element (the place holder is the the only child)
+ //and then append additional elements as additional childs
+ //the body itself then is the root for the eval part!
+ if (item.id == 'myfaces_bodyplaceholder') {
+ parentNode = item.parentNode;
+ parentNode.appendChild(fragment);
+ evalNode = parentNode;
+ } else {
+ //normal dom node case we replace only the client id fragment!
+
+ parentNode = item.parentNode;
+
+ evalNode = fragment.childNodes[0];
+ parentNode.replaceChild(fragment, item);
+ }
+ } else {
+
+ //now to the non w3c compliant browsers
+ //http://blogs.perl.org/users/clinton_gormley/2010/02/forcing-ie-to-accept-script-tags-in-innerhtml.html
+ var dummyPlaceHolder = document.createElement("div");
+
+ //fortunately a table element also works which is less critical than form elements regarding
+ //the inner content
+ dummyPlaceHolder.innerHTML = "<table>" + markup + "</table>";
+ evalNode = dummyPlaceHolder.childNodes[0].childNodes[0].childNodes[0];
+ parentNode = item.parentNode;
+ item.parentNode.replaceChild(evalNode, item);
+
+ //if this as well will fail in the future, we can let ie parse a proper xml
+ //extract the script elements and then create the script elements manually
+ //but for now we will not need it, and this solution is faster
+ //the downside of that solution would be that the fragment itself
+ //must resolve to a valid xml
+ }
+
+ // and remove the old item
+ //first we have to save the node newly insert for easier access in our eval part
+ if (myfaces._impl.core._Runtime.isManualScriptEval()) {
+ this.runScripts(evalNode);
+ }
+ return evalNode;
+ }
+ // and remove the old item, in case of an empty newtag and do nothing else
+ item.parentNode.removeChild(item);
+ return null;
+ },
+
+ /**
+ * finds a corresponding html item from a given identifier and
+ * dom fragment
+ * @param fragment the dom fragment to find the item for
+ * @param itemId the identifier of the item
+ */
+ findById : function(fragment, itemId) {
+
+ var filter = function(node) {
+ return 'undefined' != typeof node.id && node.id === itemId;
+ };
+
+ return this.findFirst(fragment, filter);
+ },
+
+ /**
+ * findfirst functionality, finds the first element
+ * for which the filter can trigger
+ *
+ * @param fragment the processed fragment/domNode
+ * @param filter a filter closure which either returns true or false depending on triggering or not
+ */
+ findFirst : function(fragment, filter) {
+ myfaces._impl._util._Lang._assertType(filter, "function");
+
+ if (document.createTreeWalker && NodeFilter) {
+ //we have a tree walker in place this allows for an optimized deep scan
+ var lastElementFound = null;
+ var treeWalkerfilter = function (node) {
+ return ((filter(node)) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP);
+ };
+
+ var treeWalker = document.createTreeWalker(fragment, NodeFilter.SHOW_ELEMENT, treeWalkerfilter, false);
+ if (treeWalker.nextNode()) {
+ return treeWalker.currentNode;
+ }
+ return null;
+ }
+
+ if (filter(fragment)) {
+ return fragment;
+ }
+
+ if (fragment.childNodes == null)
+ return null;
+
+ //sub-fragment usecases
+ var child;
+ var cnt;
+ var childLen = fragment.childNodes.length;
+ for (cnt = 0; cnt < childLen; cnt++) {
+ child = fragment.childNodes[cnt];
+ var item = this.findFirst(child, filter);
+ if (item != null)
+ return item;
+ }
+ return null;
+ },
+
+ /**
+ * determines the number of nodes according to their tagType
+ *
+ * @param {Node} fragment (Node or fragment) the fragment to be investigated
+ * @param {String} tagName the tag name (lowercase)
+ * @param {Boolean} deepScan if set to true a found element does not prevent to scan deeper
+ * (the normal usecase is false, which means if the element is found only its
+ * adjacent elements will be scanned, due to the recursive descension
+ * this should work out with elements with different nesting depths but not being
+ * parent and child to each other
+ *
+ * TODO rename to getElementsByTagName
+ * TODO add iterator handlers here for browsers which allow dom filters and iterators
+ */
+ findByTagName : function(fragment, tagName, deepScan) {
+ var _Lang = myfaces._impl._util._Lang;
+ var filter = function(node) {
+ return _Lang.exists(node, "tagName") && _Lang.equalsIgnoreCase(node.tagName, tagName);
+ };
+
+ if ('undefined' == typeof deepScan) {
+ deepScan = false;
+ }
+
+ return this.findAll(fragment, filter, deepScan);
+
+ },
+
+ findByName : function(fragment, name, deepScan) {
+ var _Lang = myfaces._impl._util._Lang;
+ var filter = function(node) {
+ return _Lang.exists(node, "name") && _Lang.equalsIgnoreCase(node.name, name);
+ };
+ if ('undefined' == typeof deepScan) {
+ deepScan = false;
+ }
+
+ return this.findAll(fragment, filter, deepScan);
+ },
+
+ /**
+ * finds the elements by an attached style class
+ *
+ * @param fragment the source fragment which is the root of our search (included in the search)
+ * @param styleClass the styleclass to search for
+ * @param deepScan if set to true a deep scan can be performed
+ */
+ findByStyleClass : function(fragment, styleClass, deepScan) {
+ var _Lang = myfaces._impl._util._Lang;
+ var filter = _Lang.hitch(this, function(node) {
+ var classes = this.getClasses(node);
+ var len = classes.length;
+ if (len == 0) return false;
+ else {
+ for (var cnt = 0; cnt < len; cnt++) {
+ if (classes[cnt] === styleClass) return true;
+ }
+ }
+ return false;
+ });
+
+ if ('undefined' == typeof deepScan) {
+ deepScan = false;
+ }
+
+ return this.findAll(fragment, filter, deepScan);
+ },
+
+ /**
+ * a filtered findAll for subdom treewalking
+ * (which uses browser optimizations wherever possible)
+ *
+ * @param {|Node|} rootNode the rootNode so start the scan
+ * @param filter filter closure with the syntax {boolean} filter({Node} node)
+ * @param deepScan if set to true or not set at all a deep scan is performed (for form scans it does not make much sense to deeply scan)
+ */
+ findAll : function(rootNode, filter, deepScan) {
+ var retVal = [];
+ var _Lang = myfaces._impl._util._Lang;
+
+ _Lang._assertType(filter, "function");
+
+ /*
+ one of my unit tests causing the treewalker to hang, have to fix that
+ before issuing that code
+ if (document.createTreeWalker && NodeFilter) {
+ //Works on firefox and webkit, opera and ie have to use the slower fallback mechanis
+ //we have a tree walker in place this allows for an optimized deep scan
+ var lastElementFound = null;
+ if (filter(rootNode)) {
+ lastElementFound = rootNode;
+ retVal.push(rootNode);
+ }
+
+ var treeWalkerfilter = function (node) {
+ _Lang.logInfo(node.className, "-", deepScan);
+ if (!deepScan && lastElementFound != null && node.parentNode == lastElementFound) {
+ return NodeFilter.FILTER_REJECT;
+ }
+
+ var retVal = (filter(node)) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
+ if (retVal == NodeFilter.FILTER_ACCEPT) {
+ lastElementFound = node;
+ }
+ return retVal;
+ };
+
+ var treeWalker = document.createTreeWalker(rootNode, NodeFilter.SHOW_ELEMENT, treeWalkerfilter, false);
+ int cnt = 0;
+ while (treeWalker.nextNode()) {
+
+ retVal.push(treeWalker.currentNode);
+
+ }
+ return retVal;
+ } */
+
+ //fix the value to prevent undefined errors
+ if ('undefined' == typeof deepScan) {
+ deepScan = true;
+ }
+
+ if (filter(rootNode)) {
+ retVal.push(rootNode);
+ if (!deepScan) return retVal;
+ }
+
+ //
+ if (!_Lang.exists(rootNode, "childNodes"))
+ return retVal;
+
+ //subfragment usecases
+
+ var retValLen = retVal.length;
+ var childLen = rootNode.childNodes.length;
+ for (var cnt = 0; (deepScan || retValLen == 0) && cnt < childLen; cnt++) {
+ var childNode = rootNode.childNodes[cnt];
+ var subRetVals = this.findAll(childNode, filter, deepScan);
+ retVal = retVal.concat(subRetVals);
+ }
+ return retVal;
+ },
+
+ /**
+ *
+ * @param {Node} form
+ * @param {String} nameOrIdenitifier
+ *
+ * checks for a a element with the name or identifier of nameOrIdentifier
+ * @returns the found node or null otherwise
+ */
+ findFormElement : function(form, nameOrIdenitifier) {
+ var eLen = form.elements.length;
+ //TODO add iterator handlers here for browsers which allow dom filters and iterators
+
+ for (var e = 0; e < eLen; e++) {
+ var elem = form.elements[e];
+ if ('undefined' != typeof elem.name && elem.name === nameOrIdenitifier) return elem;
+ if ('undefined' != typeof elem.id && elem.id === nameOrIdenitifier) return elem;
+ } // end of for (formElements)
+ return null;
+ },
+
+ /**
+ * bugfixing for ie6 which does not cope properly with setAttribute
+ */
+ setAttribute : function(domNode, attribute, value) {
+
+ //quirks mode and ie7 mode has the attributes problems ie8 standards mode behaves like
+ //a good citizen
+ if (!myfaces._impl.core._Runtime.browser.isIE || myfaces._impl.core._Runtime.browser.isIE > 7) {
+ domNode.setAttribute(attribute, value);
+ return;
+ }
+ var _Lang = myfaces._impl._util._Lang;
+ /*
+ Now to the broken browsers IE6+.... ie7 and ie8 quirks mode
+
+ we deal mainly with three problems here
+ class and for are not handled correctly
+ styles are arrays and cannot be set directly
+ and javascript events cannot be set via setAttribute as well!
+
+ or in original words of quirksmode.org ... this is a mess!
+
+ Btw. thank you Microsoft for providing all necessary tools for free
+ for being able to debug this entire mess in the ie rendering engine out
+ (which is the Microsoft ie vms, developers toolbar, Visual Web Developer 2008 express
+ and the ie8 8 developers toolset!)
+
+ also thank you http://www.quirksmode.org/
+ dojotoolkit.org and //http://delete.me.uk/2004/09/ieproto.html
+ for additional information on this mess!
+
+ The lowest common denominator tested within this code
+ is IE6, older browsers for now are legacy!
+ */
+ attribute = attribute.toLowerCase();
+
+ if (attribute === "class") {
+ domNode.setAttribute("className", value);
+ } else if (attribute === "for") {
+
+ domNode.setAttribute("htmlFor", value);
+ } else if (attribute === "style") {
+ //We have to split the styles here and assign them one by one
+ var styleEntries = value.split(";");
+ var styleEntriesLen = styleEntries.length;
+ for (var loop = 0; loop < styleEntriesLen; loop++) {
+ var keyVal = styleEntries[loop].split(":");
+ if (keyVal[0] != "" && keyVal[0] == "opacity") {
+ //special ie quirks handling for opacity
+
+ var opacityVal = Math.max(100, Math.round(parseFloat(keyVal[1]) * 10));
+ domNode.style.setAttribute("filter", "alpha(opacity=" + opacityVal + ")");
+ //if you need more hacks I would recommend
+ //to use the class attribute and conditional ie includes!
+ } else if (keyVal[0] != "") {
+ domNode.style.setAttribute(keyVal[0], keyVal[1]);
+ }
+ }
+ } else {
+ //check if the attribute is an event, since this applies only
+ //to quirks mode of ie anyway we can live with the standard html4/xhtml
+ //ie supported events
+ if (this._ieQuircksEvents[attribute]) {
+ if (_Lang.isString(attribute)) {
+ domNode.setAttribute(attribute, function(event) {
+ //event implicitly used
+ return eval(value);
+ });
+ }
+ } else {
+ //unknown cases we try to catch them via standard setAttributes
+ domNode.setAttribute(attribute, value);
+ }
+ }
+ },
+
+ /**
+ * gets an element from a form with its id -> sometimes two elements have got
+ * the same id but are located in different forms -> MyFaces 1.1.4 two forms ->
+ * 2 inputHidden fields with ID jsf_tree_64 & jsf_state_64 ->
+ * http://www.arcknowledge.com/gmane.comp.jakarta.myfaces.devel/2005-09/msg01269.html
+ * @param {Object} request
+ * @param {Object} context (Map)
+ * @param {String} itemIdOrName - ID of the HTML element located inside the form
+ * @param {Node} form - form element containing the element
+ * @param {boolean} nameSearch if set to true a search for name is also done
+ * @param {boolean} localSearchOnly if set to true a local search is performed only (a full document search is omitted)
+ * @return {Object} the element if found else null
+ *
+ */
+ getElementFromForm : function(request, context, itemIdOrName, form, nameSearch, localSearchOnly) {
+ var _Lang = myfaces._impl._util._Lang;
+ try {
+
+ if ('undefined' == typeof form || form == null) {
+ return document.getElementById(itemIdOrName);
+ }
+ if ('undefined' == typeof nameSearch || nameSearch == null) {
+ nameSearch = false;
+ }
+ if ('undefined' == typeof localSearchOnly || localSearchOnly == null) {
+ localSearchOnly = false;
+ }
+
+ var fLen = form.elements.length;
+
+ //we first check for a name entry!
+
+
+ //'undefined' != typeof form.elements[itemIdOrName] && null != form.elements[itemIdOrName]
+ if (nameSearch && _Lang.exists(form, "elements." + itemIdOrName)) {
+ return form.elements[itemIdOrName];
+ }
+ //if no name entry is found we check for an Id
+ for (var f = 0; f < fLen; f++) {
+ var element = form.elements[f];
+ if (_Lang.exists(element, "id") && element.id == itemIdOrName) {
+ return element;
+ }
+ }
+ // element not found inside the form -> try document.getElementById
+ // (kann be null if element doesn't exist)
+ if (!localSearchOnly) {
+ return document.getElementById(itemIdOrName);
+ }
+ } catch (e) {
+ _Lang.throwNewError(request, context, "Utils", "getElementFromForm", e);
+ }
+ return null;
+ },
+
+ /**
+ * fuzzy form detection which tries to determine the form
+ * an item has been detached.
+ *
+ * The problem is some Javascript libraries simply try to
+ * detach controls by reusing the names
+ * of the detached input controls. Most of the times,
+ * the name is unique in a jsf scenario, due to the inherent form mapping.
+ * One way or the other, we will try to fix that by
+ * identifying the proper form over the name
+ *
+ * We do it in several ways, in case of no form null is returned
+ * in case of multiple forms we check all elements with a given name (which we determine
+ * out of a name or id of the detached element) and then iterate over them
+ * to find whether they are in a form or not.
+ *
+ * If only one element within a form and a given identifier found then we can pull out
+ * and move on
+ *
+ * We cannot do much further because in case of two identical named elements
+ * all checks must fail and the first elements form is served.
+ *
+ * Note, this method is only triggered in case of the issuer or an ajax request
+ * is a detached element, otherwise already existing code has served the correct form.
+ *
+ * This method was added because of
+ * https://issues.apache.org/jira/browse/MYFACES-2599
+ * to support the integration of existing ajax libraries which do heavy dom manipulation on the
+ * controls side (Dojos Dijit library for instance).
+ *
+ * @param {Node} element - element as source, can be detached, undefined or null
+ *
+ * @return either null or a form node if it could be determined
+ */
+ fuzzyFormDetection : function(element) {
+ if (0 == document.forms.length) {
+ return null;
+ } else if (1 == document.forms.length) {
+ return document.forms[0];
+ }
+ if ('undefined' == typeof element || null == element) {
+ return null;
+ }
+ var _Lang = myfaces._impl._util._Lang;
+
+ //before going into the more complicated stuff we try the simple approach
+ if (!_Lang.isString(element)) {
+ return this.getParent(element, "form");
+ }
+
+ var submitIdentifier = (_Lang.exists(element, "id")) ? element.id : null;
+ var submitName = (_Lang.exists.exists(element, "name")) ? element.name : null;
+ //a framework in a detachment case also can replace an existing identifier element
+ // with a name element
+ submitName = ('undefined' == typeof submitName || null == submitName) ? submitIdentifier : submitName;
+ var foundForm;
+
+ if ('undefined' != typeof submitIdentifier && null != submitIdentifier && '' != submitIdentifier) {
+ //we have to assert that the element passed down is detached
+ var domElement = myfaces._impl._util._Lang.byId(submitIdentifier);
+ if ('undefined' != typeof domElement && null != domElement) {
+ foundForm = this.getParent(domElement, "form");
+ if (null != foundForm) return foundForm;
+ }
+ }
+
+ /**
+ * name check
+ */
+ var foundElements = new Array();
+
+ /**
+ * the lesser chance is the elements which have the same name
+ * (which is the more likely case in case of a brute dom replacement)
+ */
+ var namedFoundElements = document.getElementsByName(submitName);
+ if (null != namedFoundElements) {
+ for (var cnt = 0; cnt < namedFoundElements.length; cnt++) {
+ // we already have covered the identifier case hence we only can deal with names,
+ foundForm = this.getParent(namedFoundElements[cnt], "form");
+ if (null != foundForm) {
+ foundElements.push(foundForm);
+ }
+ }
+ }
+
+ if (null == foundElements || 0 == foundElements.length || foundElements.length > 1) {
+ return null;
+ }
+
+ return foundElements[0];
+ },
+
+ /**
+ * [STATIC]
+ * gets a parent of an item with a given tagname
+ * @param {Node} item - child element
+ * @param {String} tagNameToSearchFor - TagName of parent element
+ */
+ getParent : function(item, tagNameToSearchFor) {
+
+ if ('undefined' == typeof item || null == item) {
+ throw Error("myfaces._impl._util._Dom.getParent: item is null or undefined,this not allowed");
+ }
+
+ var _Lang = myfaces._impl._util._Lang;
+ var searchClosure = function(parentItem) {
+ return parentItem != null && _Lang.exists(parentItem, "tagName")
+ && _Lang.equalsIgnoreCase(parentItem.tagName, tagNameToSearchFor);
+ };
+
+ return this.getFilteredParent(item, searchClosure);
+ }
+ ,
+ /**
+ *
+ * @param item
+ * @param filter
+ */
+ getFilteredParent : function(item, filter) {
+ if ('undefined' == typeof item || null == item) {
+ throw Error("myfaces._impl._util._Dom.getParen: item is null or undefined,this not allowed");
+ }
+
+ //search parent tag parentName
+ var parentItem = ('undefined' != typeof item.parentNode) ? item.parentNode : null;
+
+ while ('undefined' != typeof parentItem && null != parentItem && !filter(parentItem)) {
+ parentItem = parentItem.parentNode;
+ }
+ if ('undefined' != typeof parentItem && null != parentItem) {
+ return parentItem;
+ } else {
+ return null;
+ }
+ },
+
+
+ /**
+ * @Deprecated
+ * @param item
+ * @param filter
+ */
+ getFilteredChild: function(item, filter) {
+ var childItems = item.childNodes;
+ if ('undefined' == typeof childItems || null == childItems) {
+ return null;
+ }
+ for (var c = 0, cLen = childItems.length; c < cLen; c++) {
+ if (filter(childItems[c])) {
+ return childItems[c];
+ }
+ }
+ return null;
+ },
+
+
+ /**
+ * [STATIC]
+ * gets the child of an item with a given tag name
+ * @param {Node} item - parent element
+ * @param {String} childName - TagName of child element
+ * @param {String} itemName - name attribute the child can have (can be null)
+ * @Deprecated
+ */
+ getChild: function(item, childName, itemName) {
+
+ function filter(node) {
+ return node.tagName != null
+ && node.tagName.toLowerCase() == childName
+ && (itemName == null || (itemName != null && itemName == node.getAttribute("name")));
+
+ }
+
+ return this.getFilteredChild(item, filter);
+ },
+
+
+
+ /**
+ * cross ported from dojo
+ * fetches an attribute from a node
+ *
+ * @param {String} node the node
+ * @param {String} attr the attribute
+ * @return the attributes value or null
+ */
+ getAttribute : function(/* HTMLElement */node, /* string */attr) {
+ // summary
+ // Returns the value of attribute attr from node.
+ node = this.byId(node);
+ // FIXME: need to add support for attr-specific accessors
+ if ((!node) || (!node.getAttribute)) {
+ // if(attr !== 'nwType'){
+ // alert("getAttr of '" + attr + "' with bad node");
+ // }
+ return null;
+ }
+ var ta = typeof attr == 'string' ? attr : new String(attr);
+
+ // first try the approach most likely to succeed
+ var v = node.getAttribute(ta.toUpperCase());
+ if ((v) && (typeof v == 'string') && (v != "")) {
+ return v; // string
+ }
+
+ // try returning the attributes value, if we couldn't get it as a string
+ if (v && v.value) {
+ return v.value; // string
+ }
+
+ // this should work on Opera 7, but it's a little on the crashy side
+ if ((node.getAttributeNode) && (node.getAttributeNode(ta))) {
+ return (node.getAttributeNode(ta)).value; // string
+ } else if (node.getAttribute(ta)) {
+ return node.getAttribute(ta); // string
+ } else if (node.getAttribute(ta.toLowerCase())) {
+ return node.getAttribute(ta.toLowerCase()); // string
+ }
+ return null; // string
+ },
+
+ /**
+ * checks whether the given node has an attribute attached
+ *
+ * @param {String|Object} node the node to search for
+ * @param {String} attr the attribute to search for
+ * @true if the attribute was found
+ */
+ hasAttribute : function(/* HTMLElement */node, /* string */attr) {
+ // summary
+ // Determines whether or not the specified node carries a value for the attribute in question.
+ return this.getAttribute(node, attr) ? true : false; // boolean
+ },
+
+ /**
+ * fetches the style class for the node
+ * cross ported from the dojo toolkit
+ * @param {String|Object} node the node to search
+ * @returns the className or ""
+ */
+ getClass : function(node) {
+ node = this.byId(node);
+ if (!node) {
+ return "";
+ }
+ var cs = "";
+ if (node.className) {
+ cs = node.className;
+ } else {
+ if (this.hasAttribute(node, "class")) {
+ cs = this.getAttribute(node, "class");
+ }
+ }
+ return cs.replace(/^\s+|\s+$/g, "");
+ },
+ /**
+ * fdtches the class for the node,
+ * cross ported from the dojo toolkit
+ * @param {String|Object}node the node to search
+ */
+ getClasses : function(node) {
+ var c = this.getClass(node);
+ return (c == "") ? [] : c.split(/\s+/g);
+ },
+
+ /**
+ * concatenation routine which concats all childnodes of a node which
+ * contains a set of CDATA blocks to one big string
+ * @param {Node} node the node to concat its blocks for
+ */
+ concatCDATABlocks
+ :
+ function(/*Node*/ node) {
+ var cDataBlock = [];
+ // response may contain several blocks
+ for (var i = 0; i < node.childNodes.length; i++) {
+ cDataBlock.push(node.childNodes[i].data);
+ }
+ return cDataBlock.join('');
+ }
+ ,
+
+ byId: function(identifier) {
+ return myfaces._impl._util._Lang.byId(identifier);
+ }
+});
+
Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_HtmlStripper.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_HtmlStripper.js?rev=944200&r1=944199&r2=944200&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_HtmlStripper.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_HtmlStripper.js Fri May 14 10:54:32 2010
@@ -55,15 +55,10 @@
* </p>
*/
-_reserveMyfacesNamespaces();
+myfaces._impl.core._Runtime.extendClass("myfaces._impl._util._HtmlStripper", Object, {
+ BEGIN_TAG: "html",
+ END_TAG: "lmth",
-if (!myfaces._impl._util._LangUtils.exists(myfaces._impl._util, "_HtmlStripper")) {
-
- myfaces._impl._util._HtmlStripper = function() {
- };
-
- myfaces._impl._util._HtmlStripper.prototype.BEGIN_TAG = "html";
- myfaces._impl._util._HtmlStripper.prototype.END_TAG = "lmth";
/**
* parses the token array
@@ -75,7 +70,7 @@ if (!myfaces._impl._util._LangUtils.exis
* note in the subroutines the tokenPos must be at the last char of the operation
* so that the
*/
- myfaces._impl._util._HtmlStripper.prototype.parse = function(theString, tagNameStart, tagNameEnd) {
+ parse : function(theString, tagNameStart, tagNameEnd) {
this.tokens = theString.split("");
this.tagAttributes = {};
@@ -88,10 +83,8 @@ if (!myfaces._impl._util._LangUtils.exis
this._tokenForward = 1;
-
-
if ('undefined' == typeof tagNameStart || null == tagNameStart) {
- this.tagNameStart = myfaces._impl._util._HtmlStripper.prototype.BEGIN_TAG;
+ this.tagNameStart = this.prototype.BEGIN_TAG;
} else {
this.tagNameStart = tagNameStart;
}
@@ -119,33 +112,33 @@ if (!myfaces._impl._util._LangUtils.exis
}
return this.tokens.slice(this._contentStart, this._contentEnd + 1).join("");
- };
+ },
/**
* fetches the content block which has been parsed
*/
- myfaces._impl._util._HtmlStripper.prototype.getContentBlock = function() {
+ getContentBlock : function() {
return this.tokens.slice(this._contentStart, this._contentEnd + 1).join("");
},
/**
* fetches the content tag block including the tag code
*/
- myfaces._impl._util._HtmlStripper.prototype.getContentTagBlock = function() {
+ getContentTagBlock : function() {
return this.tokens.slice(this._tagStart, this._tagEnd + 1).join("");
},
/**
* fetches the block before the tag begin
*/
- myfaces._impl._util._HtmlStripper.prototype.getPreTagBlock = function() {
+ getPreTagBlock : function() {
return this.tokens.slice(0, this._tagStart).join("");
},
/**
* fetches the block after the tag end
*/
- myfaces._impl._util._HtmlStripper.prototype.getPostTagBlock = function() {
+ getPostTagBlock : function() {
return this.tokens.slice(this._tagEnd, this.tokens.length).join("");
},
@@ -155,7 +148,7 @@ if (!myfaces._impl._util._LangUtils.exis
* a ... normal chars should not occur here, but
* in the long run for deeper parsing they might happen!
*/
- myfaces._impl._util._HtmlStripper.prototype.handleInstructionBlock = function() {
+ handleInstructionBlock : function() {
var len = this.tokens.length;
for (; this._contentStart < 0 && this._tokenPos < len && this._tokenPos >= 0; this._tokenPos += this._tokenForward) {
this._skipBlank();
@@ -164,12 +157,12 @@ if (!myfaces._impl._util._LangUtils.exis
this.handleDocument();
}
}
- };
+ },
/**
* it is either a datablock or a content tag from which we can start parsing
*/
- myfaces._impl._util._HtmlStripper.prototype.handleDocument = function() {
+ handleDocument : function() {
this._tagStart = this.tokenPos;
this._skipBlank(1);
@@ -185,7 +178,7 @@ if (!myfaces._impl._util._LangUtils.exis
default: this.handleContentTag();
}
- };
+ },
/**
* we can skip definitions or comments!
@@ -197,7 +190,7 @@ if (!myfaces._impl._util._LangUtils.exis
* and definitions followed by nothing else
*
*/
- myfaces._impl._util._HtmlStripper.prototype.handleDataBlock = function() {
+ handleDataBlock : function() {
this._skipBlank(1);
if (this._tokenPos >= this.tokens.length || this._tokenPos < 0) {
@@ -215,13 +208,13 @@ if (!myfaces._impl._util._LangUtils.exis
break;
}
- };
+ },
/**
* doc definition ==
* <! [^>] >
*/
- myfaces._impl._util._HtmlStripper.prototype.handleDocDefinition = function() {
+ handleDocDefinition : function() {
this._skipBlank();
if (this._tokenPos >= this.tokens.length || this._tokenPos < 0) {
@@ -240,7 +233,7 @@ if (!myfaces._impl._util._LangUtils.exis
this._tokenPos += this._tokenForward;
}
- };
+ },
/**
* General tag andling section
@@ -252,7 +245,7 @@ if (!myfaces._impl._util._LangUtils.exis
* on head and body sections and within head (which is skipped)
* we neither can have code or pre segments!
*/
- myfaces._impl._util._HtmlStripper.prototype.handleContentTag = function() {
+ handleContentTag : function() {
//lookahead head, body, html which means a lookahead of 4;
this._currentSection = null;
this._skipBlank();
@@ -264,7 +257,7 @@ if (!myfaces._impl._util._LangUtils.exis
this.handleIdentifiedContent();
//after the html tag is processed we can break from the first parsing stage
this.tokenPos = this.tokens.length;
- } else if (tagName == "scri" || tagName == "styl") {
+ } else if (tagName == "scri" || tagName == "styl") {
//script must be handled separately since we can have embedded tags which must be ignored
this.handleScriptStyle();
} else {
@@ -272,7 +265,7 @@ if (!myfaces._impl._util._LangUtils.exis
//and then be done with it!
this.skipToTagEnd();
}
- };
+ },
/**
* script skipping routine...
@@ -283,7 +276,7 @@ if (!myfaces._impl._util._LangUtils.exis
*
*
*/
- myfaces._impl._util._HtmlStripper.prototype.handleScriptStyle = function() {
+ handleScriptStyle : function() {
this.skipToTagEnd();
//singleToken??
if (this.tokens[this._tokenPos - 1] == "/" && this.tokens[this._tokenPos] == ">") {
@@ -305,7 +298,7 @@ if (!myfaces._impl._util._LangUtils.exis
} while (this.tokens[this._tokenPos] != "<");
//now we should be at the end of the script tag at any circumstances!
this.skipToTagEnd();
- };
+ },
/**
* javascript comment handler
@@ -317,7 +310,7 @@ if (!myfaces._impl._util._LangUtils.exis
* then oh well, syntax error on the javascript side
* we cannot do anything about it
*/
- myfaces._impl._util._HtmlStripper.prototype.handleJSComment = function() {
+ handleJSComment : function() {
var token = this._getCurrentToken();
var prefetchToken = this.tokens[this._tokenPos + 1];
var backtrackToken = this.tokens[this._tokenPos - 1];
@@ -348,7 +341,7 @@ if (!myfaces._impl._util._LangUtils.exis
}
}
}
- };
+ },
/*----------------- reverse parsing --------*/
@@ -356,7 +349,7 @@ if (!myfaces._impl._util._LangUtils.exis
* the end block tos a bottom up resolution of the parsing process
* via an inverted tag name to look for
*/
- myfaces._impl._util._HtmlStripper.prototype.handleEndBlock = function() {
+ handleEndBlock : function() {
for (; this._tokenPos >= 0; this._tokenPos += this._tokenForward) {
this._skipBlank(0);
var token = this._getCurrentToken();
@@ -364,9 +357,9 @@ if (!myfaces._impl._util._LangUtils.exis
this.handleEndTagPart();
}
}
- };
+ },
- myfaces._impl._util._HtmlStripper.prototype.handleEndTagPart = function() {
+ handleEndTagPart : function() {
this._tagEnd = this._tokenPos;
this._skipBlank(1);
@@ -386,9 +379,9 @@ if (!myfaces._impl._util._LangUtils.exis
default: this.handleContentEnd();
}
- };
+ },
- myfaces._impl._util._HtmlStripper.prototype.handleContentEnd = function() {
+ handleContentEnd : function() {
var tagFound = false;
var first = true;
for (; this._tokenPos >= 0; this._skipBlank(1)) {
@@ -408,7 +401,7 @@ if (!myfaces._impl._util._LangUtils.exis
}
}
- };
+ },
/*----------------- helpers ----------------*/
/**
@@ -418,7 +411,7 @@ if (!myfaces._impl._util._LangUtils.exis
* a map of determined key value pairs which we then can further process
* otherwise the key value pair determination is ignored!
*/
- myfaces._impl._util._HtmlStripper.prototype.skipToTagEnd = function(analyzeAttributes) {
+ skipToTagEnd : function(analyzeAttributes) {
var token = this._getCurrentToken();
//faster shortcut for tags which have to be nont analyzed
@@ -455,13 +448,13 @@ if (!myfaces._impl._util._LangUtils.exis
this._tokenPos += this._tokenForward;
}
return keyValuePairs;
- };
+ },
/**
* fetches a word which either can be a string or
* a sequence of non string characters until either = or > or blank is reached!
*/
- myfaces._impl._util._HtmlStripper.prototype._fetchWord = function() {
+ _fetchWord : function() {
this._skipBlank(0);
var result = [];
@@ -471,25 +464,25 @@ if (!myfaces._impl._util._LangUtils.exis
this._tokenPos += this._tokenForward;
return this.handleString(token)
}
-
+
result.push(token);
this._tokenPos += this._tokenForward;
token = this._getCurrentToken();
}
return result.join("");
- };
+ },
- myfaces._impl._util._HtmlStripper.prototype._isBlank = function() {
+ _isBlank : function() {
var token = this._getCurrentToken();
return token == " " && token == "\t" && token == "\n";
- };
+ },
/**
* we can make speedup shorcut assumptions here
* becase we only try to either identfy head
* html or body!
*/
- myfaces._impl._util._HtmlStripper.prototype.handleIdentifiedContent = function() {
+ handleIdentifiedContent : function() {
this.tagAttributes = this.skipToTagEnd(true);
//TODO trace down the attributes and store them
@@ -502,16 +495,16 @@ if (!myfaces._impl._util._LangUtils.exis
} else {
this._contentStart = this._tokenPos + 1;
}
- };
+ },
/**
* returns true if the current token is a string start!
*/
- myfaces._impl._util._HtmlStripper.prototype._isStringStart = function() {
+ _isStringStart : function() {
var backTrack = (this._tokenPos > 0) ? this.tokens[this._tokenPos - 1] : null;
var token = this.tokens[this._tokenPos];
return (token == "'" || token == '"') && backTrack != "\\";
- };
+ },
/**
* skips a string section cintentwise no matter how many other strings
@@ -520,7 +513,7 @@ if (!myfaces._impl._util._LangUtils.exis
* @param {String} stringToken the string token to skip!
* @return the string value without the enclosing hypenations to be processed later on
*/
- myfaces._impl._util._HtmlStripper.prototype.handleString = function(stringToken) {
+ handleString : function(stringToken) {
var backTrack = null;
var resultString = [];
while (this.tokens[this._tokenPos] != stringToken || backTrack == "\\") {
@@ -533,17 +526,17 @@ if (!myfaces._impl._util._LangUtils.exis
}
this._getCurrentToken();
return resultString.join("");
- };
+ },
- myfaces._impl._util._HtmlStripper.prototype._assertValues = function(assertValues) {
+ _assertValues : function(assertValues) {
for (var loop = 0; loop < assertValues.length; loop++) {
this._assertValue(assertValues[loop]);
this._skipBlank(1);
}
- };
+ },
- myfaces._impl._util._HtmlStripper.prototype._assertValue = function(expectedToken) {
+ _assertValue : function(expectedToken) {
var token = this._getCurrentToken();
this._assertLength();
if (token != expectedToken) {
@@ -551,20 +544,20 @@ if (!myfaces._impl._util._LangUtils.exis
}
return token;
- };
+ },
- myfaces._impl._util._HtmlStripper.prototype._assertLength = function() {
+ _assertLength : function() {
if (this._tokenPos >= this.tokens.length) {
throw Error("Invalid html comment opened but not closed");
}
- };
+ },
/**
* nested comments are not allowed hence we
* skip them!
* comment == "<!--" [-->] "-->"
*/
- myfaces._impl._util._HtmlStripper.prototype.handleComment = function(reverse) {
+ handleComment : function(reverse) {
this._assertValues(["-","-"]);
if ('undefined' == typeof reverse || null == reverse) {
reverse = false;
@@ -600,14 +593,14 @@ if (!myfaces._impl._util._LangUtils.exis
this._skipBlank(1);
}
}
- };
+ },
/**
* fetches and stores the current token
*/
- myfaces._impl._util._HtmlStripper.prototype._getCurrentToken = function() {
+ _getCurrentToken : function() {
return this.tokens[this._tokenPos];
- };
+ },
/**
* skip blank until the next token is found
@@ -615,7 +608,7 @@ if (!myfaces._impl._util._LangUtils.exis
* 1 means it skips 1 no matter if the current token is a blank or not!
*
*/
- myfaces._impl._util._HtmlStripper.prototype._skipBlank = function(skipVal) {
+ _skipBlank : function(skipVal) {
var len = this.tokens.length;
if ('undefined' == typeof skipVal || null == skipVal) {
skipVal = 0;
@@ -627,9 +620,9 @@ if (!myfaces._impl._util._LangUtils.exis
return;
}
}
- };
+ },
- myfaces._impl._util._HtmlStripper.prototype._fetchTagname = function() {
+ _fetchTagname : function() {
var tagName = [];
//TODO make the tagname prefetch more generic
@@ -645,5 +638,9 @@ if (!myfaces._impl._util._LangUtils.exis
tagName = tagName.join("").toLowerCase();
return tagName;
- };
-}
\ No newline at end of file
+ }
+
+});
+
+
+
Added: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js?rev=944200&view=auto
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js (added)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js Fri May 14 10:54:32 2010
@@ -0,0 +1,479 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * under the License.
+ */
+
+
+/*
+ theoretically we could save some code
+ by
+ defining the parent object as
+ var parent = new Object();
+ parent.prototype = new myfaces._impl.core._Runtime();
+ extendClass(function () {
+ }, parent , {
+ But for now we are not doing it the little bit of saved
+ space is not worth the loss of readability
+ */
+
+myfaces._impl.core._Runtime.singletonExtendClass("myfaces._impl._util._Lang", Object, {
+
+ fetchNamespace : function(namespacing) {
+ return myfaces._impl.core._Runtime.fetchNamespace(namespacing);
+ },
+
+ reserveNamespace : function(namespacing) {
+ return myfaces._impl.core._Runtime.reserveNamespace(namespacing);
+ },
+
+ globalEval : function(code) {
+ return myfaces._impl.core._Runtime.globalEval(code);
+ },
+
+ /**
+ * cross port from the dojo lib
+ * browser save event resolution
+ * @param event the event object
+ * (with a fallback for ie events if none is present)
+ */
+ getEventTarget: function(event) {
+ if (!event) {
+ //ie6 and 7 fallback
+ event = window.event || {};
+ }
+ var t = (event.srcElement ? event.srcElement : (event.target ? event.target : null));
+ while ((t) && (t.nodeType != 1)) {
+ t = t.parentNode;
+ }
+ return t;
+ },
+
+ /**
+ * check if an element exists in the root
+ */
+ exists : function(root, element) {
+ return myfaces._impl.core._Runtime.exists(root, element);
+ },
+
+ /**
+ @see myfaces._impl.core._Runtime.extendClass
+ */
+ singletonExtendClass : function(newClass, extendsClass, functionMap, inherited) {
+ return myfaces._impl.core._Runtime.singletonExtendClass(newClass, extendsClass, functionMap, inherited);
+ },
+
+
+ /**
+ * equalsIgnoreCase, case insensitive comparison of two strings
+ *
+ * @param source
+ * @param destination
+ * @param strongCompare
+ */
+ equalsIgnoreCase: function(source, destination) {
+ //either both are not set or null
+ if (!source && !destination) {
+ return true;
+ }
+ //source or dest is set while the other is not
+ if (!source || !destination) return false;
+
+ //in any other case we do a strong string comparison
+ return source.toLowerCase() === destination.toLowerCase();
+ },
+
+
+ /**
+ @see myfaces._impl.core._Runtime.extendClass
+ */
+ extendClass : function(newClass, extendsClass, functionMap, inherited) {
+ return myfaces._impl.core._Runtime.extendClass(newClass, extendsClass, functionMap, inherited);
+ },
+
+ //core namespacing and inheritance done, now to the language extensions
+
+ /**
+ * Save document.getElementById (this code was ported over from dojo)
+ * the idea is that either a string or domNode can be passed
+ * @param {Object} reference the reference which has to be byIded
+ */
+ byId : function(/*object*/ reference) {
+ if (this.isString(reference)) {
+ return document.getElementById(reference);
+ }
+ return reference;
+ },
+
+ /**
+ * backported from dojo
+ * Converts an array-like object (i.e. arguments, DOMCollection) to an
+ array. Returns a new Array with the elements of obj.
+ * @param {Object} obj the object to "arrayify". We expect the object to have, at a
+ minimum, a length property which corresponds to integer-indexed
+ properties.
+ * @param {int} offset the location in obj to start iterating from. Defaults to 0.
+ Optional.
+ * @param {Array} startWith An array to pack with the properties of obj. If provided,
+ properties in obj are appended at the end of startWith and
+ startWith is the returned array.
+ */
+ _toArray : function(obj, offset, startWith) {
+ // summary:
+ // Converts an array-like object (i.e. arguments, DOMCollection) to an
+ // array. Returns a new Array with the elements of obj.
+ // obj:
+ // the object to "arrayify". We expect the object to have, at a
+ // minimum, a length property which corresponds to integer-indexed
+ // properties.
+ // offset:
+ // the location in obj to start iterating from. Defaults to 0.
+ // Optional.
+ // startWith:
+ // An array to pack with the properties of obj. If provided,
+ // properties in obj are appended at the end of startWith and
+ // startWith is the returned array.
+ var arr = startWith || [];
+ for (var x = offset || 0; x < obj.length; x++) {
+ arr.push(obj[x]);
+ }
+ return arr; // Array
+ },
+
+ /**
+ * Helper function to provide a trim with a given splitter regular expression
+ * @param {|String|} it the string to be trimmed
+ * @param {|RegExp|} splitter the splitter regular expressiion
+ *
+ * FIXME is this still used?
+ */
+ trimStringInternal : function(it, splitter) {
+ return this.strToArray(it, splitter).join(splitter);
+ },
+
+ /**
+ * String to array function performs a string to array transformation
+ * @param {String} it the string which has to be changed into an array
+ * @param {RegExp} splitter our splitter reglar expression
+ * @return an array of the splitted string
+ */
+ strToArray : function(/*string*/ it, /*regexp*/ splitter) {
+ // summary:
+ // Return true if it is a String
+
+ if (!this.isString(it)) {
+ throw Error("myfaces._impl._util._Lang.strToArray param not of type string");
+ }
+ var resultArr = it.split(splitter);
+ var len = resultArr.length;
+ for (var cnt = 0; cnt < len; cnt++) {
+ resultArr[cnt] = this.trim(resultArr[cnt]);
+ }
+ return resultArr;
+ },
+
+ /**
+ * hyperfast trim
+ * http://blog.stevenlevithan.com/archives/faster-trim-javascript
+ * crossported from dojo
+ */
+ trim : function(/*string*/ str) {
+
+ str = str.replace(/^\s\s*/, '');
+ var ws = /\s/;
+ var i = str.length;
+ while (ws.test(str.charAt(--i)));
+ return str.slice(0, i + 1);
+ },
+
+ /**
+ * Splits a string and fetches the last element of the String
+ * @param {String} theString the string to be splitted
+ * @param {String} delimiter a delimiting string regexp
+ *
+ */
+ splitAndGetLast : function(theString, delimiter) {
+ var arr = theString.split(delimiter);
+ return arr[arr.length - 1];
+ },
+
+ /**
+ * Backported from dojo
+ * a failsafe string determination method
+ * (since in javascript String != "" typeof alone fails!)
+ * @param it {|Object|} the object to be checked for being a string
+ * @return true in case of being a string false otherwiseÊ
+ */
+ isString: function(/*anything*/ it) {
+ // summary:
+ // Return true if it is a String
+ return !!arguments.length && it != null && (typeof it == "string" || it instanceof String); // Boolean
+ },
+ /**
+ * hitch backported from dojo
+ * hitch allows to assign a function to a dedicated scope
+ * this is helpful in situations when function reassignments
+ * can happen
+ * (notably happens often in lazy xhr code)
+ *
+ * @param {Function} scope of the function to be executed in
+ * @param {Function} method to be executed
+ *
+ * @return whatevery the executed method returns
+ */
+ hitch : function(/*Object*/scope, /*Function|String*/method /*,...*/) {
+ // summary:
+ // Returns a function that will only ever execute in the a given scope.
+ // This allows for easy use of object member functions
+ // in callbacks and other places in which the "this" keyword may
+ // otherwise not reference the expected scope.
+ // Any number of default positional arguments may be passed as parameters
+ // beyond "method".
+ // Each of these values will be used to "placehold" (similar to curry)
+ // for the hitched function.
+ // scope:
+ // The scope to use when method executes. If method is a string,
+ // scope is also the object containing method.
+ // method:
+ // A function to be hitched to scope, or the name of the method in
+ // scope to be hitched.
+ // example:
+ // | myfaces._impl._util._Lang.hitch(foo, "bar")();
+ // runs foo.bar() in the scope of foo
+ // example:
+ // | myfaces._impl._util._Lang.hitch(foo, myFunction);
+ // returns a function that runs myFunction in the scope of foo
+ if (arguments.length > 2) {
+ return this._hitchArgs._hitchArgs.apply(this._hitchArgs, arguments); // Function
+ }
+ if (!method) {
+ method = scope;
+ scope = null;
+ }
+ if (this.isString(method)) {
+ scope = scope || window || function() {
+ };
+ /*since we do not have dojo global*/
+ if (!scope[method]) {
+ throw(['myfaces._impl._util._Lang: scope["', method, '"] is null (scope="', scope, '")'].join(''));
+ }
+ return function() {
+ return scope[method].apply(scope, arguments || []);
+ }; // Function
+ }
+ return !scope ? method : function() {
+ return method.apply(scope, arguments || []);
+ }; // Function
+ }
+ ,
+
+ _hitchArgs : function(scope, method /*,...*/) {
+ var pre = this._toArray(arguments, 2);
+ var named = this.isString(method);
+ return function() {
+ // array-fy arguments
+ var args = this._toArray(arguments);
+ // locate our method
+ var f = named ? (scope || this.global)[method] : method;
+ // invoke with collected args
+ return f && f.apply(scope || this, pre.concat(args)); // mixed
+ }; // Function
+ }
+ ,
+
+ /**
+ * Helper function to merge two maps
+ * into one
+ * @param {|Object|} destination the destination map
+ * @param {|Object|} source the source map
+ * @param {|boolean|} overwriteDest if set to true the destination is overwritten if the keys exist in both maps
+ **/
+ mixMaps : function(destination, source, overwriteDest) {
+ /**
+ * mixing code depending on the state of dest and the overwrite param
+ */
+ var _Lang = this;
+ var result = {};
+ var keyIdx = {};
+ var key = null;
+ for (key in source) {
+ /**
+ *we always overwrite dest with source
+ *unless overWrite is not set or source does not exist
+ *but also only if dest exists otherwise source still is taken
+ */
+ if (!overwriteDest) {
+ /**
+ *we use exists instead of booleans because we cannot rely
+ *on all values being non boolean, we would need an elvis
+ *operator in javascript to shorten this :-(
+ */
+ result[key] = _Lang.exists(dest, key) ? destination[key] : source[key];
+ } else {
+ result[key] = _Lang.exists(source, key) ? source[key] : destination[key];
+ }
+ keyIdx[key] = true;
+ }
+ for (key in destination) {
+ /*if result.key does not exist we push in dest.key*/
+ result[key] = _Lang.exists(result, key) ? result[key] : destination[key];
+ }
+ return result;
+ }
+ ,
+
+ /**
+ * checks if an array contains an element
+ * @param {Array} arr array
+ * @param {String} string_name string to check for
+ */
+ arrayContains : function(arr, string_name) {
+ for (var loop = 0; loop < arr.length; loop++) {
+ if (arr[loop] == string_name) {
+ return true;
+ }
+ }
+ return false;
+ }
+ ,
+
+ /**
+ * Concatenates an array to a string
+ * @param {Array} arr the array to be concatenated
+ * @param {String} delimiter the concatenation delimiter if none is set \n is used
+ *
+ * @return the concatenated array, one special behavior to enable j4fry compatibility has been added
+ * if no delimiter is used the [entryNumber]+entry is generated for a single entry
+ * TODO check if this is still needed it is somewhat outside of the scope of the function
+ * and functionality wise dirty
+ */
+ arrayToString : function(/*String or array*/ arr, /*string*/ delimiter) {
+ if (this.isString(arr)) {
+ return arr;
+ }
+ var finalDelimiter = (null == delimiter) ? "\n" : delimiter;
+
+ var resultArr = [];
+ for (var cnt = 0; cnt < arr.length; cnt ++) {
+ if (this.isString(arr[cnt])) {
+ resultArr.push(((delimiter == null) ? ("[" + cnt + "] ") : "") + arr[cnt]);
+ } else {
+ resultArr.push(((delimiter == null) ? ("[" + cnt + "] ") : "") + arr[cnt].toString());
+ }
+ }
+ return resultArr.join(finalDelimiter);
+ }
+ ,
+
+ /**
+ * general type assertion routine
+ *
+ * @param probe the probe to be checked for the correct type
+ * @param type the type to be checked for
+ */
+ _assertType : function(probe, type) {
+ if (type != typeof probe) {
+ throw Error("probe must be of type " + type);
+ }
+ },
+
+ /**
+ * [STATIC]
+ * static method used by static methods that throw errors
+ */
+ throwNewError : function(request, context, sourceClass, func, exception) {
+ var newException = new myfaces._impl.xhrCore._Exception(request, context, sourceClass, "ERROR");
+ newException.throwError(request, context, func, exception);
+ },
+
+ /**
+ * [STATIC]
+ * static method used by static methods that throw warnings
+ */
+ throwNewWarning: function(request, context, sourceClass, func, message) {
+ var newException = new myfaces._impl.xhrCore._Exception(request, context, sourceClass, "WARNING");
+ newException.throwWarning(request, context, func, message);
+ },
+
+ /**
+ * onload wrapper for chaining the onload cleanly
+ * @param func the function which should be added to the load
+ * chain (note we cannot rely on return values here, hence jsf.util.chain will fail)
+ */
+ addOnLoad: function(func) {
+ var oldonload = window.onload;
+ if (typeof window.onload != "function") {
+ window.onload = func;
+ } else {
+ window.onload = function() {
+ oldonload();
+ func();
+ }
+ }
+ },
+ /**
+ * Simple simple logging only triggering at
+ * firebug compatible logging consoles
+ *
+ * note: ;; means the code will be stripped
+ * from the production code by the build system
+ */
+ _logToContainer: function(styleClass /*+arguments*/, loggingArguments) {
+ var loggingContainer = document.getElementById("myfaces.logging");
+ if (loggingContainer) {
+ var element = document.createElement("div");
+ //element.className = styleClass;
+ element.innerHTML = loggingArguments.join(" ");
+ loggingContainer.appendChild(element);
+ }
+ },
+
+ logLog: function(/*varargs*/) {
+ var argumentStr = Array.prototype.slice.call(arguments, 0).join(" ");
+ if (window.console && window.console.log) {
+ window.console.log(argumentStr);
+ }
+ this._logToContainer("logLog", ["Log:"].concat([argumentStr]));
+ },
+ logDebug: function(/*varargs*/) {
+ var argumentStr = Array.prototype.slice.call(arguments, 0).join(" ");
+
+ if (window.console && window.console.log) {
+ window.console.debug(argumentStr);
+ }
+ this._logToContainer("logDebug", ["Debug:"].concat([argumentStr]));
+ },
+ logError: function(/*varargs*/) {
+ var argumentStr = Array.prototype.slice.call(arguments, 0).join(" ");
+
+ if (window.console && window.console.error) {
+ window.console.error(argumentStr);
+ }
+ this._logToContainer("logError", ["Error:"].concat([argumentStr]));
+
+ },
+ logInfo: function(/*varargs*/) {
+ var argumentStr = Array.prototype.slice.call(arguments, 0).join(" ");
+
+ if (window.console && window.console.info) {
+ window.console.info(argumentStr);
+ }
+ this._logToContainer("logInfo", ["Info:"].concat([argumentStr]));
+ },
+ logWarn: function(/*varargs*/) {
+ var argumentStr = Array.prototype.slice.call(arguments, 0).join(" ");
+ if (window.console && window.console.warn) {
+ window.console.warn(argumentStr);
+ }
+ this._logToContainer("logWarn", ["Warn:"].concat([argumentStr]));
+ }
+});
Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_ListenerQueue.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_ListenerQueue.js?rev=944200&r1=944199&r2=944200&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_ListenerQueue.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_ListenerQueue.js Fri May 14 10:54:32 2010
@@ -3,7 +3,7 @@
*/
-_reserveMyfacesNamespaces();
+
/**
* Simple listener queue with closures which shall be
@@ -12,71 +12,93 @@ _reserveMyfacesNamespaces();
* idea:
* var queue = new myfaces._impl._util._ListenerQueue();
*/
-if(!myfaces._impl._util._LangUtils.exists(myfaces, "_ListenerQueue")) {
- myfaces._impl._util._ListenerQueue = function() {
+myfaces._impl.core._Runtime.extendClass("myfaces._impl._util._ListenerQueue", Object, {
+ constructor_: function() {
this._queue = [];
+ },
- }
+ length: function() {
+ return this._queue.length;
+ },
- myfaces._impl._util._ListenerQueue.prototype._assertListener = function(/*function*/listener) {
- if("function" != typeof (listener)) {
+ /**
+ * listener type safety assertion function
+ *
+ * @param listener must be of type function otherwise an error is raised
+ */
+ _assertListener : function(/*function*/listener) {
+ if ("function" != typeof (listener)) {
throw Error("Error: myfaces._impl._util._ListenerQueue." + arguments.caller.toString() + "Parameter must be of type function");
}
- }
+ },
- myfaces._impl._util._ListenerQueue.prototype.add = function(/*function*/listener) {
- this._assertListener( listener);
+ /**
+ * adds a listener to the queue
+ *
+ * @param listener the listener to be added
+ */
+ add : function(/*function*/listener) {
+ this._assertListener(listener);
this._queue.push(listener);
- }
+ },
- myfaces._impl._util._ListenerQueue.prototype.remove = function(/*function*/listener) {
- this._assertListener( listener);
+ /**
+ * removes a listener form the queue
+ *
+ * @param listener the listener to be removed
+ */
+ remove : function(/*function*/listener) {
+ this._assertListener(listener);
/*find element in queue*/
var cnt = 0;
- while(cnt < this._queue.length && this._queue[cnt] != listener) {
+ var len = this._queue.length;
+ while (cnt < len && this._queue[cnt] != listener) {
cnt += 1;
}
/*found*/
- if(cnt < this._queue.length) {
+ if (cnt < len) {
this._queue[cnt] = null;
/*we remove the element now as fast as possible*/
this._queue.splice(cnt, 1);
}
- }
- /**
+ },
+
+ /**
* generic broadcast with a number of arguments being passed down
* @param scope the execution scope for the event callback
- * @param argument,...* the arguments list which has to be passed
+ * @param argument ,...* the arguments list which has to be passed
* down the queue function
*/
- myfaces._impl._util._ListenerQueue.prototype.broadcastScopedEvent = function(scope, /*any*/argument) {
- for(var cnt = 0; cnt < this._queue.length; cnt ++) {
+ broadcastScopedEvent : function(scope, /*any*/argument) {
+ for (var cnt = 0; cnt < this._queue.length; cnt ++) {
/**
* we call the original method under its original scope
* use hitch to keep the original scope in place
* because there is no way that I can keep it from here
**/
var varArgs = [];
- for(var argsCnt = 1; argsCnt < arguments.length; argsCnt++) {
+ var len = arguments.length;
+ for (var argsCnt = 1; argsCnt < len; argsCnt++) {
varArgs.push(arguments[argsCnt]);
}
this._queue[cnt].apply(scope, varArgs);
}
- }
+ },
/**
* generic broadcast with a number of arguments being passed down
*/
- myfaces._impl._util._ListenerQueue.prototype.broadcastEvent = function(/*any*/argument) {
- for(var cnt = 0; cnt < this._queue.length; cnt ++) {
+ broadcastEvent : function(/*any*/argument) {
+ var len = this._queue.length;
+ for (var cnt = 0; cnt < len; cnt ++) {
/**
* we call the original method under its original scope
* use hitch to keep the original scope in place
* because there is no way that I can keep it from here
**/
-
+
this._queue[cnt].apply(null, arguments);
}
}
-}
\ No newline at end of file
+});
\ No newline at end of file
Added: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_UnitTest.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_UnitTest.js?rev=944200&view=auto
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_UnitTest.js (added)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_UnitTest.js Fri May 14 10:54:32 2010
@@ -0,0 +1,26 @@
+/**
+ * This class is for http based unit tests
+ */
+myfaces._impl.core._Runtime.singletonExtendClass("myfaces._impl._util._UnitTest", Object, {
+ /**
+ *
+ */
+ assertTrue: function(message, assertionOutcome) {
+ var _Lang = myfaces._impl._util._Lang;
+
+ if (!assertionOutcome) {
+ _Lang.logError(message, "assertionOutcome:", assertionOutcome);
+ throw Error(message, assertionOutcome);
+ }
+ _Lang.logInfo(message, "assertionOutcome:", assertionOutcome);
+ },
+ assertFalse: function(message, assertionOutcome) {
+ var _Lang = myfaces._impl._util._Lang;
+
+ if (assertionOutcome) {
+ _Lang.logError(message, "assertionOutcome:", assertionOutcome);
+ throw Error(message, assertionOutcome);
+ }
+ _Lang.logInfo(message, "assertionOutcome:", assertionOutcome);
+ }
+});
\ No newline at end of file