/* * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * Copyright 2004-2008 Emmanouil Batsis, mailto: mbatsis at users full stop sourceforge full stop net * Copyright 2004-2008 Emmanouil Batsis, mailto: mbatsis at users full stop sourceforge full stop net * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** @project JSF JavaScript Library @version 2.2 @description This is the standard implementation of the JSF JavaScript Library. */ // Detect if this is already loaded, and if loaded, if it's a higher version if (!((jsf && jsf.specversion && jsf.specversion >= 23000 ) && (jsf.implversion && jsf.implversion >= 3))) { /** * The top level global namespace * for JavaServer Faces functionality. * @name jsf * @namespace */ var jsf = {}; /** * The namespace for Ajax * functionality. * @name jsf.ajax * @namespace * @exec */ jsf.ajax = function() { var eventListeners = []; var errorListeners = []; var delayHandler = null; /** * Determine if the current browser is part of Microsoft's failed attempt at * standards modification. * @ignore */ var isIE = function isIE() { if (typeof isIECache !== "undefined") { return isIECache; } isIECache = document.all && window.ActiveXObject && navigator.userAgent.toLowerCase().indexOf("msie") > -1 && navigator.userAgent.toLowerCase().indexOf("opera") == -1; return isIECache; }; var isIECache; /** * Determine the version of IE. * @ignore */ var getIEVersion = function getIEVersion() { if (typeof IEVersionCache !== "undefined") { return IEVersionCache; } if (/MSIE ([0-9]+)/.test(navigator.userAgent)) { IEVersionCache = parseInt(RegExp.$1); } else { IEVersionCache = -1; } return IEVersionCache; } var IEVersionCache; /** * Determine if loading scripts into the page executes the script. * This is instead of doing a complicated browser detection algorithm. Some do, some don't. * @returns {boolean} does including a script in the dom execute it? * @ignore */ var isAutoExec = function isAutoExec() { try { if (typeof isAutoExecCache !== "undefined") { return isAutoExecCache; } var autoExecTestString = ""; var tempElement = document.createElement('span'); tempElement.innerHTML = autoExecTestString; var body = document.getElementsByTagName('body')[0]; var tempNode = body.appendChild(tempElement); if (mojarra && mojarra.autoExecTest) { isAutoExecCache = true; delete mojarra.autoExecTest; } else { isAutoExecCache = false; } deleteNode(tempNode); return isAutoExecCache; } catch (ex) { // OK, that didn't work, we'll have to make an assumption if (typeof isAutoExecCache === "undefined") { isAutoExecCache = false; } return isAutoExecCache; } }; var isAutoExecCache; /** * @ignore */ var getTransport = function getTransport(context) { var returnVal; // Here we check for encoding type for file upload(s). // This is where we would also include a check for the existence of // input file control for the current form (see hasInputFileControl // function) but IE9 (at least) seems to render controls outside of // form. if (typeof context !== 'undefined' && context !== null && context.includesInputFile && context.form.enctype === "multipart/form-data") { returnVal = new FrameTransport(context); return returnVal; } var methods = [ function() { return new XMLHttpRequest(); }, function() { return new ActiveXObject('Msxml2.XMLHTTP'); }, function() { return new ActiveXObject('Microsoft.XMLHTTP'); } ]; for (var i = 0, len = methods.length; i < len; i++) { try { returnVal = methods[i](); } catch(e) { continue; } return returnVal; } throw new Error('Could not create an XHR object.'); }; /** * Used for iframe based communication (instead of XHR). * @ignore */ var FrameTransport = function FrameTransport(context) { this.context = context; this.frame = null; this.FRAME_ID = "JSFFrameId"; this.FRAME_PARTIAL_ID = "Faces-Request"; this.partial = null; this.aborted = false; this.responseText = null; this.responseXML = null; this.readyState = 0; this.requestHeader = {}; this.status = null; this.method = null; this.url = null; this.requestParams = null; }; /** * Extends FrameTransport an adds method functionality. * @ignore */ FrameTransport.prototype = { /** *@ignore */ setRequestHeader:function(key, value) { if (typeof(value) !== "undefined") { this.requestHeader[key] = value; } }, /** * Creates the hidden iframe and sets readystate. * @ignore */ open:function(method, url, async) { this.method = method; this.url = url; this.async = async; this.frame = document.getElementById(this.FRAME_ID); if (this.frame) { this.frame.parentNode.removeChild(this.frame); this.frame = null; } if (!this.frame) { if ((!isIE() && !isIE9Plus())) { this.frame = document.createElement('iframe'); this.frame.src = "about:blank"; this.frame.id = this.FRAME_ID; this.frame.name = this.FRAME_ID; this.frame.type = "content"; this.frame.collapsed = "true"; this.frame.style = "visibility:hidden"; this.frame.width = "0"; this.frame.height = "0"; this.frame.style = "border:0"; this.frame.frameBorder = 0; document.body.appendChild(this.frame); this.frame.onload = bind(this, this.callback); } else { var div = document.createElement("div"); div.id = "frameDiv"; div.innerHTML = ""; document.body.appendChild(div); this.frame = document.getElementById(this.FRAME_ID); this.frame.onload_cb = bind(this, this.callback); } } // Create to send "Faces-Request" param with value "partial/ajax" // For iframe approach we are sending as request parameter // For non-iframe (xhr ajax) it is sent in the request header this.partial = document.createElement("input"); this.partial.setAttribute("type", "hidden"); this.partial.setAttribute("id", this.FRAME_PARTIAL_ID); this.partial.setAttribute("name", this.FRAME_PARTIAL_ID); this.partial.setAttribute("value", "partial/ajax"); this.context.form.appendChild(this.partial); this.readyState = 1; }, /** * Sets the form target to iframe, sets up request parameters * and submits the form. * @ignore */ send: function(data) { var evt = {}; this.context.form.target = this.frame.name; this.context.form.method = this.method; if (this.url) { this.context.form.action = this.url; } this.readyState = 3; this.onreadystatechange(evt); var ddata = decodeURIComponent(data); var dataArray = ddata.split("&"); var input; this.requestParams = new Array(); for (var i=0; i 1 ? results : results[0]; }; /** * Get the form element which encloses the supplied element. * @param element - element to act against in search * @returns form element representing enclosing form, or first form if none found. * @ignore */ var getForm = function getForm(element) { if (element) { var form = $(element); while (form) { if (form.nodeName && (form.nodeName.toLowerCase() == 'form')) { return form; } if (form.form) { return form.form; } if (form.parentNode) { form = form.parentNode; } else { form = null; } } return document.forms[0]; } return null; }; /** * Get an array of all JSF form elements which need their view state to be updated. * This covers at least the form that submitted the request and any form that is covered in the render target list. * * @param context An object containing the request context, including the following properties: * the source element, per call onerror callback function, per call onevent callback function, the render * instructions, the submitting form ID, the naming container ID and naming container prefix. */ var getFormsToUpdate = function getFormsToUpdate(context) { var formsToUpdate = []; var add = function(element) { if (element) { if (element.nodeName && element.nodeName.toLowerCase() == "form" && element.method == "post" && element.id && element.elements && element.id.indexOf(context.namingContainerPrefix) == 0) { formsToUpdate.push(element); } else { var forms = element.getElementsByTagName("form"); for (var i = 0; i < forms.length; i++) { add(forms[i]); } } } } if (context.formId) { add(document.getElementById(context.formId)); } if (context.render) { if (context.render.indexOf("@all") >= 0) { add(document); } else { var clientIds = context.render.split(" "); for (var i = 0; i < clientIds.length; i++) { if (clientIds.hasOwnProperty(i)) { add(document.getElementById(clientIds[i])); } } } } return formsToUpdate; } /** *

