// Licensed Materials - Property of IBM
//
// IBM Cognos Products: cpscrn
//
// (C) Copyright IBM Corp. 2005, 2022
//
// US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
//
/*
* Global objects:
* _F_Ajax : Allows AJAX calls back to IBM Cognos gateway or web content.
* _F_Config : Configuration (browser, XMLHttpRequest, URI, etc.)
* _F_Document : Allows high-level modification of the HTML document.
* _F_DOM : Helper functions for reading XML document.
* _F_Drag : Drag & Drop functionality
* _F_Event : Event module
* _F_Form : Form helper functions
* _F_Queue : Queue and runable management
* _F_Resource : Resource loading (LINK & SCRIPT)
* _F_Strings : String helper functions
*/
/**
* _F_Config : Configuration (browser, XMLHttpRequest, URI, etc.)
*/
_F_Config =
{
origObj: window._F_Config !== undefined? window._F_Config : null,
version: (window._F_Config !== undefined && window._F_Config.version !== undefined)? window._F_Config.version: "1.0.2",
browser: "unknown",
browserVersion: "unknown",
OS: "unknown",
enableLog: false,
xmlHttpDefault: null,
webContent: (window._F_Config !== undefined && window._F_Config.webContent !== undefined)? window._F_Config.webContent:null,
gateway: (window._F_Config !== undefined && window._F_Config.gateway !== undefined)? window._F_Config.gateway:null,
application: (window._F_Config !== undefined && window._F_Config.application !== undefined)? window._F_Config.application:null,
help: (window._F_Config !== undefined && window._F_Config.help !== undefined)? window._F_Config.help:null,
responsePattern: (window._F_Config !== undefined && window._F_Config.responsePattern !== undefined)? window._F_Config.responsePattern:null,
cookieSecure: (window._F_Config !== undefined && window._F_Config.cookieSecure !== undefined)? window._F_Config.cookieSecure:null,
initialize: function()
{
this.browser = this.lookup(this.browsers).toLowerCase() || "unknown";
this.browserVersion = this.parseVersion(navigator.userAgent) || this.parseVersion(navigator.appVersion) || "unknown";
this.OS = this.lookup(this.systems) || "unknown";
this.xmlHttpDefault = this.findXMLHttpActiveXVersion();
if (this.origObj != null){
for (var key in this.origObj){
if ((this[key] === undefined)&& !(this.origObj[key] instanceof Function)){
this[key] = this.origObj[key];
}
}
delete this.origObj;
}
// create authtoken
if(window.CAMAuthenticityTokenSession){
var authTokenSession = new CAMAuthenticityTokenSession();
this.authToken = authTokenSession.generate();
}
},
getSecure: function()
{
if (this.cookieSecure === 'true') {
return true;
}
return null;
},
/**
* Expands the $CGI$ and $WEB$ macros to their configured values or values passed in the params parameter
* E.g. $CGI$/dashboard?x=1 ==> /cognos8/cgi-bin/cognos.cgi
* @param text usually an url
* @param params an associative array containing values to replace the macros with. This param is optional
*/
expandMacros: function(text, params)
{
var theGateway = this.gateway;
var theWebContent = this.webContent;
var theProductLocale = this.productLocale;
var theSkin = this.skin;
if (typeof params !== 'undefined'){
if (typeof params.gateway !== 'undefined'){
theGateway = params.gateway;
}
if (typeof params.webContent !== 'undefined'){
theWebContent = params.webContent;
}
if (typeof params.productLocale !== 'undefined'){
theProductLocale = params.productLocale;
}
if (typeof params.skin !== 'undefined'){
theSkin = params.skin;
}
}
return text.replace(/\$CGI\$/g, theGateway).replace(/\$WEB\$/g, theWebContent).replace(/\$PRODUCT_LOCALE\$/g, theProductLocale).replace(/\$SKIN\$/g, theSkin);
},
/**
* Builds a url to the gateway.
* @param uri (e.g. /xts.run?m=/portal/main.xts)
*/
buildGatewayURI: function(uri)
{
return this.gateway + (uri||"");
},
/**
* Builds a url to an fragment application.
* @param app (e.g. "/dashboard") if not specified, _F_Config.application will be used.
* @param uri (e.g. "/pages/dashboard.xml)
*/
buildApplicationURI: function(app, uri)
{
return this.gateway + (app||this.application) + (uri||"");
},
/**
* Builds a url to a web content resource.
* @param uri
*/
buildWebContentURI: function(uri)
{
return this.webContent + (uri||"");
},
lookup: function(data)
{
var i, l = data.length;
for (i = 0; i < l; i++)
{
this.versionKey = data[i].partialKey || data[i].identity;
var agent = data[i].agent;
if (agent) {
if (agent.indexOf(data[i].key) != -1) {
return data[i].identity;
}
} else if (data[i].prop) {
return data[i].identity;
}
}
},
parseVersion: function(s)
{
var index = s.indexOf(this.versionKey);
if (index == -1) {
return;
}
return parseFloat(s.substring(index + this.versionKey.length + 1).replace(/[^\d\.\-\+]/g, '_')); //sanitize before parse to avoid XSS vulnerability!
},
findXMLHttpActiveXVersion: function()
{
if (window.ActiveXObject || "ActiveXObject" in window)
{
var i, l = this.xmlHttpVersions.length;
for (i = 0; i < l; i++)
{
try
{
// Try and create the ActiveXObject for Internet Explorer, if it doesn't work, try again.
var xmlhttp = new ActiveXObject(this.xmlHttpVersions[i]);
if (xmlhttp) {
return this.xmlHttpVersions[i];
}
}
catch (e)
{
// this ActiveX is not there, continue with next one in list
}
}
}
return null;
},
emptyFunction: function() {},
browsers: [
{ agent: navigator.userAgent, key: "MSIE", identity: "Explorer", partialKey: "MSIE" },
{ agent: navigator.userAgent, key: "Firefox", identity: "Firefox" },
{ agent: navigator.userAgent, key: "Gecko", identity: "Mozilla", partialKey: "rv" },
{ agent: navigator.userAgent, key: "Mozilla", identity: "Netscape", partialKey: "Mozilla" },
{ agent: navigator.userAgent, key: "Netscape", identity: "Netscape" },
{ prop: window.opera, identity: "Opera" },
{ agent: navigator.vendor, key: "Apple", identity: "Safari" }
],
systems: [
{ agent: navigator.platform, key: "Win", identity: "Windows" },
{ agent: navigator.platform, key: "Mac", identity: "Mac" },
{ agent: navigator.platform, key: "Linux", identity: "Linux" }
],
xmlHttpVersions: [
"Msxml2.XMLHTTP.6.0",
"Msxml2.XMLHTTP.3.0",
"Msxml2.XMLHTTP",
"Microsoft.XMLHTTP"
]
};
/**
* @deprecated: use _F_Config variable
*/
var _F_config = _F_Config;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// utility functions
function $()
{
var element;
if (arguments.length == 1) {
element = arguments[0];
if (typeof element == 'string') {
return document.getElementById(element);
}
return element;
} else {
var elements = [];
var i, l = arguments.length;
for (i = 0; i < l; i++) {
element = arguments[i];
if (typeof element == 'string') {
element = document.getElementById(element);
}
elements.push(element);
}
return elements;
}
}
/**
* _F_Strings : String helper functions
*/
var _F_Strings =
{
normalize: function(text)
{
if (text == null) {
return null;
}
// remove whitespace at beginning and end of the string and
// replace multiple whitespace characters with a single space
return text.replace(/^\s*|\s*$/g,"").replace(/\s+/g," ");
},
urlEncode: function(text)
{
return encodeURIComponent(text);
},
urlDecode: function(text)
{
return decodeURIComponent(text);
},
htmlEncode: function(text)
{
return text
.replace(/\&/g, "&")
.replace(//g, ">");
},
htmlDecode: function(text)
{
return text
.replace(/\</g, '<')
.replace(/\>/g, '>')
.replace(/\&/g, '&');
},
xmlEncode: function(text)
{
return text
.replace(/\&/g, "&")
.replace(/")
.replace(/\'/g, "'")
.replace(/\"/g, '"')
.replace(/\&/g, "&");
}
};
/**
* @deprecated: use _F_Strings.urlEncode()
*/
function urlEncode(text)
{
_F_log("W", "DEPRECATED FUNCTION: urlEncode --> _F_Strings.urlEncode");
return _F_Strings.urlEncode(text);
}
/**
* @deprecated: use _F_Strings.htmlEncode()
*/
function htmlEncode(text)
{
_F_log("W", "DEPRECATED FUNCTION: htmlEncode --> _F_Strings.htmlEncode");
return _F_Strings.htmlEncode(text);
}
/**
* @deprecated: use _F_Strings.xmlEncode()
*/
function xmlEncode(text)
{
_F_log("W", "DEPRECATED FUNCTION: xmlEncode --> _F_Strings.xmlEncode");
return _F_Strings.xmlEncode(text);
}
/**
* @deprecated: use _F_Strings.normalize()
*/
function _F_strip(str)
{
_F_log("W", "DEPRECATED FUNCTION: _F_strip --> _F_Strings.normalize");
return _F_Strings.normalize(str);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Additional Array features
var _F_Array =
{
indexOf: function(array, value, begin, strict)
{
for (var i = +begin || 0, l = array.length; i < l; i++) {
if (array[i] === value || strict && array[i] == value) {
return i;
}
}
return -1;
},
unique: function (array, strict)
{
var a = [], i, l = array.length;
for (i = 0; i < l; i++) {
if (this.indexOf(a, array[i], 0, strict) < 0) {
a.push(array[i]);
}
}
return a;
},
forEach: function(array, func, thisArg)
{
if (typeof func == "function") {
var i, v, l = array.length;
if (thisArg === undefined) {
for (i = 0; i < l; i++) {
func(array[i]);
}
} else {
for (i = 0; i < l; i++) {
func.call(thisArg, array[i]);
}
}
}
},
insert: function(array, i, obj)
{
if (i !== undefined && obj !==undefined) {
array.splice(i, 0, obj);
}
},
remove: function(array, obj)
{
if (obj !== undefined)
{
var i = this.indexOf(array, obj);
if (i >= 0)
{
array.splice(i, 1);
return obj;
}
}
return null;
},
removeAt: function(array, i)
{
if (i !== undefined) {
array.splice(i, 1);
}
}
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// client-side logging functions
function _F_log(type, msg)
{
if (!_F_Config.enableLog) {
return;
}
// Check for Firefox's Firebug extension
if (window.console !== undefined)
{
//Builing params array without the debug key.
var params = [];
for (var i=1; i < arguments.length; i++)
{
params[i-1] = arguments[i];
}
switch (type)
{
case undefined:
break;
case "W":
console.warn.apply(console, params);
break;
case "E":
console.error.apply(console, params);
break;
case "I":
console.info.apply(console, params);
break;
case "D":
case "L":
default:
console.debug.apply(console, params);
break;
}
}
else
{
// basic status logger:
switch (type)
{
case undefined:
window.status = "";
break;
case "W":
window.status = "WARNING: " + msg;
break;
case "E":
window.status = "ERROR: " + msg;
break;
case "I":
window.status = "INFO: " + msg;
break;
case "D":
default:
window.status = "DEBUG: " + msg;
break;
}
}
}
function _F_alert(msg, title)
{
if (title != null) {
window.alert(title + "\n\n" + msg);
} else {
window.alert(msg);
}
}
/**
* _F_Resource : Resource loading (LINK & SCRIPT)
*/
var _F_Resource =
{
loaded: [],
initialize: function()
{
var nodes = document.getElementsByTagName("SCRIPT");
var l = nodes.length;
var i = 0, j=0;
var attrs;
for (i = 0; i < l; i++)
{
attrs = nodes[i].attributes;
for (j = 0; j < attrs.length; j++) {
if (attrs[j].nodeName == "src")
{
this.loaded.push(attrs[j].nodeValue);
break;
}
}
}
nodes = document.getElementsByTagName("LINK");
l = nodes.length;
for (i = 0; i < l; i++)
{
attrs = nodes[i].attributes;
for (j = 0; j < attrs.length; j++) {
if (attrs[j].nodeName == "href")
{
this.loaded.push(attrs[j].nodeValue);
break;
}
}
}
},
loadResource: function(tagName, href, arg1)
{
if (_F_Array.indexOf(this.loaded, href) == -1)
{
tagName = tagName.toUpperCase();
var head = document.getElementsByTagName('HEAD').item(0);
var node = document.createElement(tagName);
var _self = this;
switch (tagName)
{
case "SCRIPT":
node.onload = node.onreadystatechange = function()
{
if (this.readyState && this.readyState != 'loaded' && this.readyState != 'complete') {
return;
}
if (_F_Array.indexOf(_self.loaded, href) != -1) {
return;
}
_self.loaded.push(href);
_F_runQueue.resume();
};
node.type = 'text/javascript';
node.src = href;
head.appendChild(node);
break;
case "LINK":
var cssLoaded = function () {
if (_F_Array.indexOf(_self.loaded, href) != -1) {
// For a CSS file that has import(s), multiple callbacks are possible - which can cause
// synchronization issues when loading script resources - especially in IE.
// This code ensures 'spurious' callbacks are ignored.
return;
}
_self.loaded.push(href);
_F_runQueue.resume();
}
if (xIE4Up) {
// Only IE support the onload event for loading CSS
node.onload = function(){
cssLoaded();
};
}
node.type = 'text/css';
node.rel = "stylesheet";
if (arg1 != null && arg1 != "") {
node.media = arg1;
}
node.href = href;
head.appendChild(node);
if (!xIE4Up) {
// Browser other than IE do not support the onload event for CSS loading.
// In this case, we simply poll and check when it's loaded
var cssId = "css_" +(new Date).getTime();
node.id = cssId;
var count = 0;
var checkCSS = function() {
if (count > 250){
cssLoaded();
return;
}
try {
for(var i = 0; i < document.styleSheets.length; i++) {
if(document.styleSheets[i].ownerNode.id == cssId) {
document.styleSheets[i].cssRules;
cssLoaded();
return;
}
}
} catch(e) {
//swallow any exception and just fall through to trying again
//since firefox throws exception...but safari does not
}
count++;
window.setTimeout(checkCSS, 50);
}
checkCSS();
}
break;
default:
_F_log("E", "unsupported tag named: " + tagName);
break;
}
// indicate to stop the run of the queue
return true;
}
return false;
}
};
/**
* _F_Ajax : Allows AJAX calls back to IBM Cognos gateway or web content.
*
* The url is absolute to the web server. Two macros are supported to ease the url construction:
* - $WEB$ is replaced by the web content root.
* - $CGI$ is replaced by the gateway.
*
* Usage:
*
* var x = new _F_Ajax.Request( "$CGI$/xts.run",
* {
* method: "get",
* parameters: { m: "/read.xts", path: "/content" },
* onSuccess: function(transport) { jscode },
* onFailure: function() { jscode },
* });
*
*
* Options are:
* asynchronous(true) : Determines whether XMLHttpRequest is used asynchronously or not.
* contentType("application/x-www-form-urlencoded") : The Content-Type header for the request.
* encoding("UTF-8") : The encoding of the request contents.
* method("post") : The HTTP method to use for the request.
* parameters(hash-object) : The parameters for the request, which will be encoded into the URL for a 'get' method, or into the request body for the other methods.
* postBody(null) : Specific contents for the request body on a 'post' method. If it is not provided, the contents of the parameters option will be used instead.
* requestHeaders(hash-object) : Request headers as an object, with properties representing headers.
* onSuccess(function) : Invoked when a request completes and its status code is undefined or belongs in the 2xy family.
* onFailure(function) : Invoked when a request completes and its status code exists but is not in the 2xy family.
* onException(function) : Triggered whenever an XMLHttpRequest error arises.
*/
var _F_Ajax =
{
getTransport: function()
{
if (_F_Config.xmlHttpDefault != null) {
return new ActiveXObject(_F_Config.xmlHttpDefault);
}
// Well if there is no ActiveXObject available it must be firefox, opera, or something else
if (typeof XMLHttpRequest != 'undefined')
{
try
{
return new XMLHttpRequest();
}
catch (e)
{
_F_alert(e);
}
}
throw "No XMLHttpRequest object is available";
}
};
/**
* Creates a request object.
* @param url - (mandatory) target url (may contains macros).
* @param options - (mandatory) request's options.
*/
_F_Ajax.Request = function(url, options, caller)
{
try
{
var asynchronous = (options.asynchronous !== undefined) ? options.asynchronous : true;
var contentType = options.contentType || "application/x-www-form-urlencoded";
var encoding = options.encoding;
var method = (options.method || "post").toLowerCase();
var params = "";
var parts = [];
// replace the supported macros
url = _F_Config.expandMacros(url);
if (typeof options.parameters == "object")
{
for (var p in options.parameters)
{
var value = options.parameters[p];
parts.push(encodeURIComponent(p) + '=' + ((value != null) ? encodeURIComponent(value) : ''));
}
params = parts.join('&');
if (params != "")
{
url += ((url.indexOf('?') >= 0) ? '&' : '?') + params;
params = "";
}
}
if ((method == "post" || method == "put") && (options.postBody === undefined))
{
parts = url.split('?');
url = parts[0];
params = parts[1];
}
this.transport = _F_Ajax.getTransport();
this.transport.open(method.toUpperCase(), url, asynchronous);
var headers =
{
"X-Fragment-Version": _F_Config.version,
"X-Controller-Agent": "fragment/" + _F_Config.version,
"Accept": "text/javascript, text/html, application/xml, text/xml, */*"
};
if (method == 'post') {
headers['Content-Type'] = contentType + (encoding ? '; charset=' + encoding : '');
// XSRF-TOKEN cookie is null when disableXSRFCheck=true in bootstrap.properties.
var xsrfTokenCookie = _F_Document.getCookie("XSRF-TOKEN");
if (xsrfTokenCookie) {
headers['X-XSRF-TOKEN'] = xsrfTokenCookie;
}
}
for (var rh in options.requestHeaders) {
headers[rh] = options.requestHeaders[rh];
}
for (var h in headers) {
this.transport.setRequestHeader(h, headers[h]);
}
if (asynchronous)
{
var _self = this;
this.transport.onreadystatechange = function()
{
try
{
if (_self.transport.readyState == 4)
{
if (_self.transport.status >= 200 && _self.transport.status < 300)
{
if (typeof options.onSuccess == "function") {
options.onSuccess.call(_self, _self.transport);
}
}
else
{
if (typeof options.onFailure == "function") {
options.onFailure.call(_self, _self.transport);
}
}
// fix for IE memory leak
_self.transport.onreadystatechange = _F_Config.emptyFunction;
}
}
catch (e)
{
try
{
if (typeof options.onException == "function") {
if (this.status !== 0) {
options.onException.call(this, e);
}
}
}
catch (e1)
{
_F_alert(e1);
}
}
}; // of function
}
this.transport.send(options.postBody || params);
if (!asynchronous)
{
try
{
if (this.transport.status >= 200 && this.transport.status < 300)
{
if (typeof options.onSuccess == "function") {
options.onSuccess.call(this, this.transport);
}
}
else
{
if (typeof options.onFailure == "function") {
options.onFailure.call(this, this.transport);
}
}
}
catch (e)
{
try
{
if (typeof options.onException == "function") {
options.onException.call(this, e);
}
}
catch (e1)
{
_F_alert(e1);
}
}
}
}
catch (e2)
{
try
{
if (typeof options.onException == "function") {
options.onException.call(this, e2);
}
}
catch (e3)
{
_F_alert(e3);
}
this.transport.abort();
}
};
_F_Ajax.Request.prototype =
{
getHeader: function(name)
{
try
{
return this.transport.getResponseHeader(name);
}
catch (e)
{
return null;
}
},
getResponseXml: function () {
var responseXML = null;
if (this.transport.status === 200) {
if ("ActiveXObject" in window) {
responseXML = new ActiveXObject("Microsoft.XMLDOM");
responseXML.async = "false";
responseXML.loadXML(this.transport.responseText);
} else {
var parser = new DOMParser();
responseXML = parser.parseFromString(this.transport.responseText, "text/xml");
}
}
return responseXML;
},
getResponseText: function()
{
return (this.transport.status === 200) ? this.transport.responseText : null;
},
getStatus: function()
{
return this.transport.status;
}
};
/**
* _F_Document : Allows high-level modification of the HTML document.
*/
var _F_Document =
{
associate: function (target, obj, methodName)
{
return function(e)
{
e = e||window.event;
return obj[methodName](e, target);
};
},
addEventListener: function (node, type, callback, capture)
{
type = type.toLowerCase();
if (node.addEventListener) {
node.addEventListener(type, callback, capture);
} else if (node.attachEvent) {
node.attachEvent('on' + type, callback);
} else {
node['on' + type] = callback;
}
},
buildHeadTagId: function(id, tagName)
{
return (id + tagName.toLowerCase() + "s");
},
addHeadTag: function(tagName, text, id)
{
try
{
var head = document.getElementsByTagName('HEAD').item(0);
var domTag, domText;
if (id)
{
domTag = $(id);
if (domTag && domTag.parentNode == head) {
head.removeChild(domTag);
}
}
tagName = tagName.toUpperCase();
domTag = document.createElement(tagName);
if (id) {
domTag.id = id;
}
if (tagName == 'SCRIPT')
{
domTag.type = 'text/javascript';
domTag.text = text;
}
else if (tagName == 'STYLE')
{
domTag.type = 'text/css';
if (domTag.styleSheet)
{
domTag.styleSheet.cssText = text;
}
else
{
domText = document.createTextNode(text);
domTag.appendChild(domText);
}
}
else
{
domText = document.createTextNode(text);
domTag.appendChild(domText);
}
head.appendChild(domTag);
}
catch (e)
{
_F_log("E", e);
}
},
removeHeadTag: function(id)
{
if (id)
{
var head = document.getElementsByTagName('HEAD').item(0);
var domTag = $(id);
if (domTag && domTag.parentNode == head) {
head.removeChild(domTag);
}
domtag = null;
}
},
extractTagText: function(text, tagName)
{
var lowerText = text.toLowerCase();
tagName = tagName.toLowerCase();
var fromIndex = lowerText.indexOf("<" + tagName);
if (fromIndex == -1) {
return "";
}
// skip attributes
fromIndex = lowerText.indexOf(">", fromIndex + tagName.length + 1);
if (fromIndex == -1) {
return "";
}
fromIndex++;
var toIndex = lowerText.indexOf("" + tagName + ">", fromIndex);
if (toIndex == -1) {
return "";
}
return text.substring(fromIndex, toIndex);
},
addHeadUniqueTag: function(parts, id, tagName)
{
if (parts)
{
var combinedParts = "";
var i, l = parts.length;
for (i = 0; i < l; i++) {
combinedParts += this.extractTagText(parts[i], tagName);
}
if (combinedParts != "") {
this.addHeadTag(tagName, combinedParts, this.buildHeadTagId(id, tagName));
}
}
},
getCookie: function(name)
{
var value = null;
if (document.cookie.length > 0)
{
var search = name + "=";
var index = document.cookie.indexOf(search);
if (index != -1)
{
var start = index + search.length;
var end = document.cookie.indexOf(";", start);
if (end == -1) {
end = document.cookie.length;
}
value = unescape(document.cookie.substring(start, end));
}
}
return value;
},
setCookie: function(name, value, expires, path, domain, secure)
{
if (typeof expires == "number")
{
expires = new Date(new Date().getTime() + (1000 * expires));
}
if (!secure) {
secure = _F_Config.getSecure();
}
document.cookie = name + "=" + value +
((expires) ? "; expires=" + expires.toGMTString() : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "");
},
getTextContent: function(obj){
if (obj.innerText) {
return obj.innerText;
}
else if (obj.textContent) {
return obj.textContent;
}
else {
return "";
}
},
parseXml: function(xmlString)
{
var xmlDoc = findXMLHttpActiveXVersion();
if (xmlDoc) {
xmlDoc.async="false";
xmlDoc.loadXML(xmlString);
} else {
var parser = new DOMParser();
xmlDoc = parser.parseFromString(xmlString,"text/xml");
}
return xmlDoc;
}
};
/**
* _F_DOM : Helper functions for reading XML document.
*/
var _F_DOM =
{
selectNodes: function(node, xpath)
{
var arr = [];
var doc = (node.ownerDocument) ? node.ownerDocument : node;
if(doc.evaluate) {
var results = doc.evaluate(xpath, node, doc.createNSResolver(doc.documentElement), XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
if (results)
{
node = results.iterateNext();
while (node != null)
{
arr.push(node);
node = results.iterateNext();
}
return arr;
}
}
else if('all' in document && 'selectNodes' in node) {
var nodes = node.selectNodes(xpath);
var i, l = nodes.length;
for (i=0; i _F_DOM.selectNodes");
return _F_DOM.selectNodes(node, xpath);
}
/**
* @deprecated use _F_DOM.selectSingleNode()
*/
function _F_DOM_selectSingleNode(node, xpath)
{
_F_log("W", "DEPRECATED FUNCTION: _F_DOM_selectSingleNode --> _F_DOM.selectSingleNode");
return _F_DOM.selectSingleNode(node, xpath);
}
/**
* @deprecated use _F_DOM.getAttribute()
*/
function _F_DOM_getAttribute(node, name)
{
_F_log("W", "DEPRECATED FUNCTION: _F_DOM_getAttribute --> _F_DOM.getAttribute");
return _F_DOM.getAttribute(node, name);
}
/**
* @deprecated use _F_DOM.text()
*/
function _F_DOM_text(node)
{
_F_log("W", "DEPRECATED FUNCTION: _F_DOM_text --> _F_DOM.text");
return _F_DOM.text(node);
}
/**
* _F_Form : Form helper functions
*/
var _F_Form =
{
/**
* Finds a form based on its unique name (e.g. _THIS_form)
*/
find: function(name)
{
return document.forms[name];
},
lookupAction: function(action)
{
var forms = document.forms;
var i, l = forms.length;
for (i = 0; i < l; i++) {
if (forms[i].action.indexOf(action) > -1) {
return forms[i];
}
}
return null;
},
getParamForInput: function(form, elem)
{
if (elem.disabled) {
return null;
}
switch (elem.type)
{
case "select-multiple":
var s = "";
var i, l = elem.options.length;
for (i = 0; i < l; i++) {
if (elem.options[i].selected)
{
if (s != "") {
s += "&";
}
s += this.getParamName(form, elem.name) + "=" + _F_Strings.urlEncode(elem.options[i].value);
}
}
if (s != "") {
return s;
}
break;
case "select-one":
if (elem.selectedIndex >= 0) {
return this.getParamName(form, elem.name) + "=" + _F_Strings.urlEncode(elem.value);
}
break;
case "radio":
case "checkbox":
if (!elem.checked) {
return null;
}
case "text":
case "textarea":
case "password":
case "hidden":
case "submit":
if (elem.value != null) {
return this.getParamName(form, elem.name) + "=" + _F_Strings.urlEncode(elem.value);
}
// all other cases, return null
case "button":
return null;
default:
_F_log("W", "unsupported input named: " + elem.name + " (" + elem.type + ")");
break;
}
return null;
},
/**
* Used to override the input names (globally).
*/
getParamName: function(form, name)
{
return name;
},
getParams: function(form)
{
var s = "";
if (form != null)
{
var i, l = form.elements.length;
for (i = 0; i < l; i++)
{
var elem = form.elements[i];
if (elem.name != null && elem.name != "")
{
var param = this.getParamForInput(form, elem);
if (param != null) {
s += "&" + param;
}
}
}
}
return s;
},
getActionParams: function(action)
{
return this.getParams(this.lookupAction(action));
}
};
/**
* @deprecated use _F_Form.getParams()
*/
function _F_formScan(form)
{
_F_log("W", "DEPRECATED FUNCTION: _F_formScan --> _F_Form.getParams");
return _F_Form.getParams(form);
}
/**
* @deprecated use _F_Form.getParamsForAction()
*/
function _F_formParams(action)
{
_F_log("W", "DEPRECATED FUNCTION: _F_formParams --> _F_Form.getActionParams");
return _F_Form.getActionParams(action);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Fragment Functions
function _F_depth(obj)
{
var p = obj.parent;
var count = 1;
while (p != null)
{
count++;
p = p.parent;
}
return count;
}
function _F_descendants(sId, sIdExclude, assoc)
{
// descendants all start with sId, excluding sId
var list = [];
for (var id in fragments)
{
if (fragments[id] != null) {
if (id.indexOf(sId) == 0 && id != sIdExclude) {
list.push(id);
}
}
}
// make sure the list is sorted on ids
list = list.sort();
var result = (assoc) ? {} : [];
var i, l=list.length;
if (assoc) {
for (i=0; i -1)
{
this.dispatch(list, evt, false);
}
}
else
{
// if non-fragment event fired by child of page, distribute event to other children
if (evt.name.indexOf("fragment.") != 0)
{
var targetIndex = _F_Array.indexOf(list, evt.target.id);
if (targetIndex > -1) {
this.dispatch(list, evt, true);
}
}
}
// prevent the default behaviour for fragment.refresh events targetted at an event distributor
if (evt.eventPhase == evt.AT_TARGET && "fragment.refresh" == evt.name) {
evt.preventDefault();
}
if (window._F_Debug !== undefined && evt.debugEnabled()) {
_F_Debug.log.groupEnd();
}
},
/**
* Executes the event's handler function
*/
execute: function(frag, listener, evt)
{
// handle late bound functions
var func = null;
if (typeof listener[1] == "string")
{
try
{
func = eval(listener[1]);
}
catch (e)
{
}
}
else {
func = listener[1];
}
if (typeof func == "function")
{
try
{
func.call(frag, evt);
}
catch (e1)
{
_F_log("E", "Error in event handler function: " + e1 + ", function name=" + listener[1]);
}
}
else {
_F_log("E", "Expecting an event handler function, got: " + listener[1]);
}
}
};
_F_Event.Event = function()
{
this.name = "";
this.type = "";
this.payload = null;
this.source = null;
this.target = null;
this.currentTarget = null;
this.eventPhase = 0;
this.bubbles = true;
this.cancelable = true;
this.cancelled = false;
this.stopped = false;
this.timeStamp = new Date();
this.reflected = false;
};
_F_Event.Event.prototype =
{
CAPTURING_PHASE: 1,
AT_TARGET: 2,
BUBBLING_PHASE: 3,
initEvent: function(name, type, payload, canBubble, cancelable)
{
this.name = name;
this.type = type;
this.payload = payload;
this.bubbles = canBubble;
this.cancelable = cancelable;
this.cancelled = false;
this.stopped = false;
},
preventDefault: function()
{
if (this.cancelable) {
this.cancelled = true;
}
},
stopPropagation: function()
{
this.stopped = true;
}
};
/**
* @deprecated: use _F_Event.distribute()
*/
function _F_eventDistributor(list, evt)
{
_F_log("W", "DEPRECATED FUNCTION: _F_eventDistributor --> _F_Event.distribute");
_F_Event.distribute(list, evt);
}
/**
* @deprecated: use fragment.proxyEvent()
*/
function _F_eventProxy(evt)
{
_F_log("W", "DEPRECATED FUNCTION: _F_eventProxy --> this.proxyEvent");
this.proxyEvent(evt);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Fragment Object
// associative array of all active fragments by id
var fragments = {};
function fragment(path, id, div)
{
this.id = id;
this.path = path;
this.parent = findParent(this.id);
this.div = div ? div : id + "content";
this.state = null;
this.custom = null;
this.mode = "view";
this.windowState = "normal";
this.visibility = "visible";
this.view = "";
this.transientState = {};
this.eventListeners = [];
this.modes = [];
this.windowStates = [];
this.loaded = false;
this.page = false;
this.validator = null;
this.internal = {
requestCount: 0,
locked: false,
dirty: false
};
this.addEventListener("fragment.visibility.change", this.setVisibilityEvent, false);
fragments[this.id] = this;
function findParent(sId)
{
// parent has longest subid
var frag = null;
var fraglen = 0;
for (var id in fragments)
{
var test = fragments[id];
if (test != null)
{
if (sId != test.id && sId.indexOf(test.id) == 0 && test.id.length > fraglen)
{
frag = test;
fraglen = frag.id.length;
}
}
}
return frag;
}
}
fragment.prototype =
{
getRoot: function()
{
var frag = this;
while (frag.parent) {
frag = frag.parent;
}
return frag;
},
getChildren: function()
{
var children = [];
for (var sId in fragments) {
if (fragments[sId].parent == this) {
children.push(fragments[sId]);
}
}
return children;
},
getAncestors: function()
{
var ancestors = [];
var frag = this.parent;
while (frag)
{
ancestors.push(frag);
frag = frag.parent;
}
return ancestors;
},
baseURI: function()
{
return "$CGI$" + _F_Config.application + this.path;
},
attach: function (obj)
{
for (var prop in obj) {
this[prop] = obj[prop];
}
},
encodedTransients: function()
{
var name;
var transients = {};
// add any page level trans, if they are not already included
var p = this.getPageFragment();
for (name in p.transientState) {
if (transients[name] === undefined) {
transients[name] = p.transientState[name];
}
}
// finally, add global transients, if they are not already included
for (name in this.transientGlobal) {
if (transients[name] === undefined) {
transients[name] = this.transientGlobal[name];
}
}
// assemble everything as url
var s = "";
for (name in transients) {
s += "&" + _F_Strings.urlEncode(name) + "=" + _F_Strings.urlEncode(transients[name]);
}
return s;
},
fragmentURI: function()
{
var s = "frag-id=" + this.id +
"&frag-agent=" + _F_Strings.urlEncode(navigator.userAgent) +
"&frag-mode=" + this.mode;
if (_F_config.authToken) {
s += "&frag-authToken=" + _F_Strings.urlEncode(_F_config.authToken);
}
if (this.validator != null && this.validator.remote) {
s += "&frag-validator=" + this.validator.remote;
}
if (this.loaded && this.mode != "view" && _F_Array.indexOf(this.modes, this.mode) == -1) {
s += "&frag-delegate=" + _F_Strings.urlEncode(this.mode);
}
if (this.view != "") {
s += "&frag-view=" + _F_Strings.urlEncode(this.view);
}
if (this.windowState != "") {
s += "&frag-windowState=" + _F_Strings.urlEncode(this.windowState);
}
if (this.channel !== undefined && this.channel != null) {
s += "&frag-channel=" + _F_Strings.urlEncode(this.channel);
}
// state
if (this.state != null) {
s += "&frag-state=" + _F_Strings.urlEncode(this.state);
}
// custom properties
if (this.custom != null) {
s += "&frag-custom=" + _F_Strings.urlEncode(this.custom);
}
// transient properties
s += this.encodedTransients();
if (this.customProperties != null){
var customParams = "";
for (var cp in this.customProperties){
if (customParams != "") {
customParams += "&";
}
customParams+=cp + "=" + _F_Strings.urlEncode(this.customProperties[cp]);
}
s += "&frag-customProperties=" + _F_Strings.urlEncode(customParams);
}
return s;
},
renderURI: function(excludeDescendantState)
{
var s = this.baseURI();
s += ((s.indexOf('?') >= 0) ? "&" : "?") + this.fragmentURI();
if (excludeDescendantState === undefined || excludeDescendantState == false)
{
var descendants = _F_descendants(this.id, this.id);
if (descendants)
{
for (var i=0; i < descendants.length; i++)
{
s += "&frag-sub=" + _F_Strings.urlEncode(descendants[i].fragmentURI());
}
}
}
return s;
},
interactionURI: function(sParams, excludeDescendantState)
{
if (sParams && sParams != "")
{
if (sParams.indexOf('&') != 0) {
return (this.renderURI(excludeDescendantState) + "&" + sParams);
}
else {
return (this.renderURI(excludeDescendantState) + sParams);
}
}
return this.renderURI(excludeDescendantState);
},
update: function(markup, div)
{
div = div ? div : this.div;
var divTag = $(div);
var bFullUpdate = divTag == $(this.div);
var bHasHtml = false;
if (divTag != null)
{
if (bFullUpdate) {
this.raiseEvent("fragment.unload", null, "", false, false);
}
var tempNode = document.createElement("div");
// to get around IE problem. If markup starts with script tag, no at scripts will be loaded in the DOM
tempNode.innerHTML = " " + markup;
tempNode.removeChild(tempNode.firstChild);
var scriptElements = tempNode.getElementsByTagName("SCRIPT");
var scripts = [];
var length = scriptElements.length;
for (var i = length - 1 ; i >= 0; i--){
scripts.unshift("");
if(scriptElements[i].parentNode){
scriptElements[i].parentNode.removeChild(scriptElements[i]);
}
}
var styleElements = tempNode.getElementsByTagName("STYLE");
var styles = [];
length = styleElements.length;
for (var j = length - 1 ; j >= 0 ; j--){
styles.unshift("");
if(styleElements[j].parentNode){
styleElements[j].parentNode.removeChild(styleElements[j]);
}
}
// styles need to be available when html is inserted
_F_Document.addHeadUniqueTag(styles, div, 'style');
if (tempNode.childNodes){
var nodesLength = tempNode.childNodes.length;
for (var k = nodesLength - 1 ; k >= 0; k--){
if ((tempNode.childNodes[k].nodeType != 3) ||
(tempNode.childNodes[k].nodeType == 3 && tempNode.childNodes[k].nodeValue.replace(/^\s*|\s*$/g,"") != "")){
if (!bHasHtml){
divTag.innerHTML = "";
divTag.appendChild(tempNode.childNodes[k]);
bHasHtml = true;
}else{
divTag.insertBefore(tempNode.childNodes[k], divTag.firstChild);
}
}
}
}
tempNode = null;
/*
This is to get around a FF issue where the script is loaded asynchronously.
This means that the "fragment.load" event might be raised before the fragment script is evaluated.
To get around the problem, we add the code that raises the event to the fragment script.
*/
if (bFullUpdate && !xIE4Up){
var loadEventScript = "";
scripts.push(loadEventScript);
}
// html needs to be available to javascript once it is inserted
_F_Document.addHeadUniqueTag(scripts, div, 'script');
if (window._F_Debug !== undefined && this.debugEnabled())
{
_F_Debug.log.logDetails("Update innerHTML for fragment: " + this.id + "\ttitle: " + _F_Strings.normalize(this.title), this);
}
if (bFullUpdate && xIE4Up) {
this.raiseEvent("fragment.load", {source: "retrieve"}, "", false, false);
}
}
else {
_F_log("W", "target div was not found: "+div);
}
return bHasHtml;
},
performAction: function(sParams)
{
this.retrieve(sParams);
},
retrieve: function(sParams, dest, synchronous, excludeDescendantState)
{
if (!this.loaded) {
if (!sParams) {
sParams = "";
}
sParams += "&frag-action=attach";
}
if ( _F_depth(this) > 100)
{
window[this.id] = this;
fragments[this.id] = this;
this.processError("maxnestedlevels", PFM.JS.IDS_JS_ERROR_RETRIEVE, "");
return;
}
// TODO: this function is added in uicommon.js, it should be removed and replaced with events
if (this.clearerror) {
this.clearerror();
}
this.send(sParams, dest, synchronous, excludeDescendantState);
},
send: function(sParams, dest, synchronous, excludeDescendantState)
{
if (this.internal.locked > 0)
{
// don't process this send, just mark the fragment as dirty
this.internal.dirty = true;
return;
}
else
{
this.internal.dirty = false;
if (!this.raiseEvent("fragment.retrieve.before", sParams, "xsd:string"))
{
// preventDefault() was called, so invoke the "after" event
// to keep the before/after contract valid.
this.raiseEvent("fragment.retrieve.after", false, "xsd:boolean");
return;
}
}
// now we can process the request
this.setRefreshDelay(0); // cancel any pending delay
var requestCount = ++this.internal.requestCount;
var _self = this;
var requestOptions = {
requestHeaders:
{
"Connection": "keep-alive",
"Accept": "text/xml,application/xml"
},
onSuccess: function(transport)
{
// make the _THIS_ variable visible
window[_self.id] = _self;
fragments[_self.id] = _self;
if (dest == null) {
dest = _self.div;
}
if (dest == _self.div) {
if (requestCount != _self.internal.requestCount)
{
_F_log("W", "discarding expired response for fragment: "+_self.id);
_self.raiseEvent("fragment.retrieve.after", false, "xsd:boolean");
return; //out of sequence detected - discard this response!
}
}
var responseXML = this.getResponseXml();
var xmlParseError = false;
if (responseXML) {
if ((responseXML.parseError && responseXML.parseError.errorCode != 0) ||
(responseXML.documentElement && responseXML.documentElement.nodeName == "parsererror")) {
xmlParseError = true;
}
} else {
xmlParseError = true;
}
if (!xmlParseError)
{
var fragNode = _F_DOM.selectSingleNode(responseXML, "/fragment");
if (fragNode != null)
{
var list = [];
var i, l, href;
var linkNodes = _F_DOM.selectNodes(fragNode, "./css");
if (linkNodes && linkNodes.length > 0)
{
l = linkNodes.length;
for (i = 0; i < l; i++)
{
href = _F_DOM.getAttribute(linkNodes[i], "href");
var media = _F_DOM.getAttribute(linkNodes[i], "media");
list.push(["LINK", href, media]);
}
}
var librarieNodes = _F_DOM.selectNodes(fragNode, "./library");
if (librarieNodes && librarieNodes.length > 0)
{
l = librarieNodes.length;
for (i = 0; i < l; i++)
{
href = _F_DOM.getAttribute(librarieNodes[i], "href");
list.push(["SCRIPT", href]);
}
}
var processFragmentXMLFunction;
if (xIE4Up && !synchronous) {
// COGCQ0019952
processFragmentXMLFunction = function(){
var _args = arguments;
setTimeout(function(){
_self.processFragmentXML.apply(_self, _args);
}, 1);
};
} else {
processFragmentXMLFunction = _self.processFragmentXML;
}
_self.loadFragmentResources(list, processFragmentXMLFunction, fragNode, dest);
}
else
{
// check if we got an SOAP-Fault
var fault = _F_DOM.selectSingleNode(responseXML, "/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='Fault']");
if (fault != null)
{
var code = _F_DOM.text(_F_DOM.selectSingleNode(fault, "./faultcode"));
var msg = _F_DOM.text(_F_DOM.selectSingleNode(fault, "./faultstring"));
var details = _F_DOM.text(_F_DOM.selectSingleNode(fault, "./faultdetails"));
_self.processError(code, msg, details);
}
else
{
_self.processError("unexpected", PFM.JS.IDS_JS_ERROR_UNEXPECTED_RESPONSE, "");
}
_self.raiseEvent("fragment.retrieve.after", false, "xsd:boolean");
_F_log("W", "expecting XML for fragment: "+_self.id);
}
}
else
{
//DEBUG: error response most likely html, show it
var txt = this.getResponseText();
var ecode = _F_Document.extractTagText(txt, "ERROR_CODE");
if (ecode == "CAM_PASSPORT_ERROR")
{
// substitute the error code to an invalid passport
_self.processError("invalidCredentials", null, null);
_self.raiseEvent("fragment.retrieve.after", false, "xsd:boolean");
_F_log("W", "expecting XML, got HTML for fragment: "+_self.id);
}
else
{
var bReloadPage = false;
if (txt != null && _F_Config.responsePattern != null && _F_Config.responsePattern.length > 0)
{
var patterns = _F_Config.responsePattern.split(",");
var i, l;
var upperTxt = txt.toUpperCase();
for (i = 0, l = patterns.length; i < l; i++) {
if (patterns[i] != "" && (upperTxt.indexOf(patterns[i].toUpperCase()) != -1)) {
// Ignore the HTML response, and reload the page. This will force the same HTML response to be returned
// to this current page (presumably a 3rd party login page) and hopefully they will then redirect you back to
// the current location. (pre AJAX/fragment action)
bReloadPage = true;
location.reload();
}
}
}
if (!bReloadPage) {
// open up that HTML markup and let the end-user deal with it
var emsg = _F_Document.extractTagText(txt, "ERROR_MSG");
var edetails = _F_Document.extractTagText(txt, "ERROR_DETAILS");
_self.processError(ecode, emsg, edetails);
var w = window.open(_F_Config.webContent + "/common/blank.html", _self.id, "width=700,height=600,resizable,status=no,menubar=no,toolbar=no,location=no");
w.document.open();
w.document.write(txt);
w.document.close();
w.focus();
_self.raiseEvent("fragment.retrieve.after", false, "xsd:boolean");
_F_log("W", "expecting XML, got HTML for fragment: "+_self.id);
}
}
}
},
onFailure: function(transport)
{
_self.raiseEvent("fragment.retrieve.after", false, "xsd:boolean");
_F_log("E", "XMLHttp " + transport.status + ", " + transport.statusText);
_F_alert("#" + transport.status + "\n" + transport.statusText, _self.title);
},
onException: function(request, e)
{
_self.raiseEvent("fragment.retrieve.after", false, "xsd:boolean");
_F_alert(e, _self.title);
}
};
if (synchronous != null && synchronous == true)
{
requestOptions.asynchronous=false;
}
var fragRequest = new _F_Ajax.Request(this.interactionURI(sParams, excludeDescendantState), requestOptions, this);
},
processFragmentXML: function(fragNode, dest)
{
// respond to delay
var delayNode = _F_DOM.selectSingleNode(fragNode, "./delay");
if (delayNode)
{
var period = _F_DOM.text(_F_DOM.selectSingleNode(delayNode, "period"));
this.setRefreshDelay(period);
}
var bHasHtml = false;
if (dest !== undefined)
{
var markupNode = _F_DOM.selectSingleNode(fragNode, "./markup/markupString");
if (markupNode)
{
var markup = _F_DOM.text(markupNode);
if (markup == "" && delayNode)
{
markup = _F_DOM.text(_F_DOM.selectSingleNode(delayNode, "message"));
}
if (markup != "")
{
try
{
bHasHtml = this.update(markup, dest);
if (this.onupdate) {
this.onupdate();
}
}
catch (e)
{
_F_log("E", "execution error when updating markup for fragment: "+this.id);
}
}
else {
_F_log("W", "no markup text in markupString for fragment: "+this.id);
}
markupNode = null;
}
}
// respond to newWindow
var newWindowStateNode = _F_DOM.selectSingleNode(fragNode, "./newWindowState");
// and to newMode
var newModeNode = _F_DOM.selectSingleNode(fragNode, "./newMode");
if (newWindowStateNode || newModeNode)
{
var newWindowState = _F_DOM.text(newWindowStateNode);
var newMode = _F_DOM.text(newModeNode);
if (newWindowState != "")
{
// this markup is already using the new window state, assign it right away
this.setWindowState(newWindowState, "internal");
}
if (newMode != "")
{
// this markup is already using the new mode, assign it right away
this.setMode(newMode, "internal");
}
// check if we must reload the fragment because no html was returned.
if (!bHasHtml) {
this.setRefreshDelay(1);
}
}
// respond to validator
var validatorNode = _F_DOM.selectSingleNode(fragNode, "./validator");
if (validatorNode)
{
if (this.validator == null)
{
this.validator = {};
this.validator.remote = null;
this.validator.client = null;
}
try
{
this.validator.remote = _F_DOM.text(_F_DOM.selectSingleNode(validatorNode, "./remote"));
this.validator.client = eval(_F_DOM.text(_F_DOM.selectSingleNode(validatorNode, "./client")));
}
catch (e1)
{
this.validator = null;
_F_log("E", e1);
}
}
var preferredTitleNode = _F_DOM.selectSingleNode(fragNode, "./preferredTitle");
if (preferredTitleNode) {
this.setTitle(_F_DOM.text(preferredTitleNode));
}
else if (this.info != null) {
this.setTitle(this.info.title);
}
// respond to custom update
var i, l;
var customUpdateNode = _F_DOM.selectSingleNode(fragNode, "./customUpdate");
if (customUpdateNode)
{
var customParams = _F_DOM.selectNodes(customUpdateNode, "./param");
if(customParams && customParams.length > 0){
this.customProperties = {};
l = customParams.length;
for (i = 0; i < l; i++)
{
var paramName = _F_DOM.getAttribute(customParams[i], "name");
this.customProperties[paramName] = _F_DOM.text(customParams[i]);
}
}else{
this.customProperties = {};
this.custom = _F_DOM.text(customUpdateNode);
}
}
// respond to state update
var stateNode = _F_DOM.selectSingleNode(fragNode, "./state");
if (stateNode)
{
this.state = _F_DOM.text(stateNode);
}
// raise events
var eventNodes = _F_DOM.selectNodes(fragNode, "./event");
if (eventNodes)
{
l = eventNodes.length;
for (i = 0; i < l; i++)
{
var eventName = _F_DOM.getAttribute(eventNodes[i], "name");
var eventType = _F_DOM.getAttribute(eventNodes[i], "type");
var eventPayload = _F_DOM.selectSingleNode(eventNodes[i], "./payload");
var payload = null;
if (eventType.indexOf('params') > -1 && _F_DOM.selectSingleNode(eventPayload, "./params"))
{
var params = _F_DOM.selectNodes(eventPayload, "./params/param");
payload = {};
var j, m = params.length;
for (j = 0; j < m; j++)
{
var name = _F_DOM.getAttribute(params[j], "name");
var value = _F_DOM.text(params[j]);
payload[name] = value;
}
}
else
{
var payloadRoot = _F_DOM.selectSingleNode(eventPayload, "./*");
if (payloadRoot) {
payload = payloadRoot;
}
else {
payload = _F_DOM.text(eventPayload);
}
}
var evt = new _F_Event.Event();
evt.initEvent(eventName, eventType, payload, true, true);
evt.source = this;
this.dispatchEvent(evt);
}
}
var errorNode = _F_DOM.selectSingleNode(fragNode, "./error");
if (errorNode)
{
var code = _F_DOM.text(_F_DOM.selectSingleNode(errorNode, "code"));
var msg = _F_DOM.text(_F_DOM.selectSingleNode(errorNode, "message"));
var details = _F_DOM.text(_F_DOM.selectSingleNode(errorNode, "details"));
this.processError(code, msg, details);
}
// respond to transient updates
var transientUpdateNodes = _F_DOM.selectNodes(fragNode, "./transientUpdate");
if (transientUpdateNodes && transientUpdateNodes.length > 0)
{
var list = [];
l = transientUpdateNodes.length;
for (i = 0; i < l; i++)
{
var transUpdate = {};
transUpdate.name = _F_DOM.getAttribute(transientUpdateNodes[i], "name");
transUpdate.scope = _F_DOM.getAttribute(transientUpdateNodes[i], "scope");
transUpdate.channel = _F_DOM.getAttribute(transientUpdateNodes[i], "channel");
transUpdate.value = _F_DOM.text(transientUpdateNodes[i]);
list[i] = transUpdate;
}
this.transientUpdateList(list, true);
}
// process subfragments
var subfragmentNodes = _F_DOM.selectNodes(fragNode, "./subfragment/fragment");
if (subfragmentNodes && subfragmentNodes.length > 0)
{
l = subfragmentNodes.length;
for (i = 0; i < l; i++)
{
var fragID = _F_DOM.text(_F_DOM.selectSingleNode(subfragmentNodes[i], "./id"));
var subfrag = fragments[fragID];
if (subfrag !== undefined) {
subfrag.processFragmentXML(subfragmentNodes[i]);
}
else {
_F_log("E", "expecting fragment object for fragment id: " + fragID);
}
}
}
this.raiseEvent("fragment.retrieve.after", true, "xsd:boolean", true, false);
// don't stop the queue processing
return false;
},
loadFragmentResources: function(list, func)
{
if (window._F_Debug !== undefined && this.debugEnabled())
{
_F_Debug.log.logText("Begin _F_loadFragmentResources for id: " + this.id );
}
var args = Array.prototype.slice.call(arguments, 2);
if (list.length == 0)
{
// nothing to load, execute right away
if (typeof func == "function")
{
func.apply(this, args);
}
}
else
{
// load external files
var i, l;
for (i = 0, l = list.length; i < l; i++)
{
_F_runQueue.add(_F_Resource, _F_Resource.loadResource, list[i]);
}
if (typeof func == "function")
{
_F_runQueue.add(this, func, args);
}
// execute first in queue
_F_runQueue.run();
}
if (window._F_Debug !== undefined && this.debugEnabled())
{
_F_Debug.log.logText("End _F_loadFragmentResources for id: " + this.id);
}
},
lockUpdates: function(locked)
{
//-- Bug Fix: Firefox bug that destroys the PDF document when we hide the iframe.
// This is a firefox specific fix, referenced in firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=180802
var embedFrames = [];
function isEmbedFrame(iframe)
{
var doc = null;
try
{
doc = iframe.contentDocument.firstChild;
}
catch (e)
{
doc = null;
}
return (doc
&& doc.tagName == "HTML"
&& doc.firstChild.tagName == "BODY"
&& doc.firstChild.firstChild.tagName == "EMBED"
&& doc.firstChild.firstChild.type.indexOf("pdf") > -1);
}
function addEmbedFrame(iframe)
{
if (_F_Array.indexOf(embedFrames, iframe, 0, true) < 0) {
embedFrames.push(iframe);
}
}
function searchEmbedFrames(frag)
{
// detect firefox browser, return if not
if (_F_config.browser != "firefox") {
return false;
}
// search fragment markup for iframes
var div = $(frag.div);
if (div)
{
var iframes = div.getElementsByTagName("iframe");
// for each iframe check for embedded pdf
if (iframes)
{
var i, l = iframes.length;
for (i = 0; i < l; i++)
{
if (isEmbedFrame(iframes[i])) {
addEmbedFrame(iframes[i]);
}
}
}
}
}
function reloadEmbedFrames()
{
var i, l = embedFrames.length;
for (i = 0; i < l; i++)
{
embedFrames[i].setAttribute("src", embedFrames[i].getAttribute("src"));
}
}
//-- /Bug Fix
var list = _F_descendants(this.id);
var i, l = list.length;
if (locked)
{
for (i = 0; i < l; i++) {
list[i].internal.locked++;
}
}
else
{
var skipChildren = "";
for (i = 0; i < l; i++)
{
var frag = list[i];
if (0 <= (--frag.internal.locked))
{
frag.internal.locked = 0; // safety net
if (frag.internal.dirty)
{
if (skipChildren != "" && (0 == frag.id.indexOf(skipChildren)))
{
// the parent fragment's retrieve is already called,
// don't retrieve this child.
frag.internal.dirty = false;
continue;
}
else {
skipChildren = frag.id;
}
frag.retrieve();
}
else {
searchEmbedFrames(frag);
}
}
}
reloadEmbedFrames();
}
},
/**
* Callback function used to process logon fault.
*/
processingLogon: null,
processErrorHref: function() {
return window.location.href;
},
processError: function(code, message, details)
{
if (code == "invalidCredentials")
{
if (window.handleLogon != null)
{
if (this.processingLogon == null)
{
xAddEventListener(window, "beforeunload", _F_config.emptyFunction); // hack: so onload event will be fired on cancel or back action
var dashboard_login = _F_Document.getCookie("frag_login");
if (dashboard_login == "true") {
//Simply display the error
this.onerror(message, details, code);
return;
}
_F_Document.setCookie("frag_login", "true", 60);
var _self = this;
var href = this.processErrorHref();
var rmidx = href.indexOf("#");
if (rmidx != -1) {
href = href.substring(0, rmidx);
}
window.location.replace(href + "#frag-logon"); //to mark that we're in a logon process
this.processingLogon = window.setTimeout(
function()
{
handleLogon(href, _self);
_self.processingLogon = null;
},
10);
}
return;
}
}
this.onerror(message, details, code);
},
/**
* Calls the client validator library for one specific parameter.
* @param param
* @param value
* @return See validator.js for the meaning of the error codes
* 0 = success
* less than 0 = execution error of the validator's generated code
* greater then 0 = validation error code.
*/
validate: function(param, value)
{
if (this.validator != null &&
this.validator.client != null &&
typeof this.validator.client.verify == "function")
{
return this.validator.client.verify(param, value);
}
return 0;
},
//- events
EVENT_NAME: 0,
EVENT_FUNC: 1,
EVENT_USECAP: 2,
/**
* Returns an array of indexes for matching event listeners, null if no match.
* @param name: the event's name
*/
findEventListeners: function(name)
{
// note: avoid creating unnecessary array objects
var result = null;
var i, l = this.eventListeners.length;
for (i = 0; i < l; i++)
{
var sMatch = this.eventListeners[i][this.EVENT_NAME];
if (sMatch == "*")
{
if (result == null) {
result = [];
}
result.push(this.eventListeners[i]);
continue;
}
if (sMatch.indexOf(".*") == sMatch.length - 2)
{
if (name.indexOf(sMatch.substring(0, sMatch.length - 1)) == 0)
{
if (result == null) {
result = [];
}
result.push(this.eventListeners[i]);
}
}
else
if (name == sMatch)
{
if (result == null) {
result = [];
}
result.push(this.eventListeners[i]);
}
}
return result;
},
addEventListener: function(name, listener, useCapture)
{
useCapture = useCapture === undefined ? false : useCapture;
// make sure listener not already in list
var i, l = this.eventListeners.length;
for (i = 0; i < l; i++) {
if (this.eventListeners[i][this.EVENT_NAME] == name &&
this.eventListeners[i][this.EVENT_FUNC] == listener &&
this.eventListeners[i][this.EVENT_USECAP] == useCapture) {
return;
}
}
this.eventListeners.push([name, listener, useCapture]);
if (window._F_Debug !== undefined && this.debugEnabled())
{
_F_Debug.log.logDetails("Added event listener for fragment: " + this.id + "\ttitle: " + _F_Strings.normalize(this.title) + "\tevent: " + name, this);
}
},
removeEventListener: function(name, listener, useCapture)
{
useCapture = useCapture === undefined ? false : useCapture;
// find listener
var i, l = this.eventListeners.length;
for (i = 0; i < l; i++)
{
if (this.eventListeners[i][this.EVENT_NAME] == name &&
this.eventListeners[i][this.EVENT_FUNC] == listener &&
this.eventListeners[i][this.EVENT_USECAP] == useCapture)
{
_F_Array.removeAt(this.eventListeners, i);
if (window._F_Debug !== undefined && this.debugEnabled())
{
_F_Debug.log.logDetails("Removed event listener for fragment: " + this.id + "\ttitle: " + _F_Strings.normalize(this.title) + "\tevent: " + name, this);
}
break;
}
}
},
dispatchEvent: function(evt)
{
if (window._F_Debug !== undefined && evt.debugEnabled())
{
_F_Debug.log.logText("dispatchEvent: " + evt.name + " - id: " + this.id);
}
// prepare event object
evt.target = this;
evt.cancelled = false;
evt.stopped = false;
// prepare list of ancestor event handlers
var scope = this.getAncestors();
var indexes = new Array(scope.length);
var hasListener = false;
var i, l = scope.length;
for (i = 0; i < l; i++)
{
indexes[i] = scope[i].findEventListeners(evt.name);
if (indexes[i]) {
hasListener = true;
}
}
// capture phase
if (hasListener)
{
evt.eventPhase = evt.CAPTURING_PHASE;
l = scope.length;
for (i = l - 1; i >= 0; i--)
{
if (indexes[i])
{
var j, m = indexes[i].length;
for (j = 0; j < m; j++)
{
var listener = indexes[i][j];
// useCapture true?
if (listener[this.EVENT_USECAP])
{
evt.currentTarget = scope[i];
_F_Event.execute(scope[i], listener, evt);
}
}
if (evt.stopped) {
return !evt.cancelled;
}
}
}
}
// list of target event listeners
var targetListeners = this.findEventListeners(evt.name);
// at target phase
if (targetListeners)
{
evt.eventPhase = evt.AT_TARGET;
evt.currentTarget = this;
l = targetListeners.length;
for (i = 0; i < l; i++)
{
var listener1 = targetListeners[i];
_F_Event.execute(this, listener1, evt);
}
if (evt.stopped) {
return !evt.cancelled;
}
}
// bubbling phase
if (evt.bubbles && hasListener)
{
evt.eventPhase = evt.BUBBLING_PHASE;
l = scope.length;
for (i = 0; i < l; i++)
{
if (indexes[i])
{
var k, n = indexes[i].length;
for (k = 0; k < n; k++)
{
var listener2 = indexes[i][k];
// useCapture false?
if (!listener2[this.EVENT_USECAP])
{
evt.currentTarget = scope[i];
_F_Event.execute(scope[i], listener2, evt);
}
}
if (evt.stopped) {
return !evt.cancelled;
}
}
}
}
// default behaviour for fragment events
if (!evt.cancelled)
{
if ("fragment.refresh" == evt.name)
{
this.retrieve("frag-event=" + _F_Strings.urlEncode("name=" + evt.name));
}
}
return !evt.cancelled;
},
raiseEvent: function(name, payload, type, bubbles, cancelable)
{
// If not initialized, we queue the event
if (!this.onloadInitialized ){
_F_eventQueue.add(this, this.raiseEvent, arguments);
// we return trues so we don't cancel the event. Canceling it will affect the source fragment (e.g. canceling a retrieve event)
return true;
}
bubbles = bubbles === undefined ? true : bubbles;
cancelable = cancelable === undefined ? true : cancelable;
var evt = new _F_Event.Event();
evt.initEvent(name, type, payload, bubbles, cancelable);
evt.source = this;
return this.dispatchEvent(evt);
},
/**
* Proxy an event to every children
*/
proxyEvent: function(evt)
{
if (window._F_Debug !== undefined && evt.debugEnabled())
{
var phase = "";
switch (evt.eventPhase) { case 1: phase = "CAPTURE"; break; case 2: phase = "TARGET"; break; case 3: phase = "BUBBLE"; }
var source = evt.source ? evt.source.id : "none";
_F_Debug.log.group("eventProxy: " + evt.name + " (" + phase + ") - id: " + this.id + " src: " + source);
}
// pass-down specific events if raised on proxy fragment
var children;
if (evt.eventPhase == evt.AT_TARGET)
{
var bPropagate = false;
if (evt.name.indexOf("fragment.") == 0)
{
bPropagate = _F_Array.indexOf(_F_Event.propagatedEvents, evt.name) > -1;
}
else
{
// make sure event doesn't come from child
bPropagate = !(evt.proxy && evt.proxy == this);
}
if (bPropagate)
{
children = this.getChildren();
var i, l = children.length;
for (i = 0; i < l; i++) {
children[i].dispatchEvent(evt);
}
}
}
else
{
if (evt.name.indexOf("fragment.") != 0)
{
// fire event on self if event source is immediate child or from a child event proxy
children = this.getChildren();
if (_F_Array.indexOf(children, evt.source) > -1 || _F_Array.indexOf(children, evt.proxy) > -1)
{
evt.stopPropagation();
var oEvent = new _F_Event.Event();
oEvent.initEvent(evt.name, evt.type, evt.payload, evt.bubbles, evt.cancelable);
oEvent.source = evt.source;
oEvent.proxy = this;
this.dispatchEvent(oEvent);
}
}
}
// prevent the default behaviour for fragment.refresh events targetted at an event proxy
if (evt.eventPhase == evt.AT_TARGET && "fragment.refresh" == evt.name) {
evt.preventDefault();
}
if (window._F_Debug !== undefined && evt.debugEnabled()) {
_F_Debug.log.groupEnd();
}
},
//- onload
onloadInitialized: false,
onloadHandlers: [],
// old code for backwards compatibility (to be removed)
setOnloadHandler: function(func)
{
if (this.onloadInitialized) {
func();
}
else {
this.onloadHandlers.push(func);
}
},
//- transient properties
transientGlobal: { },
transientUpdate: function(sName, sValue, sScope, sChannel)
{
var scope;
sChannel = ((sChannel == null || sChannel === undefined) ? this.channel||"" : sChannel);
var sKey = sName + "[" + sChannel + "]";
if (sScope == 'private')
{
// private communication
scope = [this];
}
else if (sScope == 'page')
{
// set value in page transients
var p = this.getPageFragment();
p.transientState[sKey] = sValue;
scope = _F_descendants(p.id);
}
else if (!(sScope) || sScope == "" || sScope == "application")
{
// set value in global transients
scope = [];
this.transientGlobal[sKey] = sValue;
for (var id in fragments)
{
if (fragments[id] != null)
{
scope.push(fragments[id]);
}
}
}
else
{
// unsupported scope, do nothing
scope = [];
}
var i, l;
var refreshList = (arguments.length > 4) ? arguments[4] : null;
if (refreshList)
{
l = scope.length;
for (i = 0; i < l; i++)
{
try
{
if (scope[i].transientUpdateCheck(sName, sValue, sChannel, false)) {
refreshList.push(scope[i]);
}
}
catch (e)
{
_F_log("E", e);
}
}
}
else
{
l = scope.length;
for (i = 0; i < l; i++)
{
try
{
scope[i].transientUpdateCheck(sName, sValue, sChannel, true);
}
catch (e1)
{
_F_log("E", e1);
}
}
}
},
transientUpdateList: function(list)
{
if (list == null || list.length == 0) {
return;
}
var serverUpdate = (arguments.length > 1) ? arguments[1] : false;
var refreshList = [];
var i, l = list.length;
for (i = 0; i < l; i++) {
this.transientUpdate(list[i].name, list[i].value, list[i].scope, list[i].channel, refreshList);
}
refreshList = _F_Array.unique(refreshList);
if (serverUpdate) {
_F_Array.remove(refreshList, this);
}
l = refreshList.length;
for (i = 0; i < l; i++){
var frag = refreshList[i];
if (frag.raiseEvent("fragment.transientUpdate", list, "")){
frag.retrieve();
}
}
},
/**
* transientUpdateCheck - checks if this fragment should be refreshed because
* the value was changed for the specified channel.
* @param sName transient name
* @param sValue new value
* @param sChannel which channel name (string or undefined/null/'' are considered global)
* @param bRefreshNow allow the call to retrieve
*/
transientUpdateCheck: function(sName, sValue, sChannel, bRefreshNow)
{
if (this.transients)
{
var i, l = this.transients.length;
for (i = 0; i < l; i++) {
if (this.transients[i] == sName)
{
if ((this.transientState[sName] != sValue) && ((this.channel||'') == (sChannel||'')))
{
var refresh = this.transientNotify(sName, sValue);
if (refresh && bRefreshNow){
if (this.raiseEvent("fragment.transientUpdate", [{name: sName, value:sValue, channel:sChannel}], "")){
this.retrieve();
}
}
return refresh;
}
return false;
}
}
}
return false;
},
/**
* transientNotify: assign the new value and returns true to do the
* automatic refresh(), otherwise return false.
* @param sName transient name
* @param sValue new value to be set
*/
transientNotify: function(sName, sValue)
{
this.transientState[sName] = sValue;
if (window._F_Debug !== undefined && this.debugEnabled())
{
_F_Debug.log.logDetails("Transient Notify fragment: " + this.id + "\ttitle: " + _F_Strings.normalize(this.title),
"name = " + sName + " value = " + sValue);
}
return true;
},
getPageFragment: function()
{
var p = this;
while (p != null)
{
if (p.page) {
return p;
}
p = p.parent;
}
return (this.parent != null) ? this.parent : this;
},
/**
* Method sets the title of the fragment, the title will be added to the caption of the
* fragment if the fragment has a caption.
* When the method is called the fragment.title.change event is fired.
* The event will have an object payload, containing the currentTitle and the newTitle.
* If no one in the fragment chain handles the event and calls preventDefault,
* the default behavior of fragment.retrieve() will occur.
* @param text: title's text
*/
setTitle: function(text)
{
if (this.raiseEvent("fragment.title.change",
{
"currentTitle":this.title,
"newTitle":text
},
"params"))
{
this.title = text;
}
},
/**
* Method sets the mode of the fragment, modes can be any mode defined
* in the fragment implementation file.
* When the method is called the fragment.mode.change event is fired.
* This event has an object payload, containing the currentMode and the newMode.
* If no one in the fragment chain handles the event and calls preventDefault,
* the default behavior of fragment.retrieve() will occur.
* @param mode: new fragment mode
*/
setMode: function(mode)
{
if (mode != "" && mode != this.mode)
{
var currentMode = this.mode;
this.mode = mode;
var performDefault = this.raiseEvent("fragment.mode.change",
{
"currentMode":currentMode,
"newMode":this.mode
}
, "params");
if (performDefault && (arguments[1] === undefined || arguments[1] != "internal")) {
this.retrieve();
}
}
},
/**
* Method sets the windowState of the fragment, windowState can be normal, maximized or minimized.
* When the method is called the fragment.windowstate.change event is fired.
* This event has an object payload, containing the currentWindowState and the newWindowState.
* If no one in the fragment chain handles the event and calls preventDefault,
* the default behavior of fragment.retrieve() will occur.
* @param windowState: new fragment window state
*/
setWindowState: function(windowState)
{
if (windowState != "" && windowState != this.windowState)
{
//Raising windowstate changed event
var performDefault = this.raiseEvent("fragment.windowstate.change",
{
"currentWindowState":this.windowState,
"newWindowState":windowState
}
, "params");
this.windowState = windowState;
//Raise a visiblility change event with siblings
var siblings = this.parent.getChildren();
var visibility = windowState=="maximized" ? "hidden" : "visible";
for (var i=0; i -1) && ((arguments[1] === undefined)||(arguments[1] != "internal"))) {
this.retrieve();
}
}
},
/**
* Default event handler for the fragment.visibility.change event. This event handler should be called first as it will
* calculate and set old/new visibility for the fragment and update both the fragment and event with this data for the
* use of subsequent window.visibility.change event handlers.
* @param evt: window.visibility.change event object
*/
setVisibilityEvent: function(evt)
{
if (evt.eventPhase == evt.AT_TARGET)
{
evt.payload.currentVisibility = this.visibility;
var newVisibility;
if (evt.payload.setVisibility == "hidden")
{
newVisibility = "hidden";
}
else
{
if (this.windowState == "minimized")
{
newVisibility = "hidden";
}
else
{
newVisibility = "visible";
}
}
evt.payload.newVisibility = newVisibility;
this.visibility = newVisibility;
}
},
/**
* Instruct this fragment to refresh itself in a number of seconds.
* Calling this method with a value of 0 will cancel the current pending refresh, however
* there's no garantee that the refresh would be effectively cancelled.
* @param sec: number of seconds
*/
setRefreshDelay: function(sec)
{
if (this.refreshTimeout) {
window.clearInterval(this.refreshTimeout);
}
if (sec > 0)
{
var _self = this;
this.refreshTimeout = window.setTimeout(
function()
{
_self.retrieve();
},
sec * 1000);
}
},
//- error handling
onerror: function(msg, details, code)
{
_F_alert(code + ":\n" + msg + "\n\n" + details, this.title);
},
/**
* Destroys a fragment and all its children.
*/
destroy: function()
{
// call event handlers and delete this object
this.raiseEvent("fragment.unload", null, "", true, false);
// recursively call destroy on children
var children = this.getChildren();
var i, l = children.length;
for (i = 0; i < l; i++) {
children[i].destroy();
}
// remove private scripts and styles
_F_Document.removeHeadTag(_F_Document.buildHeadTagId(this.id, "SCRIPT"));
_F_Document.removeHeadTag(_F_Document.buildHeadTagId(this.id, "LINK"));
if ($(this.div)) {
$(this.div).innerHTML = "";
}
this.raiseEvent("fragment.destroy", null, "", true, false);
delete fragments[this.id];
},
reloadAll: function ()
{
var action = _F_Config.gateway + _F_Config.application;
var formElement = document.createElement("form");
formElement.setAttribute("name","pageload");
formElement.setAttribute("method","POST");
formElement.setAttribute("action",_F_Config.gateway);
hiddenElement = document.createElement("input");
hiddenElement.setAttribute("type","hidden");
hiddenElement.setAttribute("name","b_action");
hiddenElement.setAttribute("value",_F_Config.application.substring(1));
formElement.appendChild(hiddenElement);
for (var id in fragments)
{
var frag = fragments[id];
if (frag.parent == null)
{
var path = frag.path;
if (frag.id == "cm")
{
hiddenElement = document.createElement("input");
hiddenElement.setAttribute("type","hidden");
hiddenElement.setAttribute("name","pathinfo");
hiddenElement.setAttribute("value","/cm");
formElement.appendChild(hiddenElement);
hiddenElement = document.createElement("input");
hiddenElement.setAttribute("type","hidden");
hiddenElement.setAttribute("name","path");
hiddenElement.setAttribute("value","storeID(\"" + frag.path.substring(frag.path.lastIndexOf("/")+1) + "\")");
formElement.appendChild(hiddenElement);
}
else
{
hiddenElement = document.createElement("input");
hiddenElement.setAttribute("type","hidden");
hiddenElement.setAttribute("name","pathinfo");
hiddenElement.setAttribute("value",frag.path);
formElement.appendChild(hiddenElement);
}
}
//Raise an event before capturing the state of the fragment so that any needed updates can be done
frag.raiseEvent("fragment.reload", null, "", false, false);
hiddenElement = document.createElement("input");
hiddenElement.setAttribute("type","hidden");
hiddenElement.setAttribute("name","frag-sub");
hiddenElement.setAttribute("value",frag.fragmentURI());
formElement.appendChild(hiddenElement);
}
//Assume a header is present
hiddenElement = document.createElement("input");
hiddenElement.setAttribute("type","hidden");
hiddenElement.setAttribute("name","frag-header");
hiddenElement.setAttribute("value","true");
formElement.appendChild(hiddenElement);
document.body.appendChild(formElement);
formElement.submit();
document.body.removeChild(formElement);
formElement = null;
}
};
//--------------------------------------------------------------
// Drag and Drop
// find the nearest element up the chain that begins with "labelPrefix" in its id
function _F_findParentObj(obj, labelPrefix)
{
while (obj)
{
if (obj.id && obj.id.indexOf(labelPrefix) == 0) {
return obj;
}
obj = xParent(obj, true);
}
return obj;
}
// find the nearest element up the chain that begins with "label" in its id
function _F_ancestorFragments(obj)
{
var list = [];
while (obj)
{
var id = obj.id;
if (id && id.indexOf('content') == id.length - 7) {
list.push(obj);
}
obj = xParent(obj, true);
}
return list;
}
//-- dragContext Object
function dragContext(obj)
{
this.obj = obj;
if (this.obj.getAttributeNode("payload")) {
this.payload = this.obj.getAttributeNode("payload").nodeValue;
}
if (this.obj.getAttributeNode("itemtitle")) {
this.title = this.obj.getAttributeNode("itemtitle").nodeValue;
}
if (this.obj.getAttributeNode("dragtype"))
{
this.type = this.obj.getAttributeNode("dragtype").nodeValue;
}
else
{
// extract object class and any extra info
var s = obj.id.substring(9);
s = s.substring(0, s.indexOf("_"));
var n = s.indexOf(".");
if (n != -1)
{
this.type = s.substring(0, n);
this.info = s.substring(n+1);
}
else {
this.type = s;
}
}
// drop target handling
this.xevent = null;
this.dropType = 0;
this.dropTarget = null;
this.dropHandler = null;
// drag icon display states
this.imgPath = _F_Config.webContent + "/fragments/dragdrop/images/";
this.bDragMulti = false; // _multi
this.bDragDrop = false; // _nodrop
this.bDragCopy = false; // _copy
this.init();
}
dragContext.prototype =
{
div: null,
img: null,
icons: [],
iconNames:
[
"drag_cursor",
"drag_cursor_copy",
"drag_cursor_nodrop",
"drag_cursor_multi",
"drag_cursor_multi_copy",
"drag_cursor_multi_nodrop",
"drag_cursor_multi_nodrop_copy"
],
init: function()
{
if (!this.div)
{
this.div = document.createElement('DIV');
this.div.setAttribute("id", "F_dragDiv");
this.div.style.position = "absolute";
this.div.style.visibility = "hidden";
this.div.style.zIndex = "100";
this.img = document.createElement('IMG');
this.img.setAttribute("name", "F_dragImage");
this.img.setAttribute("src", this.imgPath + "drag_cursor.gif");
this.img.setAttribute("width", "22");
this.img.setAttribute("height", "22");
this.img.setAttribute("border", "0");
this.div.appendChild(this.img);
document.body.appendChild(this.div);
// load images
var i, l = this.iconNames.length;
for (i = 0; i < l; i++)
{
var icon = new Image(22, 22);
icon.src = this.imgPath + this.iconNames[i] + ".gif";
this.icons[this.iconNames[i]] = icon;
}
}
},
updateIcon: function()
{
var sName = "drag_cursor" +
(this.bDragMulti ? "_multi" : "") +
(this.bDragDrop ? "" : "_nodrop") +
(this.bDragCopy ? "_copy" : "");
if (this.icons[sName]) {
this.img.src = this.icons[sName].src;
}
},
canDrop: function(bDrop)
{
if (this.bDragDrop != bDrop)
{
this.bDragDrop = bDrop;
this.updateIcon();
}
},
capture: function(e)
{
this.xevent = e;
xMoveTo(this.div, e.pageX + 5, e.pageY + 8);
xShow(this.div);
this.updateIcon();
},
ENTER: 0,
MOVE: 1,
LEAVE: 2,
DROP: 3,
move: function(e)
{
this.xevent = e;
xMoveTo(this.div, e.pageX + 5, e.pageY + 8);
var droplist = _F_ancestorFragments(e.target);
var drop = null;
var frag = null;
var i, l = droplist.length;
for (i = 0; i < l; i++)
{
var id = droplist[i].id.substring(0, droplist[i].id.length - 7);
frag = fragments[id];
if (frag && frag.ondrop)
{
drop = droplist[i];
break;
}
}
if (drop != this.dropTarget)
{
if (this.dropTarget)
{
this.dropType = this.LEAVE;
this.dropHandler(this);
this.dropTarget = null;
this.dropHandler = null;
this.canDrop(false);
}
}
if (drop)
{
this.dropTarget = drop;
this.dropHandler = frag.ondrop;
this.dropType = this.ENTER;
this.dropHandler(this);
}
if (this.dropTarget)
{
this.dropType = this.MOVE;
this.dropHandler(this);
}
},
release: function(e)
{
this.xevent = e;
xHide(this.div);
if (this.dropTarget)
{
this.dropType = this.bDragDrop ? this.DROP : this.LEAVE;
this.dropHandler(this);
this.dropTarget = null;
this.dropHandler = null;
}
}
};
//-- _F_Drag Singleton
var _F_Drag =
{
obj: null,
startX: 0,
startY: 0,
dragging: false,
context: null,
pending: function(obj, e)
{
this.obj = obj;
this.startX = e.pageX;
this.startY = e.pageY;
this.dragging = false;
this.context = null;
},
start: function(e)
{
this.dragging = true;
this.context = new dragContext(this.obj);
this.context.capture(e);
},
move: function(e)
{
if (!this.dragging)
{
// check for drag outside the start rect
if ((e.pageX > (this.startX + 8)) || (e.pageX < (this.startX - 8)) ||
(e.pageY > (this.startY + 8)) || (e.pageY < (this.startY - 8)))
{
this.start(e);
}
}
if (this.context) {
this.context.move(e);
}
},
stop: function(e)
{
if (this.context) {
this.context.release(e);
}
this.obj = null;
this.dragging = false;
this.context = null;
}
};
//-- Mouse Event handling
function _F_dragMD(evt)
{
// capture events
var e = new xEvent(evt);
var obj = _F_findParentObj(e.target, 'dragitem_');
if (obj)
{
xPreventDefault(evt);
_F_Drag.pending(obj, e);
xAddEventListener(document, "mousemove", _F_dragMM, false);
xAddEventListener(document, "mouseup", _F_dragMU, false);
}
}
function _F_dragMM(evt)
{
var e = new xEvent(evt);
xPreventDefault(evt);
_F_Drag.move(e);
}
function _F_dragMU(evt)
{
var e = new xEvent(evt);
xPreventDefault(evt);
_F_Drag.stop(e);
xRemoveEventListener(document, "mousemove", _F_dragMM);
xRemoveEventListener(document, "mouseup", _F_dragMU);
}
//------------------------------------------------------------------------------
// execute a method on an object with arguments
var _F_Queue =
{
};
_F_Queue.Runnable = function(obj, func, args)
{
this.obj = obj;
this.func = func;
this.args = args;
};
_F_Queue.Runnable.prototype =
{
run: function()
{
var stopRun = this.func.apply(this.obj, this.args);
this.func = null;
this.obj = null;
this.args = null;
return stopRun;
}
};
_F_Queue.Queue = function()
{
this.head = null;
this.tail = null;
};
_F_Queue.Queue.prototype =
{
add: function(obj)
{
var newEntry =
{
value: obj,
next: null
};
if (this.tail) {
this.tail.next = newEntry;
}
else {
this.head = newEntry;
}
this.tail = newEntry;
},
hasNext: function()
{
return (this.head != null);
},
next: function()
{
var entry = this.head;
var obj = entry.value;
this.head = entry.next;
if (entry.next == null) {
this.tail = null;
}
entry.next = null;
delete (entry);
return obj;
}
};
_F_Queue.RunQueue = function()
{
this.queue = new _F_Queue.Queue();
this.isRunning = false;
};
_F_Queue.RunQueue.prototype =
{
add: function(obj, func, args)
{
this.queue.add(new _F_Queue.Runnable(obj, func, args));
},
run: function()
{
if (!this.isRunning){
this.isRunning = true;
this.resume();
}
},
resume: function()
{
while (this.queue.hasNext()) {
if (this.queue.next().run()) {
break;
}
}
this.isRunning = this.queue.hasNext();
}
};
var _F_runQueue = new _F_Queue.RunQueue();
var _F_eventQueue = new _F_Queue.RunQueue();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Framework
function _F_attach(obj)
{
var frag = fragments[obj.id];
if (!frag) {
frag = new fragment(obj.path, obj.id, obj.div);
}
if (!frag.loaded)
{
frag.attach(obj);
if (frag.title) {
frag.setTitle(frag.title);
}
frag.loaded = true;
if (window._F_Debug !== undefined && frag.debugEnabled())
{
_F_Debug.log.logDetails("Attach fragment: " + frag.id + "\ttitle: " + _F_Strings.normalize(frag.title),
"path: " + obj.path, frag);
}
frag.raiseEvent("fragment.create", null, "", true, false);
}
else
{
frag.channel = obj.channel;
}
return frag;
}
function _F_resize()
{
var skipChildren = null;
var list = (arguments.length == 1) ? arguments[0] : fragments;
for (var id in list)
{
if (skipChildren != null && id.indexOf(skipChildren) == 0) {
continue;
}
if (fragments[id] != null && fragments[id].onresize && fragments[id].onresize() == true) {
skipChildren = id;
}
else {
skipChildren = null;
}
}
}
function _F_onload(){
if (window.location.href.indexOf("#frag-logon") != -1) {
document.cookie = "frag_login=";
}
fragment.prototype.onloadInitialized = true;
// old code for backwards compatibility (to be removed)
var i, l = fragment.prototype.onloadHandlers.length;
for (i = 0; i < l; i++) {
fragment.prototype.onloadHandlers[i]();
}
// fire "fragment.load" event on all fragments
var oEvent = new _F_Event.Event();
var isbrowserBack = false;
var backJaxForm = $('cps_backjaxform');
if (typeof backJaxForm != "undefined" && backJaxForm != null)
{
if (typeof backJaxForm.visited != "undefined")
{
isbrowserBack = ("true" == backJaxForm.visited.value);
backJaxForm.visited.value = "true";
}
}
oEvent.initEvent("fragment.load", "", {source: isbrowserBack? "cache" : "dom"}, false, false);
for (var id in fragments)
{
if (fragments[id].parent == null)
{
oEvent.source = fragments[id];
fragments[id].dispatchEvent(oEvent);
}
}
_F_eventQueue.run();
while(_F_eventQueue.queue.hasNext()) {
_F_eventQueue.resume();
}
}
function _F_onresize()
{
_F_resize();
return true;
}
function _F_init()
{
_F_Config.initialize();
_F_Resource.initialize();
_F_onload();
_F_Document.addEventListener(window, "resize", _F_onresize, true);
_F_Document.addEventListener(document, "mousedown", _F_dragMD);
if (window._F_Debug !== undefined && _F_Debug.enabled)
{
_F_Debug.initialize();
}
}
function _F_getFragmentByID(fid)
{
return window.fragments[fid];
}
_F_Document.addEventListener(window, "load", _F_init);
/**
* @deprecated: use _F_Document.getCookie()
*/
function _F_getCookie(name)
{
_F_log("W", "DEPRECATED FUNCTION: _F_getCookie --> _F_Document.getCookie");
return _F_Document.getCookie(name);
}
/**
* @deprecated: use _F_Document.setCookie()
*/
function _F_setCookie(name, value, expires, path, domain, secure)
{
_F_log("W", "DEPRECATED FUNCTION: _F_setCookie --> _F_Document.setCookie");
_F_Document.setCookie(name, value, expires, path, domain, secure);
}