1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 1997-2013 Sun Microsystems, Inc. All rights reserved.
5 *
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common Development
8 * and Distribution License("CDDL") (collectively, the "License"). You
9 * may not use this file except in compliance with the License. You can obtain
10 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
11 * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
12 * language governing permissions and limitations under the License.
13 *
14 * When distributing the software, include this License Header Notice in each
15 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
16 * Sun designates this particular file as subject to the "Classpath" exception
17 * as provided by Sun in the GPL Version 2 section of the License file that
18 * accompanied this code. If applicable, add the following below the License
19 * Header, with the fields enclosed by brackets [] replaced by your own
20 * identifying information: "Portions Copyrighted [year]
21 * [name of copyright owner]"
22 *
23 * Contributor(s):
24 *
25 * If you wish your version of this file to be governed by only the CDDL or
26 * only the GPL Version 2, indicate your decision by adding "[Contributor]
27 * elects to include this software in this distribution under the [CDDL or GPL
28 * Version 2] license." If you don't indicate a single choice of license, a
29 * recipient has the option to distribute your version of this file under
30 * either the CDDL, the GPL Version 2 or to extend the choice of license to
31 * its licensees as provided above. However, if you add GPL Version 2 code
32 * and therefore, elected the GPL Version 2 license, then the option applies
33 * only if the new code is made subject to such option by the copyright
34 * holder.
35 *
36 *
37 * This file incorporates work covered by the following copyright and
38 * permission notices:
39 *
40 * Copyright 2004 The Apache Software Foundation
41 * Copyright 2004-2008 Emmanouil Batsis, mailto: mbatsis at users full stop sourceforge full stop net
42 *
43 * Licensed under the Apache License, Version 2.0 (the "License");
44 * you may not use this file except in compliance with the License.
45 * You may obtain a copy of the License at
46 *
47 * http://www.apache.org/licenses/LICENSE-2.0
48 *
49 * Unless required by applicable law or agreed to in writing, software
50 * distributed under the License is distributed on an "AS IS" BASIS,
51 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
52 * See the License for the specific language governing permissions and
53 * limitations under the License.
54 */ 55 56/**
57 @project JSF JavaScript Library
58 @version 2.2
59 @description This is the standard implementation of the JSF JavaScript Library.
60 */ 61 62/**
63 * Register with OpenAjax
64 */ 65if(typeofOpenAjax!=="undefined"&& 66typeofOpenAjax.hub.registerLibrary!=="undefined"){ 67OpenAjax.hub.registerLibrary("jsf","www.sun.com","2.2",null); 68} 69 70// Detect if this is already loaded, and if loaded, if it's a higher version 71if(!((jsf&&jsf.specversion&&jsf.specversion>=20000)&& 72(jsf.implversion&&jsf.implversion>=3))){ 73 74/**
75 * <span class="changed_modified_2_2">The top level global namespace
76 * for JavaServer Faces functionality.</span>
77 78 * @name jsf
79 * @namespace
80 */ 81varjsf={}; 82 83/**
84 85 * <span class="changed_modified_2_2">The namespace for Ajax
86 * functionality.</span>
87 88 * @name jsf.ajax
89 * @namespace
90 * @exec
91 */ 92jsf.ajax=function(){ 93 94vareventListeners=[]; 95varerrorListeners=[]; 96 97vardelayHandler=null; 98/**
99 * Determine if the current browser is part of Microsoft's failed attempt at
100 * standards modification.
101 * @ignore
102 */103varisIE=functionisIE(){104if(typeofisIECache!=="undefined"){105returnisIECache;106}107isIECache=108document.all&&window.ActiveXObject&&109navigator.userAgent.toLowerCase().indexOf("msie")>-1&&110navigator.userAgent.toLowerCase().indexOf("opera")==-1;111returnisIECache;112};113varisIECache;114115/**
116 * Determine the version of IE.
117 * @ignore
118 */119vargetIEVersion=functiongetIEVersion(){120if(typeofIEVersionCache!=="undefined"){121returnIEVersionCache;122}123if(/MSIE ([0-9]+)/.test(navigator.userAgent)){124IEVersionCache=parseInt(RegExp.$1);125}else{126IEVersionCache=-1;127}128returnIEVersionCache;129}130varIEVersionCache;131132/**
133 * Determine if loading scripts into the page executes the script.
134 * This is instead of doing a complicated browser detection algorithm. Some do, some don't.
135 * @returns {boolean} does including a script in the dom execute it?
136 * @ignore
137 */138varisAutoExec=functionisAutoExec(){139try{140if(typeofisAutoExecCache!=="undefined"){141returnisAutoExecCache;142}143varautoExecTestString="<script>var mojarra = mojarra || {};mojarra.autoExecTest = true;</script>";144vartempElement=document.createElement('span');145tempElement.innerHTML=autoExecTestString;146varbody=document.getElementsByTagName('body')[0];147vartempNode=body.appendChild(tempElement);148if(mojarra&&mojarra.autoExecTest){149isAutoExecCache=true;150deletemojarra.autoExecTest;151}else{152isAutoExecCache=false;153}154deleteNode(tempNode);155returnisAutoExecCache;156}catch(ex){157// OK, that didn't work, we'll have to make an assumption158if(typeofisAutoExecCache==="undefined"){159isAutoExecCache=false;160}161returnisAutoExecCache;162}163};164varisAutoExecCache;165166/**
167 * @ignore
168 */169vargetTransport=functiongetTransport(context){170varreturnVal;171// Here we check for encoding type for file upload(s).172// This is where we would also include a check for the existence of173// input file control for the current form (see hasInputFileControl174// function) but IE9 (at least) seems to render controls outside of175// form.176if(typeofcontext!=='undefined'&&context!==null&&177context.form.enctype==="multipart/form-data"){178returnVal=newFrameTransport(context);179returnreturnVal;180}181varmethods=[182function(){183returnnewXMLHttpRequest();184},185function(){186returnnewActiveXObject('Msxml2.XMLHTTP');187},188function(){189returnnewActiveXObject('Microsoft.XMLHTTP');190}191];192193for(vari=0,len=methods.length;i<len;i++){194try{195returnVal=methods[i]();196}catch(e){197continue;198}199returnreturnVal;200}201thrownewError('Could not create an XHR object.');202};203204/**
205 * Used for iframe based communication (instead of XHR).
206 * @ignore
207 */208varFrameTransport=functionFrameTransport(context){209this.context=context;210this.frame=null;211this.FRAME_ID="JSFFrameId";212this.FRAME_PARTIAL_ID="Faces-Request";213this.partial=null;214this.aborted=false;215this.responseText=null;216this.responseXML=null;217this.readyState=null;218this.requestHeader={};219this.status=null;220this.method=null;221this.url=null;222this.requestParams=null;223};224225/**
226 * Extends FrameTransport an adds method functionality.
227 * @ignore
228 */229FrameTransport.prototype={230231/**
232 *@ignore
233 */234setRequestHeader:function(key,value){235if(typeof(value)!=="undefined"){236this.requestHeader[key]=value;237}238},239240/**
241 * Creates the hidden iframe and sets readystate.
242 * @ignore
243 */244open:function(method,url,async){245this.method=method;246this.url=url;247this.async=async;248this.frame=document.getElementById(this.FRAME_ID);249if(this.frame){250this.frame.parentNode.removeChild(this.frame);251this.frame=null;252}253if(!this.frame){254if((!isIE()&&!isIE9Plus())){255this.frame=document.createElement('iframe');256this.frame.src="about:blank";257this.frame.id=this.FRAME_ID;258this.frame.name=this.FRAME_ID;259this.frame.type="content";260this.frame.collapsed="true";261this.frame.style="visibility:hidden";262this.frame.width="0";263this.frame.height="0";264this.frame.style="border:0";265document.body.appendChild(this.frame);266this.frame.onload=bind(this,this.callback);267}else{268vardiv=document.createElement("div");269div.id="frameDiv";270div.innerHTML="<iframe id='"+this.FRAME_ID+"' name='"+this.FRAME_ID+"' style='display:none;' src='about:blank' type='content' onload='this.onload_cb();' ></iframe>";271document.body.appendChild(div);272this.frame=document.getElementById(this.FRAME_ID);273this.frame.onload_cb=bind(this,this.callback);274}275}276// Create to send "Faces-Request" param with value "partial/ajax"277// For iframe approach we are sending as request parameter278// For non-iframe (xhr ajax) it is sent in the request header279this.partial=document.createElement("input");280this.partial.setAttribute("type","hidden");281this.partial.setAttribute("id",this.FRAME_PARTIAL_ID);282this.partial.setAttribute("name",this.FRAME_PARTIAL_ID);283this.partial.setAttribute("value","partial/ajax");284this.context.form.appendChild(this.partial);285286this.readyState=1;287},288289/**
290 * Sets the form target to iframe, sets up request parameters
291 * and submits the form.
292 * @ignore
293 */294send:function(data){295varevt={};296this.context.form.target=this.frame.name;297this.context.form.method=this.method;298if(this.url){299this.context.form.action=this.url;300}301302this.readyState=3;303304this.onreadystatechange(evt);305306varddata=decodeURIComponent(data);307vardataArray=ddata.split("&");308varinput;309this.requestParams=newArray();310for(vari=0;i<dataArray.length;i++){311varnameValue=dataArray[i].split("=");312if(nameValue[0]==="javax.faces.source"||313nameValue[0]==="javax.faces.partial.event"||314nameValue[0]==="javax.faces.partial.execute"||315nameValue[0]==="javax.faces.partial.render"||316nameValue[0]==="javax.faces.partial.ajax"){317input=document.createElement("input");318input.setAttribute("type","hidden");319input.setAttribute("id",nameValue[0]);320input.setAttribute("name",nameValue[0]);321input.setAttribute("value",nameValue[1]);322this.context.form.appendChild(input);323this.requestParams.push(nameValue[0]);324}325}326this.requestParams.push(this.FRAME_PARTIAL_ID);327this.context.form.submit();328},329330/**
331 *@ignore
332 */333abort:function(){334this.aborted=true;335},336337/**
338 *@ignore
339 */340onreadystatechange:function(evt){341342},343344/**
345 * Extracts response from iframe document, sets readystate.
346 * @ignore
347 */348callback:function(){349if(this.aborted){350return;351}352variFrameDoc;353vardocBody;354try{355varevt={};356iFrameDoc=this.frame.contentWindow.document||357this.frame.contentDocument||this.frame.document;358docBody=iFrameDoc.body||iFrameDoc.documentElement;359this.responseText=docBody.innerHTML;360this.responseXML=iFrameDoc.XMLDocument||iFrameDoc;361this.status=201;362this.readyState=4;363364this.onreadystatechange(evt);365}finally{366this.cleanupReqParams();367this.frame=null;368369}370},371372/**
373 *@ignore
374 */375cleanupReqParams:function(){376for(vari=0;i<this.requestParams.length;i++){377varelements=this.context.form.childNodes;378for(varj=0;j<elements.length;j++){379if(!elements[j].type==="hidden"){380continue;381}382if(elements[j].name===this.requestParams[i]){383varnode=this.context.form.removeChild(elements[j]);384node=null;385break;386}387}388}389}390};391392393/**
394 *Utility function that binds function to scope.
395 *@ignore
396 */397varbind=function(scope,fn){398returnfunction(){399fn.apply(scope,arguments);400};401};402403/**
404 * Utility function that determines if a file control exists
405 * for the form.
406 * @ignore
407 */408varhasInputFileControl=function(form){409varreturnVal=false;410varinputs=form.getElementsByTagName("input");411if(inputs!==null&&typeofinputs!=="undefined"){412for(vari=0;i<inputs.length;i++){413if(inputs[i].type==="file"){414returnVal=true;415break;416}417}418}419returnreturnVal;420};421422/**
423 * Find instance of passed String via getElementById
424 * @ignore
425 */426var$=function$(){427varresults=[],element;428for(vari=0;i<arguments.length;i++){429element=arguments[i];430if(typeofelement=='string'){431element=document.getElementById(element);432}433results.push(element);434}435returnresults.length>1?results:results[0];436};437438/**
439 * Get the form element which encloses the supplied element.
440 * @param element - element to act against in search
441 * @returns form element representing enclosing form, or first form if none found.
442 * @ignore
443 */444vargetForm=functiongetForm(element){445if(element){446varform=$(element);447while(form){448449if(form.nodeName&&(form.nodeName.toLowerCase()=='form')){450returnform;451}452if(form.form){453returnform.form;454}455if(form.parentNode){456form=form.parentNode;457}else{458form=null;459}460}461returndocument.forms[0];462}463returnnull;464};465466/**
467 * Get the form element which encloses the supplied element
468 * identified by the supplied identifier.
469 * @param id - the element id to act against in search
470 * @returns form element representing enclosing form, or null if not found.
471 * @ignore
472 */473vargetFormForId=functiongetFormForId(id){474if(id){475varnode=document.getElementById(id);476while(node){477if(node.nodeName&&(node.nodeName.toLowerCase()=='form')){478returnnode;479}480if(node.form){481returnnode.form;482}483if(node.parentNode){484node=node.parentNode;485}else{486node=null;487}488}489}490returnnull;491};492493/**
494 * Check if a value exists in an array
495 * @ignore
496 */497varisInArray=functionisInArray(array,value){498for(vari=0;i<array.length;i++){499if(array[i]===value){500returntrue;501}502}503returnfalse;504};505506507/**
508 * Evaluate JavaScript code in a global context.
509 * @param src JavaScript code to evaluate
510 * @ignore
511 */512varglobalEval=functionglobalEval(src){513if(window.execScript){514window.execScript(src);515return;516}517// We have to wrap the call in an anon function because of a firefox bug, where this is incorrectly set518// We need to explicitly call window.eval because of a Chrome peculiarity519/**
520 * @ignore
521 */522varfn=function(){523window.eval.call(window,src);524};525fn();526};527528/**
529 * Get all scripts from supplied string, return them as an array for later processing.
530 * @param str
531 * @returns {array} of script text
532 * @ignore
533 */534varstripScripts=functionstripScripts(str){535// Regex to find all scripts in a string536varfindscripts=/<script[^>]*>([\S\s]*?)<\/script>/igm;537// Regex to find one script, to isolate it's content [2] and attributes [1]538varfindscript=/<script([^>]*)>([\S\s]*?)<\/script>/im;539// Regex to remove leading cruft540varstripStart=/^\s*(<!--)*\s*(\/\/)*\s*(\/\*)*\s*\n*\**\n*\s*\*.*\n*\s*\*\/(<!\[CDATA\[)*/;541// Regex to find src attribute542varfindsrc=/src="([\S]*?)"/im;543varfindtype=/type="([\S]*?)"/im;544varinitialnodes=[];545varscripts=[];546initialnodes=str.match(findscripts);547while(!!initialnodes&&initialnodes.length>0){548varscriptStr=[];549scriptStr=initialnodes.shift().match(findscript);550// check the type - skip if it not javascript type551vartype=[];552type=scriptStr[1].match(findtype);553if(!!type&&type[1]){554if(type[1]!=="text/javascript"){555continue;556}557}558varsrc=[];559// check if src specified560src=scriptStr[1].match(findsrc);561varscript;562if(!!src&&src[1]){563// if this is a file, load it564varurl=src[1];565// if this is another copy of jsf.js, don't load it566// it's never necessary, and can make debugging difficult567if(/\/javax.faces.resource\/jsf.js\?ln=javax\.faces/.test(url)){568script=false;569}else{570script=loadScript(url);571}572}elseif(!!scriptStr&&scriptStr[2]){573// else get content of tag, without leading CDATA and such574script=scriptStr[2].replace(stripStart,"");575}else{576script=false;577}578if(!!script){579scripts.push(script);580}581}582returnscripts;583};584585/**
586 * Load a script via a url, use synchronous XHR request. This is liable to be slow,
587 * but it's probably the only correct way.
588 * @param url the url to load
589 * @ignore
590 */591varloadScript=functionloadScript(url){592varxhr=getTransport(null);593if(xhr===null){594return"";595}596597xhr.open("GET",url,false);598xhr.setRequestHeader("Content-Type","application/x-javascript");599xhr.send(null);600601// PENDING graceful error handling602if(xhr.readyState==4&&xhr.status==200){603returnxhr.responseText;604}605606return"";607};608609/**
610 * Run an array of scripts text
611 * @param scripts array of script nodes
612 * @ignore
613 */614varrunScripts=functionrunScripts(scripts){615if(!scripts||scripts.length===0){616return;617}618619varhead=document.getElementsByTagName('head')[0]||document.documentElement;620while(scripts.length){621// create script node622varscriptNode=document.createElement('script');623scriptNode.type='text/javascript';624scriptNode.text=scripts.shift();// add the code to the script node625head.appendChild(scriptNode);// add it to the page626head.removeChild(scriptNode);// then remove it627}628};629630/**
631 * Replace DOM element with a new tagname and supplied innerHTML
632 * @param element element to replace
633 * @param tempTagName new tag name to replace with
634 * @param src string new content for element
635 * @ignore
636 */637varelementReplaceStr=functionelementReplaceStr(element,tempTagName,src){638639vartemp=document.createElement(tempTagName);640if(element.id){641temp.id=element.id;642}643644// Creating a head element isn't allowed in IE, and faulty in most browsers,645// so it is not allowed646if(element.nodeName.toLowerCase()==="head"){647thrownewError("Attempted to replace a head element - this is not allowed.");648}else{649varscripts=[];650if(isAutoExec()){651temp.innerHTML=src;652}else{653// Get scripts from text654scripts=stripScripts(src);655// Remove scripts from text656src=src.replace(/<script[^>]*type="text\/javascript"*>([\S\s]*?)<\/script>/igm,"");657temp.innerHTML=src;658}659}660661replaceNode(temp,element);662cloneAttributes(temp,element);663runScripts(scripts);664665};666667/**
668 * Get a string with the concatenated values of all string nodes under the given node
669 * @param oNode the given DOM node
670 * @param deep boolean - whether to recursively scan the children nodes of the given node for text as well. Default is <code>false</code>
671 * @ignore
672 * Note: This code originally from Sarissa: http://dev.abiss.gr/sarissa
673 * It has been modified to fit into the overall codebase
674 */675vargetText=functiongetText(oNode,deep){676varNode={ELEMENT_NODE:1,ATTRIBUTE_NODE:2,TEXT_NODE:3,CDATA_SECTION_NODE:4,677ENTITY_REFERENCE_NODE:5,ENTITY_NODE:6,PROCESSING_INSTRUCTION_NODE:7,678COMMENT_NODE:8,DOCUMENT_NODE:9,DOCUMENT_TYPE_NODE:10,679DOCUMENT_FRAGMENT_NODE:11,NOTATION_NODE:12};680681vars="";682varnodes=oNode.childNodes;683for(vari=0;i<nodes.length;i++){684varnode=nodes[i];685varnodeType=node.nodeType;686if(nodeType==Node.TEXT_NODE||nodeType==Node.CDATA_SECTION_NODE){687s+=node.data;688}elseif(deep===true&&(nodeType==Node.ELEMENT_NODE||689nodeType==Node.DOCUMENT_NODE||690nodeType==Node.DOCUMENT_FRAGMENT_NODE)){691s+=getText(node,true);692}693}694returns;695};696697varPARSED_OK="Document contains no parsing errors";698varPARSED_EMPTY="Document is empty";699varPARSED_UNKNOWN_ERROR="Not well-formed or other error";700vargetParseErrorText;701if(isIE()){702/**
703 * Note: This code orginally from Sarissa: http://dev.abiss.gr/sarissa
704 * @ignore
705 */706getParseErrorText=function(oDoc){707varparseErrorText=PARSED_OK;708if(oDoc&&oDoc.parseError&&oDoc.parseError.errorCode&&oDoc.parseError.errorCode!==0){709parseErrorText="XML Parsing Error: "+oDoc.parseError.reason+710"\nLocation: "+oDoc.parseError.url+711"\nLine Number "+oDoc.parseError.line+", Column "+712oDoc.parseError.linepos+713":\n"+oDoc.parseError.srcText+714"\n";715for(vari=0;i<oDoc.parseError.linepos;i++){716parseErrorText+="-";717}718parseErrorText+="^\n";719}720elseif(oDoc.documentElement===null){721parseErrorText=PARSED_EMPTY;722}723returnparseErrorText;724};725}else{// (non-IE)726727/**
728 * <p>Returns a human readable description of the parsing error. Useful
729 * for debugging. Tip: append the returned error string in a <pre>
730 * element if you want to render it.</p>
731 * @param oDoc The target DOM document
732 * @returns {String} The parsing error description of the target Document in
733 * human readable form (preformated text)
734 * @ignore
735 * Note: This code orginally from Sarissa: http://dev.abiss.gr/sarissa
736 */737getParseErrorText=function(oDoc){738varparseErrorText=PARSED_OK;739if((!oDoc)||(!oDoc.documentElement)){740parseErrorText=PARSED_EMPTY;741}elseif(oDoc.documentElement.tagName=="parsererror"){742parseErrorText=oDoc.documentElement.firstChild.data;743parseErrorText+="\n"+oDoc.documentElement.firstChild.nextSibling.firstChild.data;744}elseif(oDoc.getElementsByTagName("parsererror").length>0){745varparsererror=oDoc.getElementsByTagName("parsererror")[0];746parseErrorText=getText(parsererror,true)+"\n";747}elseif(oDoc.parseError&&oDoc.parseError.errorCode!==0){748parseErrorText=PARSED_UNKNOWN_ERROR;749}750returnparseErrorText;751};752}753754if((typeof(document.importNode)=="undefined")&&isIE()){755try{756/**
757 * Implementation of importNode for the context window document in IE.
758 * If <code>oNode</code> is a TextNode, <code>bChildren</code> is ignored.
759 * @param oNode the Node to import
760 * @param bChildren whether to include the children of oNode
761 * @returns the imported node for further use
762 * @ignore
763 * Note: This code orginally from Sarissa: http://dev.abiss.gr/sarissa
764 */765document.importNode=function(oNode,bChildren){766vartmp;767if(oNode.nodeName=='#text'){768returndocument.createTextNode(oNode.data);769}770else{771if(oNode.nodeName=="tbody"||oNode.nodeName=="tr"){772tmp=document.createElement("table");773}774elseif(oNode.nodeName=="td"){775tmp=document.createElement("tr");776}777elseif(oNode.nodeName=="option"){778tmp=document.createElement("select");779}780else{781tmp=document.createElement("div");782}783if(bChildren){784tmp.innerHTML=oNode.xml?oNode.xml:oNode.outerHTML;785}else{786tmp.innerHTML=oNode.xml?oNode.cloneNode(false).xml:oNode.cloneNode(false).outerHTML;787}788returntmp.getElementsByTagName("*")[0];789}790};791}catch(e){792}793}794// Setup Node type constants for those browsers that don't have them (IE)795varNode={ELEMENT_NODE:1,ATTRIBUTE_NODE:2,TEXT_NODE:3,CDATA_SECTION_NODE:4,796ENTITY_REFERENCE_NODE:5,ENTITY_NODE:6,PROCESSING_INSTRUCTION_NODE:7,797COMMENT_NODE:8,DOCUMENT_NODE:9,DOCUMENT_TYPE_NODE:10,798DOCUMENT_FRAGMENT_NODE:11,NOTATION_NODE:12};799800// PENDING - add support for removing handlers added via DOM 2 methods801/**
802 * Delete all events attached to a node
803 * @param node
804 * @ignore
805 */806varclearEvents=functionclearEvents(node){807if(!node){808return;809}810811// don't do anything for text and comment nodes - unnecessary812if(node.nodeType==Node.TEXT_NODE||node.nodeType==Node.COMMENT_NODE){813return;814}815816varevents=['abort','blur','change','error','focus','load','reset','resize','scroll','select','submit','unload',817'keydown','keypress','keyup','click','mousedown','mousemove','mouseout','mouseover','mouseup','dblclick'];818try{819for(vareinevents){820if(events.hasOwnProperty(e)){821node[e]=null;822}823}824}catch(ex){825// it's OK if it fails, at least we tried826}827};828829/**
830 * Determine if this current browser is IE9 or greater
831 * @param node
832 * @ignore
833 */834varisIE9Plus=functionisIE9Plus(){835variev=getIEVersion();836if(iev>=9){837returntrue;838}else{839returnfalse;840}841}842843844/**
845 * Deletes node
846 * @param node
847 * @ignore
848 */849vardeleteNode=functiondeleteNode(node){850if(!node){851return;852}853if(!node.parentNode){854// if there's no parent, there's nothing to do855return;856}857if(!isIE()||(isIE()&&isIE9Plus())){858// nothing special required859node.parentNode.removeChild(node);860return;861}862// The rest of this code is specialcasing for IE863if(node.nodeName.toLowerCase()==="body"){864// special case for removing body under IE.865deleteChildren(node);866try{867node.outerHTML='';868}catch(ex){869// fails under some circumstances, but not in RI870// supplied responses. If we've gotten here, it's871// fairly safe to leave a lingering body tag rather than872// fail outright873}874return;875}876vartemp=node.ownerDocument.createElement('div');877varparent=node.parentNode;878temp.appendChild(parent.removeChild(node));879// Now clean up the temporary element880try{881temp.outerHTML='';//prevent leak in IE882}catch(ex){883// at least we tried. Fails in some circumstances,884// but not in RI supplied responses. Better to leave a lingering885// temporary div than to fail outright.886}887};888889/**
890 * Deletes all children of a node
891 * @param node
892 * @ignore
893 */894vardeleteChildren=functiondeleteChildren(node){895if(!node){896return;897}898for(varx=node.childNodes.length-1;x>=0;x--){//delete all of node's children899varchildNode=node.childNodes[x];900deleteNode(childNode);901}902};903904/**
905 * <p> Copies the childNodes of nodeFrom to nodeTo</p>
906 *
907 * @param nodeFrom the Node to copy the childNodes from
908 * @param nodeTo the Node to copy the childNodes to
909 * @ignore
910 * Note: This code originally from Sarissa: http://dev.abiss.gr/sarissa
911 * It has been modified to fit into the overall codebase
912 */913varcopyChildNodes=functioncopyChildNodes(nodeFrom,nodeTo){914915if((!nodeFrom)||(!nodeTo)){916throw"Both source and destination nodes must be provided";917}918919deleteChildren(nodeTo);920varnodes=nodeFrom.childNodes;921// if within the same doc, just move, else copy and delete922if(nodeFrom.ownerDocument==nodeTo.ownerDocument){923while(nodeFrom.firstChild){924nodeTo.appendChild(nodeFrom.firstChild);925}926}else{927varownerDoc=nodeTo.nodeType==Node.DOCUMENT_NODE?nodeTo:nodeTo.ownerDocument;928vari;929if(typeof(ownerDoc.importNode)!="undefined"){930for(i=0;i<nodes.length;i++){931nodeTo.appendChild(ownerDoc.importNode(nodes[i],true));932}933}else{934for(i=0;i<nodes.length;i++){935nodeTo.appendChild(nodes[i].cloneNode(true));936}937}938}939};940941942/**
943 * Replace one node with another. Necessary for handling IE memory leak.
944 * @param node
945 * @param newNode
946 * @ignore
947 */948varreplaceNode=functionreplaceNode(newNode,node){949if(isIE()){950node.parentNode.insertBefore(newNode,node);951deleteNode(node);952}else{953node.parentNode.replaceChild(newNode,node);954}955};956957/**
958 * @ignore
959 */960varpropertyToAttribute=functionpropertyToAttribute(name){961if(name==='className'){962return'class';963}elseif(name==='xmllang'){964return'xml:lang';965}else{966returnname.toLowerCase();967}968};969970/**
971 * @ignore
972 */973varisFunctionNative=functionisFunctionNative(func){974return/^\s*function[^{]+{\s*\[native code\]\s*}\s*$/.test(String(func));975};976977/**
978 * @ignore
979 */980vardetectAttributes=functiondetectAttributes(element){981//test if 'hasAttribute' method is present and its native code is intact982//for example, Prototype can add its own implementation if missing983if(element.hasAttribute&&isFunctionNative(element.hasAttribute)){984returnfunction(name){985returnelement.hasAttribute(name);986}987}else{988try{989//when accessing .getAttribute method without arguments does not throw an error then the method is not available990element.getAttribute;991992varhtml=element.outerHTML;993varstartTag=html.match(/^<[^>]*>/)[0];994returnfunction(name){995returnstartTag.indexOf(name+'=')>-1;996}997}catch(ex){998returnfunction(name){999returnelement.getAttribute(name);1000}1001}1002}1003};10041005/**
1006 * copy all attributes from one element to another - except id
1007 * @param target element to copy attributes to
1008 * @param source element to copy attributes from
1009 * @ignore
1010 */1011varcloneAttributes=functioncloneAttributes(target,source){10121013// enumerate core element attributes - without 'dir' as special case1014varcoreElementProperties=['className','title','lang','xmllang'];1015// enumerate additional input element attributes1016varinputElementProperties=[1017'name','value','size','maxLength','src','alt','useMap','tabIndex','accessKey','accept','type'1018];1019// enumerate additional boolean input attributes1020varinputElementBooleanProperties=[1021'checked','disabled','readOnly'1022];10231024// Enumerate all the names of the event listeners1025varlistenerNames=1026['onclick','ondblclick','onmousedown','onmousemove','onmouseout',1027'onmouseover','onmouseup','onkeydown','onkeypress','onkeyup',1028'onhelp','onblur','onfocus','onchange','onload','onunload','onabort',1029'onreset','onselect','onsubmit'1030];10311032varsourceAttributeDetector=detectAttributes(source);1033vartargetAttributeDetector=detectAttributes(target);10341035varisInputElement=target.nodeName.toLowerCase()==='input';1036varpropertyNames=isInputElement?coreElementProperties.concat(inputElementProperties):coreElementProperties;1037varisXML=!source.ownerDocument.contentType||source.ownerDocument.contentType=='text/xml';1038for(variIndex=0,iLength=propertyNames.length;iIndex<iLength;iIndex++){1039varpropertyName=propertyNames[iIndex];1040varattributeName=propertyToAttribute(propertyName);1041if(sourceAttributeDetector(attributeName)){10421043//With IE 7 (quirks or standard mode) and IE 8/9 (quirks mode only), 1044//you cannot get the attribute using 'class'. You must use 'className'1045//which is the same value you use to get the indexed property. The only 1046//reliable way to detect this (without trying to evaluate the browser1047//mode and version) is to compare the two return values using 'className' 1048//to see if they exactly the same. If they are, then use the property1049//name when using getAttribute.1050if(attributeName=='class'){1051if(isIE()&&(source.getAttribute(propertyName)===source[propertyName])){1052attributeName=propertyName;1053}1054}10551056varnewValue=isXML?source.getAttribute(attributeName):source[propertyName];1057varoldValue=target[propertyName];1058if(oldValue!=newValue){1059target[propertyName]=newValue;1060}1061}else{1062//setting property to '' seems to be the only cross-browser method for removing an attribute1063//avoid setting 'value' property to '' for checkbox and radio input elements because then the1064//'value' is used instead of the 'checked' property when the form is serialized by the browser1065if(attributeName=="value"&&(target.type!='checkbox'&&target.type!='radio')){1066target[propertyName]='';1067}1068target.removeAttribute(attributeName);1069}1070}10711072varbooleanPropertyNames=isInputElement?inputElementBooleanProperties:[];1073for(varjIndex=0,jLength=booleanPropertyNames.length;jIndex<jLength;jIndex++){1074varbooleanPropertyName=booleanPropertyNames[jIndex];1075varnewBooleanValue=source[booleanPropertyName];1076varoldBooleanValue=target[booleanPropertyName];1077if(oldBooleanValue!=newBooleanValue){1078target[booleanPropertyName]=newBooleanValue;1079}1080}10811082//'style' attribute special case1083if(sourceAttributeDetector('style')){1084varnewStyle;1085varoldStyle;1086if(isIE()){1087newStyle=source.style.cssText;1088oldStyle=target.style.cssText;1089if(newStyle!=oldStyle){1090target.style.cssText=newStyle;1091}1092}else{1093newStyle=source.getAttribute('style');1094oldStyle=target.getAttribute('style');1095if(newStyle!=oldStyle){1096target.setAttribute('style',newStyle);1097}1098}1099}elseif(targetAttributeDetector('style')){1100target.removeAttribute('style');1101}11021103// Special case for 'dir' attribute1104if(!isIE()&&source.dir!=target.dir){1105if(sourceAttributeDetector('dir')){1106target.dir=source.dir;1107}elseif(targetAttributeDetector('dir')){1108target.dir='';1109}1110}11111112for(varlIndex=0,lLength=listenerNames.length;lIndex<lLength;lIndex++){1113varname=listenerNames[lIndex];1114target[name]=source[name]?source[name]:null;1115if(source[name]){1116source[name]=null;1117}1118}11191120//clone HTML5 data-* attributes1121try{1122vartargetDataset=target.dataset;1123varsourceDataset=source.dataset;1124if(targetDataset||sourceDataset){1125//cleanup the dataset1126for(vartpintargetDataset){1127deletetargetDataset[tp];1128}1129//copy dataset's properties1130for(varspinsourceDataset){1131targetDataset[sp]=sourceDataset[sp];1132}1133}1134}catch(ex){1135//most probably dataset properties are not supported1136}1137};11381139/**
1140 * Replace an element from one document into another
1141 * @param newElement new element to put in document
1142 * @param origElement original element to replace
1143 * @ignore
1144 */1145varelementReplace=functionelementReplace(newElement,origElement){1146copyChildNodes(newElement,origElement);1147// sadly, we have to reparse all over again1148// to reregister the event handlers and styles1149// PENDING do some performance tests on large pages1150origElement.innerHTML=origElement.innerHTML;11511152try{1153cloneAttributes(origElement,newElement);1154}catch(ex){1155// if in dev mode, report an error, else try to limp onward1156if(jsf.getProjectStage()=="Development"){1157thrownewError("Error updating attributes");1158}1159}1160deleteNode(newElement);11611162};11631164/**
1165 * Create a new document, then select the body element within it
1166 * @param docStr Stringified version of document to create
1167 * @return element the body element
1168 * @ignore
1169 */1170vargetBodyElement=functiongetBodyElement(docStr){11711172vardoc;// intermediate document we'll create1173varbody;// Body element to return11741175if(typeofDOMParser!=="undefined"){// FF, S, Chrome1176doc=(newDOMParser()).parseFromString(docStr,"text/xml");1177}elseif(typeofActiveXObject!=="undefined"){// IE1178doc=newActiveXObject("MSXML2.DOMDocument");1179doc.loadXML(docStr);1180}else{1181thrownewError("You don't seem to be running a supported browser");1182}11831184if(getParseErrorText(doc)!==PARSED_OK){1185thrownewError(getParseErrorText(doc));1186}11871188body=doc.getElementsByTagName("body")[0];11891190if(!body){1191thrownewError("Can't find body tag in returned document.");1192}11931194returnbody;1195};11961197/**
1198 * Find view state field for a given form.
1199 * @param form
1200 * @ignore
1201 */1202vargetViewStateElement=functiongetViewStateElement(form){1203varviewStateElement=form['javax.faces.ViewState'];12041205if(viewStateElement){1206returnviewStateElement;1207}else{1208varformElements=form.elements;1209for(vari=0,length=formElements.length;i<length;i++){1210varformElement=formElements[i];1211if(formElement.name=='javax.faces.ViewState'){1212returnformElement;1213}1214}1215}12161217returnundefined;1218};12191220/**
1221 * Do update.
1222 * @param element element to update
1223 * @param context context of request
1224 * @ignore
1225 */1226vardoUpdate=functiondoUpdate(element,context,partialResponseId){1227varid,content,markup,state,windowId;1228varstateForm,windowIdForm;1229varscripts=[];// temp holding value for array of script nodes12301231id=element.getAttribute('id');1232varviewStateRegex=newRegExp("javax.faces.ViewState"+1233jsf.separatorchar+".*$");1234varwindowIdRegex=newRegExp("^.*"+jsf.separatorchar+1235"javax.faces.ClientWindow"+1236jsf.separatorchar+".*$");1237if(id.match(viewStateRegex)){12381239state=element.firstChild;12401241// Now set the view state from the server into the DOM1242// but only for the form that submitted the request.12431244if(typeofcontext.formid!=='undefined'&&context.formid!==null){1245stateForm=getFormForId(context.formid);1246}else{1247stateForm=getFormForId(context.element.id);1248}12491250if(!stateForm||!stateForm.elements){1251// if the form went away for some reason, or it lacks elements 1252// we're going to just return silently.1253return;1254}1255varfield=getViewStateElement(stateForm);1256if(typeoffield=='undefined'){1257field=document.createElement("input");1258field.type="hidden";1259field.name="javax.faces.ViewState";1260stateForm.appendChild(field);1261}1262field.value=state.nodeValue;12631264// Now set the view state from the server into the DOM1265// for any form that is a render target.12661267if(typeofcontext.render!=='undefined'&&context.render!==null){1268vartemp=context.render.split(' ');1269for(vari=0;i<temp.length;i++){1270if(temp.hasOwnProperty(i)){1271// See if the element is a form and1272// the form is not the one that caused the submission..1273varf=document.forms[temp[i]];1274if(typeoff!=='undefined'&&f!==null&&f.id!==context.formid){1275field=getViewStateElement(f);1276if(typeoffield==='undefined'){1277field=document.createElement("input");1278field.type="hidden";1279field.name="javax.faces.ViewState";1280f.appendChild(field);1281}1282field.value=state.nodeValue;1283}1284}1285}1286}1287return;1288}elseif(id.match(windowIdRegex)){12891290windowId=element.firstChild;12911292// Now set the windowId from the server into the DOM1293// but only for the form that submitted the request.12941295windowIdForm=document.getElementById(context.formid);1296if(!windowIdForm||!windowIdForm.elements){1297// if the form went away for some reason, or it lacks elements 1298// we're going to just return silently.1299return;1300}1301varfield=windowIdForm.elements["javax.faces.ClientWindow"];1302if(typeoffield=='undefined'){1303field=document.createElement("input");1304field.type="hidden";1305field.name="javax.faces.ClientWindow";1306windowIdForm.appendChild(field);1307}1308field.value=windowId.nodeValue;13091310// Now set the windowId from the server into the DOM1311// for any form that is a render target.13121313if(typeofcontext.render!=='undefined'&&context.render!==null){1314vartemp=context.render.split(' ');1315for(vari=0;i<temp.length;i++){1316if(temp.hasOwnProperty(i)){1317// See if the element is a form and1318// the form is not the one that caused the submission..1319varf=document.forms[temp[i]];1320if(typeoff!=='undefined'&&f!==null&&f.id!==context.formid){1321field=f.elements["javax.faces.ClientWindow"];1322if(typeoffield==='undefined'){1323field=document.createElement("input");1324field.type="hidden";1325field.name="javax.faces.ClientWindow";1326f.appendChild(field);1327}1328field.value=windowId.nodeValue;1329}1330}1331}1332}1333return;1334}13351336// join the CDATA sections in the markup1337markup='';1338for(varj=0;j<element.childNodes.length;j++){1339content=element.childNodes[j];1340markup+=content.nodeValue;1341}13421343varsrc=markup;13441345// If our special render all markup is present..1346if(id==="javax.faces.ViewRoot"||id==="javax.faces.ViewBody"){1347varbodyStartEx=newRegExp("< *body[^>]*>","gi");1348varbodyEndEx=newRegExp("< */ *body[^>]*>","gi");1349varnewsrc;13501351vardocBody=document.getElementsByTagName("body")[0];1352varbodyStart=bodyStartEx.exec(src);13531354if(bodyStart!==null){// replace body tag1355// First, try with XML manipulation1356try{1357// Get scripts from text1358scripts=stripScripts(src);1359// Remove scripts from text1360newsrc=src.replace(/<script[^>]*type="text\/javascript"*>([\S\s]*?)<\/script>/igm,"");1361elementReplace(getBodyElement(newsrc),docBody);1362runScripts(scripts);1363}catch(e){1364// OK, replacing the body didn't work with XML - fall back to quirks mode insert1365varsrcBody,bodyEnd;1366// if src contains </body>1367bodyEnd=bodyEndEx.exec(src);1368if(bodyEnd!==null){1369srcBody=src.substring(bodyStartEx.lastIndex,1370bodyEnd.index);1371}else{// can't find the </body> tag, punt1372srcBody=src.substring(bodyStartEx.lastIndex);1373}1374// replace body contents with innerHTML - note, script handling happens within function1375elementReplaceStr(docBody,"body",srcBody);13761377}13781379}else{// replace body contents with innerHTML - note, script handling happens within function1380elementReplaceStr(docBody,"body",src);1381}1382}elseif(id==="javax.faces.ViewHead"){1383thrownewError("javax.faces.ViewHead not supported - browsers cannot reliably replace the head's contents");1384}else{1385vard=$(id);1386if(!d){1387thrownewError("During update: "+id+" not found");1388}1389varparent=d.parentNode;1390// Trim space padding before assigning to innerHTML1391varhtml=src.replace(/^\s+/g,'').replace(/\s+$/g,'');1392varparserElement=document.createElement('div');1393vartag=d.nodeName.toLowerCase();1394vartableElements=['td','th','tr','tbody','thead','tfoot'];1395varisInTable=false;1396for(vartei=0,tel=tableElements.length;tei<tel;tei++){1397if(tableElements[tei]==tag){1398isInTable=true;1399break;1400}1401}1402if(isInTable){14031404if(isAutoExec()){1405// Create html1406parserElement.innerHTML='<table>'+html+'</table>';1407}else{1408// Get the scripts from the text1409scripts=stripScripts(html);1410// Remove scripts from text1411html=html.replace(/<script[^>]*type="text\/javascript"*>([\S\s]*?)<\/script>/igm,"");1412parserElement.innerHTML='<table>'+html+'</table>';1413}1414varnewElement=parserElement.firstChild;1415//some browsers will also create intermediary elements such as table>tbody>tr>td1416while((null!==newElement)&&(id!==newElement.id)){1417newElement=newElement.firstChild;1418}1419parent.replaceChild(newElement,d);1420runScripts(scripts);1421}elseif(d.nodeName.toLowerCase()==='input'){1422// special case handling for 'input' elements1423// in order to not lose focus when updating,1424// input elements need to be added in place.1425parserElement=document.createElement('div');1426parserElement.innerHTML=html;1427newElement=parserElement.firstChild;14281429cloneAttributes(d,newElement);1430deleteNode(parserElement);1431}elseif(html.length>0){1432if(isAutoExec()){1433// Create html1434parserElement.innerHTML=html;1435}else{1436// Get the scripts from the text1437scripts=stripScripts(html);1438// Remove scripts from text1439html=html.replace(/<script[^>]*type="text\/javascript"*>([\S\s]*?)<\/script>/igm,"");1440parserElement.innerHTML=html;1441}1442replaceNode(parserElement.firstChild,d);1443deleteNode(parserElement);1444runScripts(scripts);1445}1446}1447};14481449/**
1450 * Delete a node specified by the element.
1451 * @param element
1452 * @ignore
1453 */1454vardoDelete=functiondoDelete(element){1455varid=element.getAttribute('id');1456vartarget=$(id);1457deleteNode(target);1458};14591460/**
1461 * Insert a node specified by the element.
1462 * @param element
1463 * @ignore
1464 */1465vardoInsert=functiondoInsert(element){1466vartablePattern=newRegExp("<\\s*(td|th|tr|tbody|thead|tfoot)","i");1467varscripts=[];1468vartarget=$(element.firstChild.getAttribute('id'));1469varparent=target.parentNode;1470varhtml=element.firstChild.firstChild.nodeValue;1471varisInTable=tablePattern.test(html);14721473if(!isAutoExec()){1474// Get the scripts from the text1475scripts=stripScripts(html);1476// Remove scripts from text1477html=html.replace(/<script[^>]*type="text\/javascript"*>([\S\s]*?)<\/script>/igm,"");1478}1479vartempElement=document.createElement('div');1480varnewElement=null;1481if(isInTable){1482tempElement.innerHTML='<table>'+html+'</table>';1483newElement=tempElement.firstChild;1484//some browsers will also create intermediary elements such as table>tbody>tr>td1485//test for presence of id on the new element since we do not have it directly1486while((null!==newElement)&&(""==newElement.id)){1487newElement=newElement.firstChild;1488}1489}else{1490tempElement.innerHTML=html;1491newElement=tempElement.firstChild;1492}14931494if(element.firstChild.nodeName==='after'){1495// Get the next in the list, to insert before1496target=target.nextSibling;1497}// otherwise, this is a 'before' element1498if(!!tempElement.innerHTML){// check if only scripts were inserted - if so, do nothing here1499parent.insertBefore(newElement,target);1500}1501runScripts(scripts);1502deleteNode(tempElement);1503};15041505/**
1506 * Modify attributes of given element id.
1507 * @param element
1508 * @ignore
1509 */1510vardoAttributes=functiondoAttributes(element){15111512// Get id of element we'll act against1513varid=element.getAttribute('id');15141515vartarget=$(id);15161517if(!target){1518thrownewError("The specified id: "+id+" was not found in the page.");1519}15201521// There can be multiple attributes modified. Loop through the list.1522varnodes=element.childNodes;1523for(vari=0;i<nodes.length;i++){1524varname=nodes[i].getAttribute('name');1525varvalue=nodes[i].getAttribute('value');15261527//boolean attribute handling code for all browsers1528if(name==='disabled'){1529target.disabled=value==='disabled'||value==='true';1530return;1531}elseif(name==='checked'){1532target.checked=value==='checked'||value==='on'||value==='true';1533return;1534}elseif(name=='readonly'){1535target.readOnly=value==='readonly'||value==='true';1536return;1537}15381539if(!isIE()){1540if(name==='value'){1541target.value=value;1542}else{1543target.setAttribute(name,value);1544}1545}else{// if it's IE, then quite a bit more work is required1546if(name==='class'){1547target.className=value;1548}elseif(name==="for"){1549name='htmlFor';1550target.setAttribute(name,value,0);1551}elseif(name==='style'){1552target.style.setAttribute('cssText',value,0);1553}elseif(name.substring(0,2)==='on'){1554varc=document.body.appendChild(document.createElement('span'));1555try{1556c.innerHTML='<span '+name+'="'+value+'"/>';1557target[name]=c.firstChild[name];1558}finally{1559document.body.removeChild(c);1560}1561}elseif(name==='dir'){1562if(jsf.getProjectStage()=='Development'){1563thrownewError("Cannot set 'dir' attribute in IE");1564}1565}else{1566target.setAttribute(name,value,0);1567}1568}1569}1570};15711572/**
1573 * Eval the CDATA of the element.
1574 * @param element to eval
1575 * @ignore
1576 */1577vardoEval=functiondoEval(element){1578varevalText=element.firstChild.nodeValue;1579globalEval(evalText);1580};15811582/**
1583 * Ajax Request Queue
1584 * @ignore
1585 */1586varQueue=newfunctionQueue(){15871588// Create the internal queue1589varqueue=[];159015911592// the amount of space at the front of the queue, initialised to zero1593varqueueSpace=0;15941595/** Returns the size of this Queue. The size of a Queue is equal to the number
1596 * of elements that have been enqueued minus the number of elements that have
1597 * been dequeued.
1598 * @ignore
1599 */1600this.getSize=functiongetSize(){1601returnqueue.length-queueSpace;1602};16031604/** Returns true if this Queue is empty, and false otherwise. A Queue is empty
1605 * if the number of elements that have been enqueued equals the number of
1606 * elements that have been dequeued.
1607 * @ignore
1608 */1609this.isEmpty=functionisEmpty(){1610return(queue.length===0);1611};16121613/** Enqueues the specified element in this Queue.
1614 *
1615 * @param element - the element to enqueue
1616 * @ignore
1617 */1618this.enqueue=functionenqueue(element){1619// Queue the request1620queue.push(element);1621};162216231624/** Dequeues an element from this Queue. The oldest element in this Queue is
1625 * removed and returned. If this Queue is empty then undefined is returned.
1626 *
1627 * @returns Object The element that was removed from the queue.
1628 * @ignore
1629 */1630this.dequeue=functiondequeue(){1631// initialise the element to return to be undefined1632varelement=undefined;16331634// check whether the queue is empty1635if(queue.length){1636// fetch the oldest element in the queue1637element=queue[queueSpace];16381639// update the amount of space and check whether a shift should occur1640if(++queueSpace*2>=queue.length){1641// set the queue equal to the non-empty portion of the queue1642queue=queue.slice(queueSpace);1643// reset the amount of space at the front of the queue1644queueSpace=0;1645}1646}1647// return the removed element1648try{1649returnelement;1650}finally{1651element=null;// IE 6 leak prevention1652}1653};16541655/** Returns the oldest element in this Queue. If this Queue is empty then
1656 * undefined is returned. This function returns the same value as the dequeue
1657 * function, but does not remove the returned element from this Queue.
1658 * @ignore
1659 */1660this.getOldestElement=functiongetOldestElement(){1661// initialise the element to return to be undefined1662varelement=undefined;16631664// if the queue is not element then fetch the oldest element in the queue1665if(queue.length){1666element=queue[queueSpace];1667}1668// return the oldest element1669try{1670returnelement;1671}finally{1672element=null;//IE 6 leak prevention1673}1674};1675}();167616771678/**
1679 * AjaxEngine handles Ajax implementation details.
1680 * @ignore
1681 */1682varAjaxEngine=functionAjaxEngine(context){16831684varreq={};// Request Object1685req.url=null;// Request URL1686req.context=context;// Context of request and response1687req.context.sourceid=null;// Source of this request1688req.context.onerror=null;// Error handler for request1689req.context.onevent=null;// Event handler for request1690req.xmlReq=null;// XMLHttpRequest Object1691req.async=true;// Default - Asynchronous1692req.parameters={};// Parameters For GET or POST1693req.queryString=null;// Encoded Data For GET or POST1694req.method=null;// GET or POST1695req.status=null;// Response Status Code From Server1696req.fromQueue=false;// Indicates if the request was taken off the queue1697// before being sent. This prevents the request from1698// entering the queue redundantly.16991700req.que=Queue;17011702// Get a transport Handle1703// The transport will be an iframe transport if the form1704// has multipart encoding type. This is where we could1705// handle XMLHttpRequest Level2 as well (perhaps 1706// something like: if ('upload' in req.xmlReq)'1707req.xmlReq=getTransport(context);17081709if(req.xmlReq===null){1710returnnull;1711}17121713/**
1714 * @ignore
1715 */1716functionnoop(){}17171718// Set up request/response state callbacks1719/**
1720 * @ignore
1721 */1722req.xmlReq.onreadystatechange=function(){1723if(req.xmlReq.readyState===4){1724req.onComplete();1725// next two lines prevent closure/ciruclar reference leaks1726// of XHR instances in IE1727req.xmlReq.onreadystatechange=noop;1728req.xmlReq=null;1729}1730};17311732/**
1733 * This function is called when the request/response interaction
1734 * is complete. If the return status code is successfull,
1735 * dequeue all requests from the queue that have completed. If a
1736 * request has been found on the queue that has not been sent,
1737 * send the request.
1738 * @ignore
1739 */1740req.onComplete=functiononComplete(){1741if(req.xmlReq.status&&(req.xmlReq.status>=200&&req.xmlReq.status<300)){1742sendEvent(req.xmlReq,req.context,"complete");1743jsf.ajax.response(req.xmlReq,req.context);1744}else{1745sendEvent(req.xmlReq,req.context,"complete");1746sendError(req.xmlReq,req.context,"httpError");1747}17481749// Regardless of whether the request completed successfully (or not),1750// dequeue requests that have been completed (readyState 4) and send1751// requests that ready to be sent (readyState 0).17521753varnextReq=req.que.getOldestElement();1754if(nextReq===null||typeofnextReq==='undefined'){1755return;1756}1757while((typeofnextReq.xmlReq!=='undefined'&&nextReq.xmlReq!==null)&&1758nextReq.xmlReq.readyState===4){1759req.que.dequeue();1760nextReq=req.que.getOldestElement();1761if(nextReq===null||typeofnextReq==='undefined'){1762break;1763}1764}1765if(nextReq===null||typeofnextReq==='undefined'){1766return;1767}1768if((typeofnextReq.xmlReq!=='undefined'&&nextReq.xmlReq!==null)&&1769nextReq.xmlReq.readyState===0){1770nextReq.fromQueue=true;1771nextReq.sendRequest();1772}1773};17741775/**
1776 * Utility method that accepts additional arguments for the AjaxEngine.
1777 * If an argument is passed in that matches an AjaxEngine property, the
1778 * argument value becomes the value of the AjaxEngine property.
1779 * Arguments that don't match AjaxEngine properties are added as
1780 * request parameters.
1781 * @ignore
1782 */1783req.setupArguments=function(args){1784for(variinargs){1785if(args.hasOwnProperty(i)){1786if(typeofreq[i]==='undefined'){1787req.parameters[i]=args[i];1788}else{1789req[i]=args[i];1790}1791}1792}1793};17941795/**
1796 * This function does final encoding of parameters, determines the request method
1797 * (GET or POST) and sends the request using the specified url.
1798 * @ignore
1799 */1800req.sendRequest=function(){1801if(req.xmlReq!==null){1802// if there is already a request on the queue waiting to be processed..1803// just queue this request1804if(!req.que.isEmpty()){1805if(!req.fromQueue){1806req.que.enqueue(req);1807return;1808}1809}1810// If the queue is empty, queue up this request and send1811if(!req.fromQueue){1812req.que.enqueue(req);1813}1814// Some logic to get the real request URL1815if(req.generateUniqueUrl&&req.method=="GET"){1816req.parameters["AjaxRequestUniqueId"]=newDate().getTime()+""+req.requestIndex;1817}1818varcontent=null;// For POST requests, to hold query string1819for(variinreq.parameters){1820if(req.parameters.hasOwnProperty(i)){1821if(req.queryString.length>0){1822req.queryString+="&";1823}1824req.queryString+=encodeURIComponent(i)+"="+encodeURIComponent(req.parameters[i]);1825}1826}1827if(req.method==="GET"){1828if(req.queryString.length>0){1829req.url+=((req.url.indexOf("?")>-1)?"&":"?")+req.queryString;1830}1831}1832req.xmlReq.open(req.method,req.url,req.async);1833// note that we are including the charset=UTF-8 as part of the content type (even1834// if encodeURIComponent encodes as UTF-8), because with some1835// browsers it will not be set in the request. Some server implementations need to 1836// determine the character encoding from the request header content type.1837if(req.method==="POST"){1838if(typeofreq.xmlReq.setRequestHeader!=='undefined'){1839req.xmlReq.setRequestHeader('Faces-Request','partial/ajax');1840req.xmlReq.setRequestHeader('Content-type','application/x-www-form-urlencoded;charset=UTF-8');1841}1842content=req.queryString;1843}1844// note that async == false is not a supported feature. We may change it in ways1845// that break existing programs at any time, with no warning.1846if(!req.async){1847req.xmlReq.onreadystatechange=null;// no need for readystate change listening1848}1849sendEvent(req.xmlReq,req.context,"begin");1850req.xmlReq.send(content);1851if(!req.async){1852req.onComplete();1853}1854}1855};18561857returnreq;1858};18591860/**
1861 * Error handling callback.
1862 * Assumes that the request has completed.
1863 * @ignore
1864 */1865varsendError=functionsendError(request,context,status,description,serverErrorName,serverErrorMessage){18661867// Possible errornames:1868// httpError1869// emptyResponse1870// serverError1871// malformedXML18721873varsent=false;1874vardata={};// data payload for function1875data.type="error";1876data.status=status;1877data.source=context.sourceid;1878data.responseCode=request.status;1879data.responseXML=request.responseXML;1880data.responseText=request.responseText;18811882// ensure data source is the dom element and not the ID1883// per 14.4.1 of the 2.0 specification.1884if(typeofdata.source==='string'){1885data.source=document.getElementById(data.source);1886}18871888if(description){1889data.description=description;1890}elseif(status=="httpError"){1891if(data.responseCode===0){1892data.description="The Http Transport returned a 0 status code. This is usually the result of mixing ajax and full requests. This is usually undesired, for both performance and data integrity reasons.";1893}else{1894data.description="There was an error communicating with the server, status: "+data.responseCode;1895}1896}elseif(status=="serverError"){1897data.description=serverErrorMessage;1898}elseif(status=="emptyResponse"){1899data.description="An empty response was received from the server. Check server error logs.";1900}elseif(status=="malformedXML"){1901if(getParseErrorText(data.responseXML)!==PARSED_OK){1902data.description=getParseErrorText(data.responseXML);1903}else{1904data.description="An invalid XML response was received from the server.";1905}1906}19071908if(status=="serverError"){1909data.errorName=serverErrorName;1910data.errorMessage=serverErrorMessage;1911}19121913// If we have a registered callback, send the error to it.1914if(context.onerror){1915context.onerror.call(null,data);1916sent=true;1917}19181919for(variinerrorListeners){1920if(errorListeners.hasOwnProperty(i)){1921errorListeners[i].call(null,data);1922sent=true;1923}1924}19251926if(!sent&&jsf.getProjectStage()==="Development"){1927if(status=="serverError"){1928alert("serverError: "+serverErrorName+" "+serverErrorMessage);1929}else{1930alert(status+": "+data.description);1931}1932}1933};19341935/**
1936 * Event handling callback.
1937 * Request is assumed to have completed, except in the case of event = 'begin'.
1938 * @ignore
1939 */1940varsendEvent=functionsendEvent(request,context,status){19411942vardata={};1943data.type="event";1944data.status=status;1945data.source=context.sourceid;1946// ensure data source is the dom element and not the ID1947// per 14.4.1 of the 2.0 specification.1948if(typeofdata.source==='string'){1949data.source=document.getElementById(data.source);1950}1951if(status!=='begin'){1952data.responseCode=request.status;1953data.responseXML=request.responseXML;1954data.responseText=request.responseText;1955}19561957if(context.onevent){1958context.onevent.call(null,data);1959}19601961for(variineventListeners){1962if(eventListeners.hasOwnProperty(i)){1963eventListeners[i].call(null,data);1964}1965}1966};19671968// Use module pattern to return the functions we actually expose1969return{1970/**
1971 * Register a callback for error handling.
1972 * <p><b>Usage:</b></p>
1973 * <pre><code>
1974 * jsf.ajax.addOnError(handleError);
1975 * ...
1976 * var handleError = function handleError(data) {
1977 * ...
1978 * }
1979 * </pre></code>
1980 * <p><b>Implementation Requirements:</b></p>
1981 * This function must accept a reference to an existing JavaScript function.
1982 * The JavaScript function reference must be added to a list of callbacks, making it possible
1983 * to register more than one callback by invoking <code>jsf.ajax.addOnError</code>
1984 * more than once. This function must throw an error if the <code>callback</code>
1985 * argument is not a function.
1986 *
1987 * @member jsf.ajax
1988 * @param callback a reference to a function to call on an error
1989 */1990addOnError:functionaddOnError(callback){1991if(typeofcallback==='function'){1992errorListeners[errorListeners.length]=callback;1993}else{1994thrownewError("jsf.ajax.addOnError: Added a callback that was not a function.");1995}1996},1997/**
1998 * Register a callback for event handling.
1999 * <p><b>Usage:</b></p>
2000 * <pre><code>
2001 * jsf.ajax.addOnEvent(statusUpdate);
2002 * ...
2003 * var statusUpdate = function statusUpdate(data) {
2004 * ...
2005 * }
2006 * </pre></code>
2007 * <p><b>Implementation Requirements:</b></p>
2008 * This function must accept a reference to an existing JavaScript function.
2009 * The JavaScript function reference must be added to a list of callbacks, making it possible
2010 * to register more than one callback by invoking <code>jsf.ajax.addOnEvent</code>
2011 * more than once. This function must throw an error if the <code>callback</code>
2012 * argument is not a function.
2013 *
2014 * @member jsf.ajax
2015 * @param callback a reference to a function to call on an event
2016 */2017addOnEvent:functionaddOnEvent(callback){2018if(typeofcallback==='function'){2019eventListeners[eventListeners.length]=callback;2020}else{2021thrownewError("jsf.ajax.addOnEvent: Added a callback that was not a function");2022}2023},2024/**
20252026 * <p><span class="changed_modified_2_2">Send</span> an
2027 * asynchronous Ajax req uest to the server.
20282029 * <p><b>Usage:</b></p>
2030 * <pre><code>
2031 * Example showing all optional arguments:
2032 *
2033 * <commandButton id="button1" value="submit"
2034 * onclick="jsf.ajax.request(this,event,
2035 * {execute:'button1',render:'status',onevent: handleEvent,onerror: handleError});return false;"/>
2036 * </commandButton/>
2037 * </pre></code>
2038 * <p><b>Implementation Requirements:</b></p>
2039 * This function must:
2040 * <ul>
2041 * <li>Be used within the context of a <code>form</code>.</li>
2042 * <li>Capture the element that triggered this Ajax request
2043 * (from the <code>source</code> argument, also known as the
2044 * <code>source</code> element.</li>
2045 * <li>If the <code>source</code> element is <code>null</code> or
2046 * <code>undefined</code> throw an error.</li>
2047 * <li>If the <code>source</code> argument is not a <code>string</code> or
2048 * DOM element object, throw an error.</li>
2049 * <li>If the <code>source</code> argument is a <code>string</code>, find the
2050 * DOM element for that <code>string</code> identifier.
2051 * <li>If the DOM element could not be determined, throw an error.</li>
2052 * <li>If the <code>onerror</code> and <code>onevent</code> arguments are set,
2053 * they must be functions, or throw an error.
2054 * <li>Determine the <code>source</code> element's <code>form</code>
2055 * element.</li>
2056 * <li>Get the <code>form</code> view state by calling
2057 * {@link jsf.getViewState} passing the
2058 * <code>form</code> element as the argument.</li>
2059 * <li>Collect post data arguments for the Ajax request.
2060 * <ul>
2061 * <li>The following name/value pairs are required post data arguments:
2062 * <table border="1">
2063 * <tr>
2064 * <th>name</th>
2065 * <th>value</th>
2066 * </tr>
2067 * <tr>
2068 * <td><code>javax.faces.ViewState</code></td>
2069 * <td><code>Contents of javax.faces.ViewState hidden field. This is included when
2070 * {@link jsf.getViewState} is used.</code></td>
2071 * </tr>
2072 * <tr>
2073 * <td><code>javax.faces.partial.ajax</code></td>
2074 * <td><code>true</code></td>
2075 * </tr>
2076 * <tr>
2077 * <td><code>javax.faces.source</code></td>
2078 * <td><code>The identifier of the element that triggered this request.</code></td>
2079 * </tr>
2080 * <tr class="changed_added_2_2">
2081 * <td><code>javax.faces.ClientWindow</code></td>
20822083 * <td><code>Call jsf.getClientWindow(), passing the current
2084 * form. If the return is non-null, it must be set as the
2085 * value of this name/value pair, otherwise, a name/value
2086 * pair for client window must not be sent.</code></td>
20872088 * </tr>
2089 * </table>
2090 * </li>
2091 * </ul>
2092 * </li>
2093 * <li>Collect optional post data arguments for the Ajax request.
2094 * <ul>
2095 * <li>Determine additional arguments (if any) from the <code>options</code>
2096 * argument. If <code>options.execute</code> exists:
2097 * <ul>
2098 * <li>If the keyword <code>@none</code> is present, do not create and send
2099 * the post data argument <code>javax.faces.partial.execute</code>.</li>
2100 * <li>If the keyword <code>@all</code> is present, create the post data argument with
2101 * the name <code>javax.faces.partial.execute</code> and the value <code>@all</code>.</li>
2102 * <li>Otherwise, there are specific identifiers that need to be sent. Create the post
2103 * data argument with the name <code>javax.faces.partial.execute</code> and the value as a
2104 * space delimited <code>string</code> of client identifiers.</li>
2105 * </ul>
2106 * </li>
2107 * <li>If <code>options.execute</code> does not exist, create the post data argument with the
2108 * name <code>javax.faces.partial.execute</code> and the value as the identifier of the
2109 * element that caused this request.</li>
2110 * <li>If <code>options.render</code> exists:
2111 * <ul>
2112 * <li>If the keyword <code>@none</code> is present, do not create and send
2113 * the post data argument <code>javax.faces.partial.render</code>.</li>
2114 * <li>If the keyword <code>@all</code> is present, create the post data argument with
2115 * the name <code>javax.faces.partial.render</code> and the value <code>@all</code>.</li>
2116 * <li>Otherwise, there are specific identifiers that need to be sent. Create the post
2117 * data argument with the name <code>javax.faces.partial.render</code> and the value as a
2118 * space delimited <code>string</code> of client identifiers.</li>
2119 * </ul>
2120 * <li>If <code>options.render</code> does not exist do not create and send the
2121 * post data argument <code>javax.faces.partial.render</code>.</li>
21222123 * <li class="changed_added_2_2">If
2124 * <code>options.delay</code> exists let it be the value
2125 * <em>delay</em>, for this discussion. If
2126 * <code>options.delay</code> does not exist, or is the
2127 * literal string <code>'none'</code>, without the quotes,
2128 * no delay is used. If less than <em>delay</em>
2129 * milliseconds elapses between calls to <em>request()</em>
2130 * only the most recent one is sent and all other requests
2131 * are discarded.</li>
213221332134 * <li class="changed_added_2_2">If
2135 * <code>options.resetValues</code> exists and its value is
2136 * <code>true</code>, ensure a post data argument with the
2137 * name <code>javax.faces.partial.resetValues</code> and the
2138 * value <code>true</code> is sent in addition to the other
2139 * post data arguments. This will cause
2140 * <code>UIViewRoot.resetValues()</code> to be called,
2141 * passing the value of the "render" attribute. Note: do
2142 * not use any of the <code>@</code> keywords such as
2143 * <code>@form</code> or <code>@this</code> with this option
2144 * because <code>UIViewRoot.resetValues()</code> does not
2145 * descend into the children of the listed components.</li>
214621472148 * <li>Determine additional arguments (if any) from the <code>event</code>
2149 * argument. The following name/value pairs may be used from the
2150 * <code>event</code> object:
2151 * <ul>
2152 * <li><code>target</code> - the ID of the element that triggered the event.</li>
2153 * <li><code>captured</code> - the ID of the element that captured the event.</li>
2154 * <li><code>type</code> - the type of event (ex: onkeypress)</li>
2155 * <li><code>alt</code> - <code>true</code> if ALT key was pressed.</li>
2156 * <li><code>ctrl</code> - <code>true</code> if CTRL key was pressed.</li>
2157 * <li><code>shift</code> - <code>true</code> if SHIFT key was pressed. </li>
2158 * <li><code>meta</code> - <code>true</code> if META key was pressed. </li>
2159 * <li><code>right</code> - <code>true</code> if right mouse button
2160 * was pressed. </li>
2161 * <li><code>left</code> - <code>true</code> if left mouse button
2162 * was pressed. </li>
2163 * <li><code>keycode</code> - the key code.
2164 * </ul>
2165 * </li>
2166 * </ul>
2167 * </li>
2168 * <li>Encode the set of post data arguments.</li>
2169 * <li>Join the encoded view state with the encoded set of post data arguments
2170 * to form the <code>query string</code> that will be sent to the server.</li>
2171 * <li>Create a request <code>context</code> object and set the properties:
2172 * <ul><li><code>source</code> (the source DOM element for this request)</li>
2173 * <li><code>onerror</code> (the error handler for this request)</li>
2174 * <li><code>onevent</code> (the event handler for this request)</li></ul>
2175 * The request context will be used during error/event handling.</li>
2176 * <li>Send a <code>begin</code> event following the procedure as outlined
2177 * in the Chapter 13 "Sending Events" section of the spec prose document <a
2178 * href="../../javadocs/overview-summary.html#prose_document">linked in the
2179 * overview summary</a></li>
2180 * <li>Set the request header with the name: <code>Faces-Request</code> and the
2181 * value: <code>partial/ajax</code>.</li>
2182 * <li>Determine the <code>posting URL</code> as follows: If the hidden field
2183 * <code>javax.faces.encodedURL</code> is present in the submitting form, use its
2184 * value as the <code>posting URL</code>. Otherwise, use the <code>action</code>
2185 * property of the <code>form</code> element as the <code>URL</code>.</li>
21862187 * <li>
21882189 * <p><span class="changed_modified_2_2">Determine whether
2190 * or not the submitting form is using
2191 * <code>multipart/form-data</code> as its
2192 * <code>enctype</code> attribute. If not, send the request
2193 * as an <code>asynchronous POST</code> using the
2194 * <code>posting URL</code> that was determined in the
2195 * previous step.</span> <span
2196 * class="changed_added_2_2">Otherwise, send the request
2197 * using a multi-part capable transport layer, such as a
2198 * hidden inline frame. Note that using a hidden inline
2199 * frame does <strong>not</strong> use
2200 * <code>XMLHttpRequest</code>, but the request must be sent
2201 * with all the parameters that a JSF
2202 * <code>XMLHttpRequest</code> would have been sent with.
2203 * In this way, the server side processing of the request
2204 * will be identical whether or the request is multipart or
2205 * not.</span></p
22062207 * <div class="changed_added_2_2">
22082209 * <p>The <code>begin</code>, <code>complete</code>, and
2210 * <code>success</code> events must be emulated when using
2211 * the multipart transport. This allows any listeners to
2212 * behave uniformly regardless of the multipart or
2213 * <code>XMLHttpRequest</code> nature of the transport.</p>
22142215 * </div>
22162217 </li>
2218 * </ul>
2219 * Form serialization should occur just before the request is sent to minimize
2220 * the amount of time between the creation of the serialized form data and the
2221 * sending of the serialized form data (in the case of long requests in the queue).
2222 * Before the request is sent it must be put into a queue to ensure requests
2223 * are sent in the same order as when they were initiated. The request callback function
2224 * must examine the queue and determine the next request to be sent. The behavior of the
2225 * request callback function must be as follows:
2226 * <ul>
2227 * <li>If the request completed successfully invoke {@link jsf.ajax.response}
2228 * passing the <code>request</code> object.</li>
2229 * <li>If the request did not complete successfully, notify the client.</li>
2230 * <li>Regardless of the outcome of the request (success or error) every request in the
2231 * queue must be handled. Examine the status of each request in the queue starting from
2232 * the request that has been in the queue the longest. If the status of the request is
2233 * <code>complete</code> (readyState 4), dequeue the request (remove it from the queue).
2234 * If the request has not been sent (readyState 0), send the request. Requests that are
2235 * taken off the queue and sent should not be put back on the queue.</li>
2236 * </ul>
2237 *
2238 * </p>
2239 *
2240 * @param source The DOM element that triggered this Ajax request, or an id string of the
2241 * element to use as the triggering element.
2242 * @param event The DOM event that triggered this Ajax request. The
2243 * <code>event</code> argument is optional.
2244 * @param options The set of available options that can be sent as
2245 * request parameters to control client and/or server side
2246 * request processing. Acceptable name/value pair options are:
2247 * <table border="1">
2248 * <tr>
2249 * <th>name</th>
2250 * <th>value</th>
2251 * </tr>
2252 * <tr>
2253 * <td><code>execute</code></td>
2254 * <td><code>space seperated list of client identifiers</code></td>
2255 * </tr>
2256 * <tr>
2257 * <td><code>render</code></td>
2258 * <td><code>space seperated list of client identifiers</code></td>
2259 * </tr>
2260 * <tr>
2261 * <td><code>onevent</code></td>
2262 * <td><code>function to callback for event</code></td>
2263 * </tr>
2264 * <tr>
2265 * <td><code>onerror</code></td>
2266 * <td><code>function to callback for error</code></td>
2267 * </tr>
2268 * <tr>
2269 * <td><code>params</code></td>
2270 * <td><code>object containing parameters to include in the request</code></td>
2271 * </tr>
22722273 * <tr class="changed_added_2_2">
22742275 * <td><code>delay</code></td>
22762277 * <td>If less than <em>delay</em> milliseconds elapses
2278 * between calls to <em>request()</em> only the most recent
2279 * one is sent and all other requests are discarded. If the
2280 * value of <em>delay</em> is the literal string
2281 * <code>'none'</code> without the quotes, or no delay is
2282 * specified, no delay is used. </td>
22832284 * </tr>
22852286 * <tr class="changed_added_2_2">
22872288 * <td><code>resetValues</code></td>
22892290 * <td>If true, ensure a post data argument with the name
2291 * javax.faces.partial.resetValues and the value true is
2292 * sent in addition to the other post data arguments. This
2293 * will cause UIViewRoot.resetValues() to be called, passing
2294 * the value of the "render" attribute. Note: do not use any
2295 * of the @ keywords such as @form or @this with this option
2296 * because UIViewRoot.resetValues() does not descend into
2297 * the children of the listed components.</td>
22982299 * </tr>
230023012302 * </table>
2303 * The <code>options</code> argument is optional.
2304 * @member jsf.ajax
2305 * @function jsf.ajax.request
23062307 * @throws Error if first required argument
2308 * <code>element</code> is not specified, or if one or more
2309 * of the components in the <code>options.execute</code>
2310 * list is a file upload component, but the form's enctype
2311 * is not set to <code>multipart/form-data</code>
2312 */23132314request:functionrequest(source,event,options){23152316varelement,form;// Element variables2317varall,none;23182319varcontext={};23202321if(typeofsource==='undefined'||source===null){2322thrownewError("jsf.ajax.request: source not set");2323}2324if(delayHandler){2325clearTimeout(delayHandler);2326delayHandler=null;2327}23282329// set up the element based on source2330if(typeofsource==='string'){2331element=document.getElementById(source);2332}elseif(typeofsource==='object'){2333element=source;2334}else{2335thrownewError("jsf.request: source must be object or string");2336}2337// attempt to handle case of name unset2338// this might be true in a badly written composite component2339if(!element.name){2340element.name=element.id;2341}23422343context.element=element;23442345if(typeof(options)==='undefined'||options===null){2346options={};2347}23482349// Error handler for this request2350varonerror=false;23512352if(options.onerror&&typeofoptions.onerror==='function'){2353onerror=options.onerror;2354}elseif(options.onerror&&typeofoptions.onerror!=='function'){2355thrownewError("jsf.ajax.request: Added an onerror callback that was not a function");2356}23572358// Event handler for this request2359varonevent=false;23602361if(options.onevent&&typeofoptions.onevent==='function'){2362onevent=options.onevent;2363}elseif(options.onevent&&typeofoptions.onevent!=='function'){2364thrownewError("jsf.ajax.request: Added an onevent callback that was not a function");2365}23662367form=getForm(element);2368if(!form){2369thrownewError("jsf.ajax.request: Method must be called within a form");2370}2371context.form=form;2372context.formid=form.id;23732374varviewState=jsf.getViewState(form);23752376// Set up additional arguments to be used in the request..2377// Make sure "javax.faces.source" is set up.2378// If there were "execute" ids specified, make sure we2379// include the identifier of the source element in the2380// "execute" list. If there were no "execute" ids2381// specified, determine the default.23822383varargs={};23842385args["javax.faces.source"]=element.id;23862387if(event&&!!event.type){2388args["javax.faces.partial.event"]=event.type;2389}23902391if("resetValues"inoptions){2392args["javax.faces.partial.resetValues"]=options.resetValues;2393}23942395// If we have 'execute' identifiers:2396// Handle any keywords that may be present.2397// If @none present anywhere, do not send the2398// "javax.faces.partial.execute" parameter.2399// The 'execute' and 'render' lists must be space2400// delimited.24012402if(options.execute){2403none=options.execute.search(/@none/);2404if(none<0){2405all=options.execute.search(/@all/);2406if(all<0){2407options.execute=options.execute.replace("@this",element.id);2408options.execute=options.execute.replace("@form",form.id);2409vartemp=options.execute.split(' ');2410if(!isInArray(temp,element.name)){2411options.execute=element.name+" "+options.execute;2412}2413}else{2414options.execute="@all";2415}2416args["javax.faces.partial.execute"]=options.execute;2417}2418}else{2419options.execute=element.name+" "+element.id;2420args["javax.faces.partial.execute"]=options.execute;2421}24222423if(options.render){2424none=options.render.search(/@none/);2425if(none<0){2426all=options.render.search(/@all/);2427if(all<0){2428options.render=options.render.replace("@this",element.id);2429options.render=options.render.replace("@form",form.id);2430}else{2431options.render="@all";2432}2433args["javax.faces.partial.render"]=options.render;2434}2435}2436varexplicitlyDoNotDelay=((typeofoptions.delay=='undefined')||(typeofoptions.delay=='string')&&2437(options.delay.toLowerCase()=='none'));2438vardelayValue;2439if(typeofoptions.delay=='number'){2440delayValue=options.delay;2441}elseif(!explicitlyDoNotDelay){2442thrownewError('invalid value for delay option: '+options.delay);2443}24442445// remove non-passthrough options2446deleteoptions.execute;2447deleteoptions.render;2448deleteoptions.onerror;2449deleteoptions.onevent;2450deleteoptions.delay;24512452// copy all other options to args2453for(varpropertyinoptions){2454if(options.hasOwnProperty(property)){2455args[property]=options[property];2456}2457}24582459args["javax.faces.partial.ajax"]="true";2460args["method"]="POST";24612462// Determine the posting url24632464varencodedUrlField=form.elements["javax.faces.encodedURL"];2465if(typeofencodedUrlField=='undefined'){2466args["url"]=form.action;2467}else{2468args["url"]=encodedUrlField.value;2469}2470varsendRequest=function(){2471varajaxEngine=newAjaxEngine(context);2472ajaxEngine.setupArguments(args);2473ajaxEngine.queryString=viewState;2474ajaxEngine.context.onevent=onevent;2475ajaxEngine.context.onerror=onerror;2476ajaxEngine.context.sourceid=element.id;2477ajaxEngine.context.render=args["javax.faces.partial.render"];2478ajaxEngine.sendRequest();24792480// null out element variables to protect against IE memory leak2481element=null;2482form=null;2483sendRequest=null;2484context=null;2485};24862487if(explicitlyDoNotDelay){2488sendRequest();2489}else{2490delayHandler=setTimeout(sendRequest,delayValue);2491}24922493},2494/**
2495 * <p><span class="changed_modified_2_2">Receive</span> an Ajax response
2496 * from the server.
2497 * <p><b>Usage:</b></p>
2498 * <pre><code>
2499 * jsf.ajax.response(request, context);
2500 * </pre></code>
2501 * <p><b>Implementation Requirements:</b></p>
2502 * This function must evaluate the markup returned in the
2503 * <code>request.responseXML</code> object and perform the following action:
2504 * <ul>
2505 * <p>If there is no XML response returned, signal an <code>emptyResponse</code>
2506 * error. If the XML response does not follow the format as outlined
2507 * in Appendix A of the spec prose document <a
2508 * href="../../javadocs/overview-summary.html#prose_document">linked in the
2509 * overview summary</a> signal a <code>malformedError</code> error. Refer to
2510 * section "Signaling Errors" in Chapter 13 of the spec prose document <a
2511 * href="../../javadocs/overview-summary.html#prose_document">linked in the
2512 * overview summary</a>.</p>
2513 * <p>If the response was successfully processed, send a <code>success</code>
2514 * event as outlined in Chapter 13 "Sending Events" section of the spec prose
2515 * document <a
2516 * href="../../javadocs/overview-summary.html#prose_document">linked in the
2517 * overview summary</a>.</p>
2518 * <p><i>Update Element Processing</i></p>
2519 * The <code>update</code> element is used to update a single DOM element. The
2520 * "id" attribute of the <code>update</code> element refers to the DOM element that
2521 * will be updated. The contents of the <code>CDATA</code> section is the data that
2522 * will be used when updating the contents of the DOM element as specified by the
2523 * <code><update></code> element identifier.
2524 * <li>If an <code><update></code> element is found in the response
2525 * with the identifier <code>javax.faces.ViewRoot</code>:
2526 * <pre><code><update id="javax.faces.ViewRoot">
2527 * <![CDATA[...]]>
2528 * </update></code></pre>
2529 * Update the entire DOM replacing the appropriate <code>head</code> and/or
2530 * <code>body</code> sections with the content from the response.</li>
25312532 * <li class="changed_modified_2_2">If an
2533 * <code><update></code> element is found in the
2534 * response with an identifier containing
2535 * <code>javax.faces.ViewState</code>:
25362537 * <pre><code><update id="<VIEW_ROOT_CONTAINER_CLIENT_ID><SEP>javax.faces.ViewState<SEP><UNIQUE_PER_VIEW_NUMBER>">
2538 * <![CDATA[...]]>
2539 * </update></code></pre>
25402541 * locate and update the submitting form's
2542 * <code>javax.faces.ViewState</code> value with the
2543 * <code>CDATA</code> contents from the response.
2544 * <SEP>: is the currently configured
2545 * <code>UINamingContainer.getSeparatorChar()</code>.
2546 * <VIEW_ROOT_CONTAINER_CLIENT_ID> is the return from
2547 * <code>UIViewRoot.getContainerClientId()</code> on the
2548 * view from whence this state originated.
2549 * <UNIQUE_PER_VIEW_NUMBER> is a number that must be
2550 * unique within this view, but must not be included in the
2551 * view state. This requirement is simply to satisfy XML
2552 * correctness in parity with what is done in the
2553 * corresponding non-partial JSF view. Locate and update
2554 * the <code>javax.faces.ViewState</code> value for all
2555 * forms specified in the <code>render</code> target
2556 * list.</li>
25572558 * <li class="changed_added_2_2">If an
2559 * <code>update</code> element is found in the response with
2560 * an identifier containing
2561 * <code>javax.faces.ClientWindow</code>:
25622563 * <pre><code><update id="<VIEW_ROOT_CONTAINER_CLIENT_ID><SEP>javax.faces.ClientWindow<SEP><UNIQUE_PER_VIEW_NUMBER>">
2564 * <![CDATA[...]]>
2565 * </update></code></pre>
25662567 * locate and update the submitting form's
2568 * <code>javax.faces.ClientWindow</code> value with the
2569 * <code>CDATA</code> contents from the response.
2570 * <SEP>: is the currently configured
2571 * <code>UINamingContainer.getSeparatorChar()</code>.
2572 * <VIEW_ROOT_CONTAINER_CLIENT_ID> is the return from
2573 * <code>UIViewRoot.getContainerClientId()</code> on the
2574 * view from whence this state originated.
2575 * <UNIQUE_PER_VIEW_NUMBER> is a number that must be
2576 * unique within this view, but must not be included in the
2577 * view state. This requirement is simply to satisfy XML
2578 * correctness in parity with what is done in the
2579 * corresponding non-partial JSF view. Locate and update
2580 * the <code>javax.faces.ClientWindow</code> value for all
2581 * forms specified in the <code>render</code> target
2582 * list.</li>
258325842585 * <li>If an <code>update</code> element is found in the response with the identifier
2586 * <code>javax.faces.ViewHead</code>:
2587 * <pre><code><update id="javax.faces.ViewHead">
2588 * <![CDATA[...]]>
2589 * </update></code></pre>
2590 * update the document's <code>head</code> section with the <code>CDATA</code>
2591 * contents from the response.</li>
2592 * <li>If an <code>update</code> element is found in the response with the identifier
2593 * <code>javax.faces.ViewBody</code>:
2594 * <pre><code><update id="javax.faces.ViewBody">
2595 * <![CDATA[...]]>
2596 * </update></code></pre>
2597 * update the document's <code>body</code> section with the <code>CDATA</code>
2598 * contents from the response.</li>
2599 * <li>For any other <code><update></code> element:
2600 * <pre><code><update id="update id">
2601 * <![CDATA[...]]>
2602 * </update></code></pre>
2603 * Find the DOM element with the identifier that matches the
2604 * <code><update></code> element identifier, and replace its contents with
2605 * the <code><update></code> element's <code>CDATA</code> contents.</li>
2606 * </li>
2607 * <p><i>Insert Element Processing</i></p>
26082609 * <li>If an <code><insert></code> element is found in
2610 * the response with a nested <code><before></code>
2611 * element:
26122613 * <pre><code><insert>
2614 * <before id="before id">
2615 * <![CDATA[...]]>
2616 * </before>
2617 * </insert></code></pre>
2618 *
2619 * <ul>
2620 * <li>Extract this <code><before></code> element's <code>CDATA</code> contents
2621 * from the response.</li>
2622 * <li>Find the DOM element whose identifier matches <code>before id</code> and insert
2623 * the <code><before></code> element's <code>CDATA</code> content before
2624 * the DOM element in the document.</li>
2625 * </ul>
2626 * </li>
2627 *
2628 * <li>If an <code><insert></code> element is found in
2629 * the response with a nested <code><after></code>
2630 * element:
2631 *
2632 * <pre><code><insert>
2633 * <after id="after id">
2634 * <![CDATA[...]]>
2635 * </after>
2636 * </insert></code></pre>
2637 *
2638 * <ul>
2639 * <li>Extract this <code><after></code> element's <code>CDATA</code> contents
2640 * from the response.</li>
2641 * <li>Find the DOM element whose identifier matches <code>after id</code> and insert
2642 * the <code><after></code> element's <code>CDATA</code> content after
2643 * the DOM element in the document.</li>
2644 * </ul>
2645 * </li>
2646 * <p><i>Delete Element Processing</i></p>
2647 * <li>If a <code><delete></code> element is found in the response:
2648 * <pre><code><delete id="delete id"/></code></pre>
2649 * Find the DOM element whose identifier matches <code>delete id</code> and remove it
2650 * from the DOM.</li>
2651 * <p><i>Element Attribute Update Processing</i></p>
2652 * <li>If an <code><attributes></code> element is found in the response:
2653 * <pre><code><attributes id="id of element with attribute">
2654 * <attribute name="attribute name" value="attribute value">
2655 * ...
2656 * </attributes></code></pre>
2657 * <ul>
2658 * <li>Find the DOM element that matches the <code><attributes></code> identifier.</li>
2659 * <li>For each nested <code><attribute></code> element in <code><attribute></code>,
2660 * update the DOM element attribute value (whose name matches <code>attribute name</code>),
2661 * with <code>attribute value</code>.</li>
2662 * </ul>
2663 * </li>
2664 * <p><i>JavaScript Processing</i></p>
2665 * <li>If an <code><eval></code> element is found in the response:
2666 * <pre><code><eval>
2667 * <![CDATA[...JavaScript...]]>
2668 * </eval></code></pre>
2669 * <ul>
2670 * <li>Extract this <code><eval></code> element's <code>CDATA</code> contents
2671 * from the response and execute it as if it were JavaScript code.</li>
2672 * </ul>
2673 * </li>
2674 * <p><i>Redirect Processing</i></p>
2675 * <li>If a <code><redirect></code> element is found in the response:
2676 * <pre><code><redirect url="redirect url"/></code></pre>
2677 * Cause a redirect to the url <code>redirect url</code>.</li>
2678 * <p><i>Error Processing</i></p>
2679 * <li>If an <code><error></code> element is found in the response:
2680 * <pre><code><error>
2681 * <error-name>..fully qualified class name string...<error-name>
2682 * <error-message><![CDATA[...]]><error-message>
2683 * </error></code></pre>
2684 * Extract this <code><error></code> element's <code>error-name</code> contents
2685 * and the <code>error-message</code> contents. Signal a <code>serverError</code> passing
2686 * the <code>errorName</code> and <code>errorMessage</code>. Refer to
2687 * section "Signaling Errors" in Chapter 13 of the spec prose document <a
2688 * href="../../javadocs/overview-summary.html#prose_document">linked in the
2689 * overview summary</a>.</li>
2690 * <p><i>Extensions</i></p>
2691 * <li>The <code><extensions></code> element provides a way for framework
2692 * implementations to provide their own information.</li>
2693 * <p><li>The implementation must check if <script> elements in the response can
2694 * be automatically run, as some browsers support this feature and some do not.
2695 * If they can not be run, then scripts should be extracted from the response and
2696 * run separately.</li></p>
2697 * </ul>
2698 *
2699 * </p>
2700 *
2701 * @param request The <code>XMLHttpRequest</code> instance that
2702 * contains the status code and response message from the server.
2703 *
2704 * @param context An object containing the request context, including the following properties:
2705 * the source element, per call onerror callback function, and per call onevent callback function.
2706 *
2707 * @throws Error if request contains no data
2708 *
2709 * @function jsf.ajax.response
2710 */2711response:functionresponse(request,context){2712if(!request){2713thrownewError("jsf.ajax.response: Request parameter is unset");2714}27152716// ensure context source is the dom element and not the ID2717// per 14.4.1 of the 2.0 specification. We're doing it here2718// *before* any errors or events are propagated becasue the2719// DOM element may be removed after the update has been processed.2720if(typeofcontext.sourceid==='string'){2721context.sourceid=document.getElementById(context.sourceid);2722}27232724varxml=request.responseXML;2725if(xml===null){2726sendError(request,context,"emptyResponse");2727return;2728}27292730if(getParseErrorText(xml)!==PARSED_OK){2731sendError(request,context,"malformedXML");2732return;2733}27342735varpartialResponse=xml.getElementsByTagName("partial-response")[0];2736varpartialResponseId=partialResponse.getAttribute("id");2737varresponseType=partialResponse.firstChild;27382739if(responseType.nodeName==="error"){// it's an error2740varerrorName="";2741varerrorMessage="";27422743varelement=responseType.firstChild;2744if(element.nodeName==="error-name"){2745if(null!=element.firstChild){2746errorName=element.firstChild.nodeValue;2747}2748}27492750element=responseType.firstChild.nextSibling;2751if(element.nodeName==="error-message"){2752if(null!=element.firstChild){2753errorMessage=element.firstChild.nodeValue;2754}2755}2756sendError(request,context,"serverError",null,errorName,errorMessage);2757sendEvent(request,context,"success");2758return;2759}276027612762if(responseType.nodeName==="redirect"){2763window.location=responseType.getAttribute("url");2764return;2765}276627672768if(responseType.nodeName!=="changes"){2769sendError(request,context,"malformedXML","Top level node must be one of: changes, redirect, error, received: "+responseType.nodeName+" instead.");2770return;2771}277227732774varchanges=responseType.childNodes;27752776try{2777for(vari=0;i<changes.length;i++){2778switch(changes[i].nodeName){2779case"update":2780doUpdate(changes[i],context,partialResponseId);2781break;2782case"delete":2783doDelete(changes[i]);2784break;2785case"insert":2786doInsert(changes[i]);2787break;2788case"attributes":2789doAttributes(changes[i]);2790break;2791case"eval":2792doEval(changes[i]);2793break;2794case"extension":2795// no action2796break;2797default:2798sendError(request,context,"malformedXML","Changes allowed are: update, delete, insert, attributes, eval, extension. Received "+changes[i].nodeName+" instead.");2799return;2800}2801}2802}catch(ex){2803sendError(request,context,"malformedXML",ex.message);2804return;2805}2806sendEvent(request,context,"success");28072808}2809};2810}();28112812/**
2813 *
2814 * <p>Return the value of <code>Application.getProjectStage()</code> for
2815 * the currently running application instance. Calling this method must
2816 * not cause any network transaction to happen to the server.</p>
2817 * <p><b>Usage:</b></p>
2818 * <pre><code>
2819 * var stage = jsf.getProjectStage();
2820 * if (stage === ProjectStage.Development) {
2821 * ...
2822 * } else if stage === ProjectStage.Production) {
2823 * ...
2824 * }
2825 * </code></pre>
2826 *
2827 * @returns String <code>String</code> representing the current state of the
2828 * running application in a typical product development lifecycle. Refer
2829 * to <code>javax.faces.application.Application.getProjectStage</code> and
2830 * <code>javax.faces.application.ProjectStage</code>.
2831 * @function jsf.getProjectStage
2832 */2833jsf.getProjectStage=function(){2834// First, return cached value if available2835if(typeofmojarra!=='undefined'&&typeofmojarra.projectStageCache!=='undefined'){2836returnmojarra.projectStageCache;2837}2838varscripts=document.getElementsByTagName("script");// nodelist of scripts2839varscript;// jsf.js script2840vars=0;// incremental variable for for loop2841varstage;// temp value for stage2842varmatch;// temp value for match2843while(s<scripts.length){2844if(typeofscripts[s].src==='string'&&scripts[s].src.match('\/javax\.faces\.resource\/jsf\.js\?.*ln=javax\.faces')){2845script=scripts[s].src;2846break;2847}2848s++;2849}2850if(typeofscript=="string"){2851match=script.match("stage=(.*)");2852if(match){2853stage=match[1];2854}2855}2856if(typeofstage==='undefined'||!stage){2857stage="Production";2858}28592860mojarra=mojarra||{};2861mojarra.projectStageCache=stage;28622863returnmojarra.projectStageCache;2864};286528662867/**
2868 * <p>Collect and encode state for input controls associated
2869 * with the specified <code>form</code> element. This will include
2870 * all input controls of type <code>hidden</code>.</p>
2871 * <p><b>Usage:</b></p>
2872 * <pre><code>
2873 * var state = jsf.getViewState(form);
2874 * </pre></code>
2875 *
2876 * @param form The <code>form</code> element whose contained
2877 * <code>input</code> controls will be collected and encoded.
2878 * Only successful controls will be collected and encoded in
2879 * accordance with: <a href="http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2">
2880 * Section 17.13.2 of the HTML Specification</a>.
2881 *
2882 * @returns String The encoded state for the specified form's input controls.
2883 * @function jsf.getViewState
2884 */2885jsf.getViewState=function(form){2886if(!form){2887thrownewError("jsf.getViewState: form must be set");2888}2889varels=form.elements;2890varlen=els.length;2891// create an array which we'll use to hold all the intermediate strings2892// this bypasses a problem in IE when repeatedly concatenating very2893// large strings - we'll perform the concatenation once at the end2894varqString=[];2895varaddField=function(name,value){2896vartmpStr="";2897if(qString.length>0){2898tmpStr="&";2899}2900tmpStr+=encodeURIComponent(name)+"="+encodeURIComponent(value);2901qString.push(tmpStr);2902};2903for(vari=0;i<len;i++){2904varel=els[i];2905if(el.name===""){2906continue;2907}2908if(!el.disabled){2909switch(el.type){2910case'submit':2911case'reset':2912case'image':2913case'file':2914break;2915case'select-one':2916if(el.selectedIndex>=0){2917addField(el.name,el.options[el.selectedIndex].value);2918}2919break;2920case'select-multiple':2921for(varj=0;j<el.options.length;j++){2922if(el.options[j].selected){2923addField(el.name,el.options[j].value);2924}2925}2926break;2927case'checkbox':2928case'radio':2929if(el.checked){2930addField(el.name,el.value||'on');2931}2932break;2933default:2934// this is for any input incl. text', 'password', 'hidden', 'textarea'2935varnodeName=el.nodeName.toLowerCase();2936if(nodeName==="input"||nodeName==="select"||2937nodeName==="button"||nodeName==="object"||2938nodeName==="textarea"){2939addField(el.name,el.value);2940}2941break;2942}2943}2944}2945// concatenate the array2946returnqString.join("");2947};29482949/**
2950 * <p class="changed_added_2_2">Return the windowId of the window
2951 * in which the argument form is rendered.</p>
29522953 * @param {optional String|DomNode} node. Determine the nature of
2954 * the argument. If not present, search for the windowId within
2955 * <code>document.forms</code>. If present and the value is a
2956 * string, assume the string is a DOM id and get the element with
2957 * that id and start the search from there. If present and the
2958 * value is a DOM element, start the search from there.
29592960 * @returns String The windowId of the current window, or null
2961 * if the windowId cannot be determined.
29622963 * @throws an error if more than one unique WindowId is found.
29642965 * @function jsf.getViewState
2966 */2967jsf.getClientWindow=function(node){2968varFORM="form";2969varWIN_ID="javax.faces.ClientWindow";29702971varfetchWindowIdFromForms=function(forms){2972varresult_idx={};2973varresult;2974varfoundCnt=0;2975for(varcnt=forms.length-1;cnt>=0;cnt--){2976varUDEF='undefined';2977varcurrentForm=forms[cnt];2978varwindowId=currentForm[WIN_ID]&¤tForm[WIN_ID].value;2979if(UDEF!=typeofwindowId){2980if(foundCnt>0&&UDEF==typeofresult_idx[windowId])throwError("Multiple different windowIds found in document");2981result=windowId;2982result_idx[windowId]=true;2983foundCnt++;2984}2985}2986returnresult;2987}29882989/**
2990 * @ignore
2991 */2992vargetChildForms=function(currentElement){2993//Special condition no element we return document forms2994//as search parameter, ideal would be to2995//have the viewroot here but the frameworks2996//can deal with that themselves by using2997//the viewroot as currentElement2998if(!currentElement){2999returndocument.forms;3000}30013002vartargetArr=[];3003if(!currentElement.tagName)return[];3004elseif(currentElement.tagName.toLowerCase()==FORM){3005targetArr.push(currentElement);3006returntargetArr;3007}30083009//if query selectors are supported we can take3010//a non recursive shortcut3011if(currentElement.querySelectorAll){3012returncurrentElement.querySelectorAll(FORM);3013}30143015//old recursive way, due to flakeyness of querySelectorAll3016for(varcnt=currentElement.childNodes.length-1;cnt>=0;cnt--){3017varcurrentChild=currentElement.childNodes[cnt];3018targetArr=targetArr.concat(getChildForms(currentChild,FORM));3019}3020returntargetArr;3021}30223023/**
3024 * @ignore
3025 */3026varfetchWindowIdFromURL=function(){3027varhref=window.location.href;3028varwindowId="windowId";3029varregex=newRegExp("[\\?&]"+windowId+"=([^\\;]*)");3030varresults=regex.exec(href);3031//initial trial over the url and a regexp3032if(results!=null)returnresults[1];3033returnnull;3034}30353036//byId ($)3037varfinalNode=(node&&(typeofnode=="string"||nodeinstanceofString))?3038document.getElementById(node):(node||null);30393040varforms=getChildForms(finalNode);3041varresult=fetchWindowIdFromForms(forms);3042return(null!=result)?result:fetchWindowIdFromURL();304330443045};304630473048/**
3049 * The namespace for JavaServer Faces JavaScript utilities.
3050 * @name jsf.util
3051 * @namespace
3052 */3053jsf.util={};30543055/**
3056 * <p>A varargs function that invokes an arbitrary number of scripts.
3057 * If any script in the chain returns false, the chain is short-circuited
3058 * and subsequent scripts are not invoked. Any number of scripts may
3059 * specified after the <code>event</code> argument.</p>
3060 *
3061 * @param source The DOM element that triggered this Ajax request, or an
3062 * id string of the element to use as the triggering element.
3063 * @param event The DOM event that triggered this Ajax request. The
3064 * <code>event</code> argument is optional.
3065 *
3066 * @returns boolean <code>false</code> if any scripts in the chain return <code>false</code>,
3067 * otherwise returns <code>true</code>
3068 *
3069 * @function jsf.util.chain
3070 */3071jsf.util.chain=function(source,event){30723073if(arguments.length<3){3074returntrue;3075}30763077// RELEASE_PENDING rogerk - shouldn't this be getElementById instead of null3078varthisArg=(typeofsource==='object')?source:null;30793080// Call back any scripts that were passed in3081for(vari=2;i<arguments.length;i++){30823083varf=newFunction("event",arguments[i]);3084varreturnValue=f.call(thisArg,event);30853086if(returnValue===false){3087returnfalse;3088}3089}3090returntrue;30913092};30933094/**
3095 * <p class="changed_added_2_2">The result of calling
3096 * <code>UINamingContainer.getNamingContainerSeparatorChar().</code></p>
3097 */3098jsf.separatorchar='#{facesContext.namingContainerSeparatorChar}';30993100/**
3101 * <p>An integer specifying the specification version that this file implements.
3102 * It's format is: rightmost two digits, bug release number, next two digits,
3103 * minor release number, leftmost digits, major release number.
3104 * This number may only be incremented by a new release of the specification.</p>
3105 */3106jsf.specversion=22000;31073108/**
3109 * <p>An integer specifying the implementation version that this file implements.
3110 * It's a monotonically increasing number, reset with every increment of
3111 * <code>jsf.specversion</code>
3112 * This number is implementation dependent.</p>
3113 */3114jsf.implversion=3;311531163117}//end if version detection block3118