Namespace given space separated parameters if necessary (only * call this if there is a namingContainerPrefix!). This * function is here for backwards compatibility with manual * jsf.ajax.request() calls written before Spec790 changes.

* @param parameters Spaceseparated string of parameters as * usually specified in f:ajax execute and render attributes. * @param sourceClientId The client ID of the f:ajax * source. This is to be used for prefixing relative target * client IDs. * It's expected that this already starts with * namingContainerPrefix. * @param namingContainerPrefix The naming container prefix (the * view root ID suffixed with separator character). * This is to be used for prefixing absolute target client IDs. * @ignore */ var namespaceParametersIfNecessary = function namespaceParametersIfNecessary(parameters, sourceClientId, namingContainerPrefix) { if (sourceClientId.indexOf(namingContainerPrefix) != 0) { return parameters; // Unexpected source client ID; let's silently do nothing. } var targetClientIds = parameters.replace(/^\s+|\s+$/g, '').split(/\s+/g); for (var i = 0; i < targetClientIds.length; i++) { var targetClientId = targetClientIds[i]; if (targetClientId.indexOf(jsf.separatorchar) == 0) { targetClientId = targetClientId.substring(1); if (targetClientId.indexOf(namingContainerPrefix) != 0) { targetClientId = namingContainerPrefix + targetClientId; } } else if (targetClientId.indexOf(namingContainerPrefix) != 0) { var parentClientId = sourceClientId.substring(0, sourceClientId.lastIndexOf(jsf.separatorchar)); if (namingContainerPrefix + targetClientId == parentClientId) { targetClientId = parentClientId; } else { targetClientId = parentClientId + jsf.separatorchar + targetClientId; } } targetClientIds[i] = targetClientId; } return targetClientIds.join(' '); }; /** * Check if a value exists in an array * @ignore */ var isInArray = function isInArray(array, value) { for (var i = 0; i < array.length; i++) { if (array[i] === value) { return true; } } return false; }; /** * Evaluate JavaScript code in a global context. * @param src JavaScript code to evaluate * @ignore */ var globalEval = function globalEval(src) { if (window.execScript) { window.execScript(src); return; } // We have to wrap the call in an anon function because of a firefox bug, where this is incorrectly set // We need to explicitly call window.eval because of a Chrome peculiarity /** * @ignore */ var fn = function() { window.eval.call(window,src); }; fn(); }; /** * Get all scripts from supplied string, return them as an array for later processing. * @param str * @returns {array} of script text * @ignore */ var getScripts = function getScripts(str) { // Regex to find all scripts in a string var findscripts = /]*>([\S\s]*?)<\/script>/igm; // Regex to find one script, to isolate it's content [2] and attributes [1] var findscript = /]*)>([\S\s]*?)<\/script>/im; // Regex to find type attribute var findtype = /type="([\S]*?)"/im; var initialnodes = []; var scripts = []; initialnodes = str.match(findscripts); while (!!initialnodes && initialnodes.length > 0) { var scriptStr = []; scriptStr = initialnodes.shift().match(findscript); // check the type - skip if it not javascript type var type = []; type = scriptStr[1].match(findtype); if ( !!type && type[1]) { if (type[1] !== "text/javascript") { continue; } } scripts.push(scriptStr); } return scripts; }; var removeScripts = function removeScripts(str) { return str.replace(/]*type="text\/javascript"[^>]*>([\S\s]*?)<\/script>/igm,""); }; /** * Run an array of script nodes, * @param scripts Array of script nodes. * @ignore */ var runScripts = function runScripts(scripts) { if (!scripts || scripts.length === 0) { return; } var loadedScripts = document.getElementsByTagName("script"); var loadedScriptUrls = []; for (var i = 0; i < loadedScripts.length; i++) { var scriptNode = loadedScripts[i]; var url = scriptNode.getAttribute("src"); if (url) { loadedScriptUrls.push(url); } } var head = document.head || document.getElementsByTagName('head')[0] || document.documentElement; runScript(head, loadedScriptUrls, scripts, 0); }; /** * Run script at given index. * @param head Document's head. * @param loadedScriptUrls URLs of scripts which are already loaded. * @param scripts Array of script nodes. * @param index Index of script to be loaded. * @ignore */ var runScript = function runScript(head, loadedScriptUrls, scripts, index) { if (index >= scripts.length) { return; } // Regex to find src attribute var findsrc = /src="([\S]*?)"/im; // Regex to remove leading cruft var stripStart = /^\s*(