This is a utility class and provides various utility functions to dynamically load and remove JavaScript and CSS files.
/**
* @class Jx.JxUtilities
* Class containing Utility functions
*/
Jx.JxUtilities = function () {
return {
debug: false,
heartbeatId: null,
// select debug or regular JSON encoder. (debug has pretty printing)
encode: function () {
var encode = this.debug ? Jx.JxJSON.encode : Ext.util.JSON.encode;
return encode.apply(this, arguments);
},
/**
* View related configuration property retrieval. The config needs to contain
* xtype in order for use to figure out whats the default config value is.
* Once config has been realized(instantiated into object), then no need to use this function.
*
* Return may be null or undefined.
*
* @param config
* @param propName
*/
getXTypePropValue: function (config, propName) {
if (!config) {
JxDebugConsole.log('JxUtilities.getPropValue: config not defined.');
return undefined;
}
var propValue = config[propName];
if (propValue) return propValue;
if (!config.xtype) {
JxDebugConsole.log('JxUtilities.getPropValue: config.xtype not defined.');
return undefined;
}
var currentClass = Ext.ComponentMgr.types[config.xtype];
while (currentClass) {
var defaultConfig;
if (Ext.isFunction(currentClass)) {
defaultConfig = currentClass.prototype;
} else {
defaultConfig = currentClass;
}
propValue = defaultConfig[propName];
if (propValue) {
break;
}
currentClass = currentClass.superclass;
}
return propValue;
},
/**
* View related configuration processing. Clean up
* @param config
* @return any processing or not
*/
processJxItems: function (config) {
if (config == undefined) {
return false;
}
if (config.jxitems == undefined) {
return false; //
}
if (config.jxitems && config.items) {
// something wrong. should be one or the other
JxDebugConsole.log('Jx.JxUtilities.processJxItems() Error: both jxitems and items are defined.');
return false;
}
if (config.jxViewRepository == undefined) {
// something wrong. nothing in view repository for current container.
JxDebugConsole.log('Jx.JxUtilities.processJxItems() Error: config.jxViewRepository is undefined.');
return false;
}
var jxViewRepository = config.jxViewRepository;
config.items = [];
for (var indx = 0; indx < config.jxitems.length; indx++) {
var viewName = config.jxitems[indx];
if (Ext.isString(viewName)) {
// assume it is string always
viewName = jxViewRepository[viewName];
} // else assume Object
config.items.push(viewName);
// for child view to use
viewName.jxViewRepository = config.jxViewRepository;
}
delete config.jxitems;
return true;
},
/**
* For example:
* Jx.JxUtilities.findPluginByType(myPanel, Ext.ux.grid.RowExpander) will return
* myPanel's RowExpander plugins.
*
* @param comp
* @param xtype
*/
findPluginByType: function (comp, xtype) {
if (!Ext.isFunction(xtype)) {
JxDebugConsole.log('please input Plugin class instead of string');
return null;
}
if (Ext.isArray(comp.plugins)) {
for (var index = 0; index < comp.plugins.length; index++) {
var p = comp.plugins[index];
if (p.constructor === xtype) return p;
}
}
return null;
},
/**
* processJxActionItems:
* @param config
* Will Process the View Config and wrap action object as a wrapper for the various
* button bars such as bbar, fbar and tbar if custom jxbbar, jxtbar and jxfbar are used.
* Ext defined buttons will not be processed as they will use Ext framework.
*/
processJxActionItems: function (config) {
if (config == undefined) {
return false;
}
//If Ext Config then skip attaching actions
if (config.bbar || config.tbar || config.fbar) {
JxDebugConsole.log('Jx.JxUtilities.processJxActionItems()bbar, tbar or fbar defined, nothing to do.');
return false;
}
//If action is not defined then wrap action object on view config for support within framework
if (config.action == undefined) {
Ext.apply(config, {
action: {}
});
}
var action = config.action;
if (config.jxbbar) {
Ext.apply(action, {
bbar: config.jxbbar
})
}
if (config.jxfbar) {
Ext.apply(action, {
fbar: config.jxfbar
});
}
if (config.jxtbar) {
Ext.apply(action, {
tbar: config.jxtbar
});
}
return true;
},
/**
* Clone Function to make a deep clone of an object or an array
* @param {Object/Array} o Object or array to clone
* @return {Object/Array} Deep copy of an object or an array
**/
clone: function (o) {
if (!o || 'object' !== typeof o) {
return o;
}
if ('function' === typeof o.clone) {
return o.clone();
}
var c = '[object Array]' === Object.prototype.toString.call(o) ? [] : {};
var p, v;
for (p in o) {
if (o.hasOwnProperty(p)) {
v = o[p];
if (v && 'object' === typeof v) {
c[p] = Jx.JxUtilities.clone(v);
} else {
c[p] = v;
}
}
}
return c;
},
/**
* Figure out if the gui component config is that of a JxHostContainer or its derived class.
* Since gui config is not yet a component object, the function isXType() is not available.
*
* @param {Object} config A gui component's configuration
* @return {Boolean} true if the gui component config is a JxHostContainer.
*/
isJxHostContainer: function (config) {
if (config.xtype == 'jxhostcontainer') {
return true;
} else if (config.xtype == 'jxresthostcontainer') {
return true;
}
return false;
},
/**
* Find GUI component's parent container that is type of JxHostContainer
* Ext.Component.findParentByType is a SHALLOW class hierachy comparison.
* So we have to do a separate utility for this.
*
* @param {Object} comp A gui component object.
* @return {Object} parent JxHostContainer.
*/
findParentHostContainer: function (comp) {
var fn = function (parentComp) {
if (parentComp.isXType('jxhostcontainer')) return true;
return false;
};
return comp.findParentBy(fn);
},
removeSquareBracket: function (somestring) {
return somestring.replace(/\[[^()]*\]/, "");
},
getStringFromLastSlash: function (somestring, rowIndex) {
var index = somestring.lastIndexOf('/');
if (index) {
somestring = somestring.substring(index + 1);
}
return somestring + '[' + rowIndex + ']';
// return somestring + '[@rowId=\"' + rowIndex + '\"]';
},
appendRowIndexToUrl: function (decoded_url, decoded_dpath, rowIndex) {
var pre = decoded_url.substring(0, decoded_url.lastIndexOf('dpath=') + 6);
//pre is decoded
if (Jx.JxUtilities.isInteger(rowIndex)) {
decoded_dpath = Jx.JxUtilities.appendRowIndexToDPath(decoded_dpath, rowIndex);
} else {
var array = rowIndex.split('/');
for (var i = 0; i < array.length; i++) {
var withRowId = array[i];
var pos = withRowId.indexOf('[@rowId=');
var from = withRowId.substring(0, pos);
var newdecoded_dpath = decoded_dpath.replace('/' + from + '/', '/' + withRowId + '/');
if (newdecoded_dpath == decoded_dpath) {
var fromstr = '/' + from;
if (newdecoded_dpath.lastIndexOf(fromstr) + fromstr.length == newdecoded_dpath.length) {
newdecoded_dpath = newdecoded_dpath.substring(0, newdecoded_dpath.lastIndexOf('/')) + '/' + withRowId;
}
}
decoded_dpath = newdecoded_dpath;
}
}
var pos = Ext.urlEncode({
url: decoded_dpath
}).substring(4);
//pos is encoded
return pre + pos;
},
appendRowIndexToDPath: function (dpath, rowIndex) {
return dpath + "[@rowId=\"" + rowIndex + "\"]";
},
isInteger: function (s) {
return (s.toString().search(/^-?[0-9]+$/) == 0);
},
/**
* Set preview parameters if preview flag has been set to true
* @param caller
* @param url
*/
setPreviewUrl: function (caller, url) {
if (caller.findParentByType('jxsteppanel') != null) {
var stepPanel = caller.findParentByType('jxsteppanel');
if (stepPanel.previewMode) {
url = url + '&preview=true';
}
}
return url;
},
/**
* @param {Object} config
* @return {Number} heartbeat Id
* This function performs the task of initiating an heartbeat.
* Current active context is determined by using the selected node
* in the ribbon. The action url attribute of the node is used to
* generate the heartbeat.User of this utility function can provide
* success and failure handler function as an input config to this
* function.The user can also provide the time interval used to determine
* how frequently the heartbeat is sent to the server.
*/
startHeartbeat: function (config) {
function heartbeat() {
var ribbon = Ext.getCmp('newribbon');
if (ribbon) {
if (ribbon.treePane && ribbon.treePane.selectedNode) {
var actionURL = ribbon.treePane.selectedNode.attributes.action;
var heartbeatURL = actionURL.substring(0, actionURL.indexOf('?action'));
if (heartbeatURL.length > 0) {
new Jx.JxConnection().request({
url: config.url ? config.url : heartbeatURL,
scope: this,
success: config.successHandler ? config.successHandler : Ext.emptyFn,
failure: config.failureHandler ? config.failureHandler : Ext.emptyFn
});
}
}
}
}
this.heartbeatId = window.setInterval(heartbeat, config.interval);
return this.heartbeatId;
},
/**
* This function serves the purpose of stopping the heartbeat
* It does that by clearing the interval that sends the heartbeat.
*/
stopHeartbeat: function () {
window.clearInterval(this.heartbeatId);
},
/**
* @param functionName
* @param context
* This utility function takes two parameters. The function name and
* the context in which to execute the function. It then executes
* the function in the context/scope provided.
*/
executeFunctionByName: function (functionName, context /*, args */ ) {
var localContext = window[context];
var args = Array.prototype.slice.call(arguments).splice(2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for (var i = 0; i < namespaces.length; i++) {
localContext = localContext[namespaces[i]];
}
return localContext[func].apply(this, args);
},
/**
* @param functionName
* @param context
* This utility function takes two parameters. The constructor function
* name and the context.It then uses the context to locate the
* constructor function and execute it.
*/
executeConstructor: function (functionName, context /*, args */ ) {
var localContext = window[context];
var args = Array.prototype.slice.call(arguments).splice(2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for (var i = 0; i < namespaces.length; i++) {
localContext = localContext[namespaces[i]];
}
return new localContext[func](args);
},
/**
* @param files
* @param onLoadCallback
* This utility function mimics the functionality provided by many
* open source javascript frameworks to load javascript and css
* files dynamically. The user needs to provide array of filenames
* and the callback function that gets called once all the files
* are loaded.Under the hood this function uses the includeMany
* function provided by the JxNativeJxUtils.Each element within
* the file name array needs to be an array that has two members.
* The first member is the type of file and second is the name of the file.
* For example:
* this.jsFiles = [];
* this.cssFiles = [];
* this.jsFiles.push(['js', './js/examples/Jx/usertask/models/UserSore.js']) to load javascript file.
* this.cssFiles.push(['css', './css/usetask-1.css']) to load css file.
*/
require: function (files, onLoadCallback) {
var filenames = Ext.isArray(files) ? files : new Array(files);
JxNativeJsUtils.includeMany(files, onLoadCallback);
},
/**
* @param filetype
* @param filenames
* This utility function serves the purpose of dynamically removing the
* the script tags (for javascript files) and link tags (for css files)
* for the list of filenames provided by the user.The usage is as follows:
* Jx.JxUtilites.removeFiles('js',this.jsFiles);
* Jx.JxUtilites.removeFiles('js',this.cssFiles);
* where jsFiles and cssFiles are arrays that follow the convention mentioned
* in {@link Jx.JxUtilties.require}.
*/
removeFiles: function (filetype, filenames) {
var tags, attribute;
if (filetype == 'css') {
attribute = 'href';
tags = document.getElementsByTagName("link");
} else if (filetype == 'js') {
attribute = 'src';
tags = document.getElementsByTagName("script");
}
for (var i = 0; i < filenames.length; i++) {
for (var j = 0; j < tags.length; j++) {
var filenameInTag = tags[j].getAttribute(attribute);
var filenameToSearch = filenames[i][1];
if (filenameInTag && filenameToSearch) {
if (filenameInTag.search(filenameToSearch) != -1) {
console.log("Removing files " + filenameToSearch);
tags[j].parentNode.removeChild(tags[j]);
}
}
}
}
},
/**
* @param taskId
* This utility function calls the destroy method of
* the previously selected task.This is done for cleanup purposes.
* It then enables the user to jump to the task that has the task id
* provided by the user.
*/
jumpToTask: function (taskId) {
var newribbon = Ext.getCmp("newribbon");
newribbon.navigateTo(taskId);
}
};
}();