QCubed object creation js performance
JavaScript performance comparison
Info
this function is called for every qcubed control, it adds function to every dom node representing a qcubed control ...
Preparation code
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<span id="editButton1_ctl"><button type="button" name="editButton" id="editButton1" class="button"> Edit Person </button></span>
<span id="editButton2_ctl"><button type="button" name="editButton" id="editButton2" class="button"> Edit Person </button></span>
<span id="editButton3_ctl"><button type="button" name="editButton" id="editButton3" class="button"> Edit Person </button></span>
<span id="editButton4_ctl"><button type="button" name="editButton" id="editButton4" class="button"> Edit Person </button></span>
<span id="editButton5_ctl"><button type="button" name="editButton" id="editButton5" class="button"> Edit Person </button></span>
<span id="editButton6_ctl"><button type="button" name="editButton" id="editButton6" class="button"> Edit Person </button></span>
<span id="editButton7_ctl"><button type="button" name="editButton" id="editButton17" class="button"> Edit Person </button></span>
<span id="editButton8_ctl"><button type="button" name="editButton" id="editButton8" class="button"> Edit Person </button></span>
<span id="editButton9_ctl"><button type="button" name="editButton" id="editButton9" class="button"> Edit Person </button></span>
<span id="editButton10_ctl"><button type="button" name="editButton" id="editButton10" class="button"> Edit Person </button></span>
<span id="editButton11_ctl"><button type="button" name="editButton" id="editButton11" class="button"> Edit Person </button></span>
<span id="editButton12_ctl"><button type="button" name="editButton" id="editButton12" class="button"> Edit Person </button></span>
<span id="editButton13_ctl"><button type="button" name="editButton" id="editButton13" class="button"> Edit Person </button></span>
<span id="editButton14_ctl"><button type="button" name="editButton" id="editButton14" class="button"> Edit Person </button></span>
<span id="editButton15_ctl"><button type="button" name="editButton" id="editButton15" class="button"> Edit Person </button></span>
<span id="editButton16_ctl"><button type="button" name="editButton" id="editButton16" class="button"> Edit Person </button></span>
<span id="editButton17_ctl"><button type="button" name="editButton" id="editButton17" class="button"> Edit Person </button></span>
<span id="editButton18_ctl"><button type="button" name="editButton" id="editButton18" class="button"> Edit Person </button></span>
<span id="editButton19_ctl"><button type="button" name="editButton" id="editButton19" class="button"> Edit Person </button></span>
<span id="editButton20_ctl"><button type="button" name="editButton" id="editButton20" class="button"> Edit Person </button></span>
<script>
var $j = jQuery.noConflict();
$j.fn.extend({
wait: function(time, type) {
time = time || 1000;
type = type || "fx";
return this.queue(type, function() {
var self = this;
setTimeout(function() {
$j(self).dequeue();
}, time);
});
}
});
/*
* Queued Ajax requests.
* A new Ajax request won't be started until the previous queued
* request has finished.
*/
$j.ajaxQueue = function(o){
$j.ajax( o );
};
/*
* Synced Ajax requests.
* The Ajax request will happen as soon as you call this method, but
* the callbacks (success/error/complete) won't fire until all previous
* synced requests have been completed.
*/
$j.ajaxSync = function(o){
var fn = $j.ajaxSync.fn, data = $j.ajaxSync.data, pos = fn.length;
fn[ pos ] = {
error: o.error,
success: o.success,
complete: o.complete,
done: false
};
data[ pos ] = {
error: [],
success: [],
complete: []
};
o.error = function(){ data[ pos ].error = arguments; };
o.success = function(){ data[ pos ].success = arguments; };
o.complete = function(){
data[ pos ].complete = arguments;
fn[ pos ].done = true;
if ( pos == 0 || !fn[ pos-1 ] )
for ( var i = pos; i < fn.length && fn[i].done; i++ ) {
if ( fn[i].error ) fn[i].error.apply( $j, data[i].error );
if ( fn[i].success ) fn[i].success.apply( $j, data[i].success );
if ( fn[i].complete ) fn[i].complete.apply( $j, data[i].complete );
fn[i] = null;
data[i] = null;
}
};
return $j.ajax(o);
};
$j.ajaxSync.fn = [];
$j.ajaxSync.data = [];
///////////////////////////////////////////////////
// The QCubed Object is used for everything in Qcodo
///////////////////////////////////////////////////
var qcubed = {
recordControlModification: function (strControlId, strProperty, strNewValue) {
if (!qcubed.controlModifications[strControlId])
qcubed.controlModifications[strControlId] = new Object;
qcubed.controlModifications[strControlId][strProperty] = strNewValue;
},
postBack: function(strForm, strControl, strEvent, mixParameter) {
var strForm = $j("#Qform__FormId").attr("value");
var objForm = $j('#' + strForm);
if ( mixParameter && ( typeof mixParameter !== "string" ) ) {
mixParameter = $j.param( { "Qform__FormParameter" : mixParameter } );
objForm.append('<input type="hidden" name="Qform__FormParameterType" value="obj">');
}
$j('#Qform__FormControl').attr("value", strControl);
$j('#Qform__FormEvent').attr("value", strEvent);
$j('#Qform__FormParameter').attr("value", mixParameter);
$j('#Qform__FormCallType').attr("value", "Server");
$j('#Qform__FormUpdates').attr("value", this.formUpdates());
$j('#Qform__FormCheckableControls').attr("value", this.formCheckableControls(strForm, "Server"));
// have $j trigger the submit event (so it can catch all submit events)
objForm.trigger("submit");
},
formUpdates: function() {
var strToReturn = "";
for (var strControlId in qcubed.controlModifications)
for (var strProperty in qcubed.controlModifications[strControlId])
strToReturn += strControlId + " " + strProperty + " " + qcubed.controlModifications[strControlId][strProperty] + "\n";
qcubed.controlModifications = new Object;
return strToReturn;
},
formCheckableControls: function(strForm, strCallType) {
// Select the QCubed Form
var objFormElements = $j('#' + strForm + ' input,select,textarea');
var strToReturn = "";
objFormElements.each(function(i) {
if ((($j(this).attr("type") == "checkbox") ||
($j(this).attr("type") == "radio")) &&
((strCallType == "Ajax") ||
(!$j(this).attr("disabled")))) {
var strControlId = $j(this).attr("id");
// CheckBoxList
if (strControlId.indexOf('[') >= 0) {
if (strControlId.indexOf('[0]') >= 0)
strToReturn += " " + strControlId.substring(0, strControlId.length - 3);
// RadioButtonList
} else if (strControlId.indexOf('_') >= 0) {
if (strControlId.indexOf('_0') >= 0)
strToReturn += " " + strControlId.substring(0, strControlId.length - 2);
// Standard Radio or Checkbox
} else {
strToReturn += " " + strControlId;
}
}
});
if (strToReturn.length > 0)
return strToReturn.substring(1);
else
return "";
},
postAjax: function(strForm, strControl, strEvent, mixParameter, strWaitIconControlId) {
var objForm = $j('#' + strForm);
var strFormAction = objForm.attr("action");
var objFormElements = $j('#' + strForm + ' input,#' + strForm + ' select,#' + strForm + ' textarea');
var strPostData = '';
if( mixParameter && ( typeof mixParameter !== "string" ) ) {
strPostData = $j.param( { "Qform__FormParameter" : mixParameter } );
objFormElements = objFormElements.not("#Qform__FormParameter");
}
else {
$j('#Qform__FormParameter').attr("value", mixParameter);
}
$j('#Qform__FormControl').attr("value", strControl);
$j('#Qform__FormEvent').attr("value", strEvent);
$j('#Qform__FormCallType').attr("value", "Ajax");
$j('#Qform__FormUpdates').attr("value", this.formUpdates());
$j('#Qform__FormCheckableControls').attr("value", this.formCheckableControls(strForm, "Ajax"));
objFormElements.each(function () {
var strType = $j(this).attr("type");
var strControlId = $j(this).attr("id");
switch (strType) {
case "checkbox":
case "radio":
if ($j(this).attr("checked")) {
var strTestName = $j(this).attr("name") + "_";
if (strControlId.substring(0, strTestName.length) == strTestName)
strPostData += "&" + $j(this).attr("name") + "=" + strControlId.substring(strTestName.length);
else
strPostData += "&" + strControlId + "=" + $j(this).val();
};
break;
case "select-multiple":
var blnOneSelected = false;
$j(this).find(':selected').each (function (i) {
strPostData += "&" + $j(this).parents("select").attr("name") + "=";
strPostData += $j(this).val();
});
break;
default:
strPostData += "&" + strControlId + "=";
// For Internationalization -- we must escape the element's value properly
var strPostValue = $j(this).val();
if (strPostValue) {
strPostValue = strPostValue.replace(/\%/g, "%25");
strPostValue = strPostValue.replace(/&/g, escape('&'));
strPostValue = strPostValue.replace(/\+/g, "%2B");
}
strPostData += strPostValue;
break;
}
});
if (strWaitIconControlId) {
this.objAjaxWaitIcon = this.getWrapper(strWaitIconControlId);
if (this.objAjaxWaitIcon)
this.objAjaxWaitIcon.style.display = 'inline';
};
$j.ajaxQueue({
url: strFormAction,
type: "POST",
data: strPostData,
error: function (XMLHttpRequest, textStatus, errorThrown) {
if (XMLHttpRequest.status != 0 || XMLHttpRequest.responseText.length > 0) {
alert("An error occurred during AJAX Response parsing.\r\n\r\nThe error response will appear in a new popup.");
var objErrorWindow = window.open('about:blank', 'qcodo_error','menubar=no,toolbar=no,location=no,status=no,scrollbars=yes,resizable=yes,width=1000,height=700,left=50,top=50');
objErrorWindow.focus();
objErrorWindow.document.write(XMLHttpRequest.responseText);
return;
}
},
success: function (xml) {
$j(xml).find('control').each(function() {
var strControlId = '#' + $j(this).attr("id");
var strControlHtml = $j(this).text();
if (strControlId == "#Qform__FormState") {
$j(strControlId).val(strControlHtml);
} else {
var ctrl = $j(strControlId + "_ctl");
if(ctrl.length)
ctrl.html(strControlHtml);
else
$j(strControlId).replaceWith(strControlHtml);
}
});
var strCommand = '';
$j(xml).find('command').each(function() {
strCommand += $j(this).text();
});
eval(strCommand);
if (qcubed.objAjaxWaitIcon)
qcubed.objAjaxWaitIcon.style.display = 'none';
}
});
},
initialize: function() {
////////////////////////////////
// Browser-related functionality
////////////////////////////////
this.loadJavaScriptFile = function(strScript, objCallback) {
strScript = qc.jsAssets + "/" + strScript;
jQuery.ajax({type: "GET",url: strScript,success: objCallback,dataType: "script",cache: true});//$j.getScript(strScript, objCallback);
};
this.loadStyleSheetFile = function(strStyleSheetFile, strMediaType) {
strStyleSheetFile = qc.cssAssets + "/" + strStyleSheetFile;
$j('head').append('<link rel="stylesheet" href="' + strStyleSheetFile + '" type="text/css" />');
};
/////////////////////////////
// QForm-related functionality
/////////////////////////////
this.wrappers = new Array();
}
};
///////////////////////////////
// Timers-related functionality
///////////////////////////////
qcubed._objTimers = new Object();
qcubed.clearTimeout = function(strTimerId) {
if (qcubed._objTimers[strTimerId]) {
clearTimeout(qcubed._objTimers[strTimerId]);
qcubed._objTimers[strTimerId] = null;
};
};
qcubed.setTimeout = function(strTimerId, strAction, intDelay) {
qcubed.clearTimeout(strTimerId);
qcubed._objTimers[strTimerId] = setTimeout(strAction, intDelay);
};
/////////////////////////////////////
// Event Object-related functionality
/////////////////////////////////////
// You may still use this function but be advised
// we no longer use it in core. All event terminations
// and event bubbling are handled through jQuery.
// see http://trac.qcu.be/projects/qcubed/ticket/681
// @deprecated
qcubed.terminateEvent = function(objEvent) {
objEvent = qcubed.handleEvent(objEvent);
if (objEvent) {
// Stop Propogation
if (objEvent.preventDefault)
objEvent.preventDefault();
if (objEvent.stopPropagation)
objEvent.stopPropagation();
objEvent.cancelBubble = true;
objEvent.returnValue = false;
};
return false;
};
////////////////////////////////
// Qcodo Shortcut and Initialize
////////////////////////////////
// Make sure we set $j.noConflict() to $j
var qc = qcubed;
qc.initialize();
qc.pB = qcubed.postBack;
qc.pA = qcubed.postAjax;
</script>
<script>
/////////////////////////////////
// Controls-related functionality
/////////////////////////////////
qcubed.getControl = function(mixControl) {
if (typeof(mixControl) == 'string')
return document.getElementById(mixControl);
else
return mixControl;
};
qcubed.getWrapper = function(mixControl) {
var objControl;
if (!(objControl = qcubed.getControl(mixControl)))
{
//maybe it doesn't have a child control, just the wrapper
if (typeof(mixControl) == 'string')
return this.getControl(mixControl + "_ctl");
return;
}
if (objControl)
return this.getControl(objControl.id + "_ctl");
else
return null;
};
/////////////////////////////
// Register Control - General
/////////////////////////////
qcubed.controlModifications = new Object;
qcubed.javascriptStyleToQcodo = new Object;
qcubed.javascriptStyleToQcodo["backgroundColor"] = "BackColor";
qcubed.javascriptStyleToQcodo["borderColor"] = "BorderColor";
qcubed.javascriptStyleToQcodo["borderStyle"] = "BorderStyle";
qcubed.javascriptStyleToQcodo["border"] = "BorderWidth";
qcubed.javascriptStyleToQcodo["height"] = "Height";
qcubed.javascriptStyleToQcodo["width"] = "Width";
qcubed.javascriptStyleToQcodo["text"] = "Text";
qcubed.javascriptWrapperStyleToQcodo = new Object;
qcubed.javascriptWrapperStyleToQcodo["position"] = "Position";
qcubed.javascriptWrapperStyleToQcodo["top"] = "Top";
qcubed.javascriptWrapperStyleToQcodo["left"] = "Left";
qcubed.recordControlModification = function(strControlId, strProperty, strNewValue) {
if (!qcubed.controlModifications[strControlId])
qcubed.controlModifications[strControlId] = new Object;
qcubed.controlModifications[strControlId][strProperty] = strNewValue;
};
qcubed.registerControl = function(mixControl) {
var objControl;
objControl = qcubed.getControl(mixControl);
// Link the Wrapper and the Control together
var objWrapper = this.getWrapper(mixControl);
if(!objWrapper) return;
if(objControl !== null)
objControl.wrapper = objWrapper;
objWrapper.control = objControl;
// Add the wrapper to the global qcodo wrappers array
qcubed.wrappers[objWrapper.id] = objWrapper;
// Create New Methods, etc.
// Like: objWrapper.something = xyz;
// Updating Style-related Things
objWrapper.updateStyle = function(strStyleName, strNewValue) {
if(this.control === null)
{
switch (strStyleName) {
case "display":
if (strNewValue) {
objWrapper.style.display = "inline";
} else {
objWrapper.style.display = "none";
};
break;
default:
if (qcubed.javascriptWrapperStyleToQcodo[strStyleName]) {
this.style[strStyleName] = strNewValue;
};
break;
};
return;
}
var objControl = this.control;
switch (strStyleName) {
case "className":
objControl.className = strNewValue;
qcubed.recordControlModification(objControl.id, "CssClass", strNewValue);
break;
case "parent":
if (strNewValue) {
var objNewParentControl = qcubed.getControl(strNewValue);
objNewParentControl.appendChild(this);
qcubed.recordControlModification(objControl.id, "Parent", strNewValue);
} else {
var objParentControl = this.parentNode;
objParentControl.removeChild(this);
qcubed.recordControlModification(objControl.id, "Parent", "");
};
break;
case "displayStyle":
objControl.style.display = strNewValue;
qcubed.recordControlModification(objControl.id, "DisplayStyle", strNewValue);
break;
case "display":
if (strNewValue) {
objWrapper.style.display = "inline";
qcubed.recordControlModification(objControl.id, "Display", "1");
} else {
objWrapper.style.display = "none";
qcubed.recordControlModification(objControl.id, "Display", "0");
};
break;
case "enabled":
if (strNewValue) {
objWrapper.control.disabled = false;
qcubed.recordControlModification(objControl.id, "Enabled", "1");
} else {
objWrapper.control.disabled = true;
qcubed.recordControlModification(objControl.id, "Enabled", "0");
};
break;
case "width":
case "height":
objControl.style[strStyleName] = strNewValue;
if (qcubed.javascriptStyleToQcodo[strStyleName])
qcubed.recordControlModification(objControl.id, qcubed.javascriptStyleToQcodo[strStyleName], strNewValue);
if (objWrapper.handle)
objWrapper.updateHandle();
break;
case "text":
objControl.innerHTML = strNewValue;
qcubed.recordControlModification(objControl.id, "Text", strNewValue);
break;
default:
if (qcubed.javascriptWrapperStyleToQcodo[strStyleName]) {
this.style[strStyleName] = strNewValue;
qcubed.recordControlModification(objControl.id, qcubed.javascriptWrapperStyleToQcodo[strStyleName], strNewValue);
} else {
objControl.style[strStyleName] = strNewValue;
if (qcubed.javascriptStyleToQcodo[strStyleName])
qcubed.recordControlModification(objControl.id, qcubed.javascriptStyleToQcodo[strStyleName], strNewValue);
};
break;
};
};
// Positioning-related functions
objWrapper.getAbsolutePosition = function() {
var intOffsetLeft = 0;
var intOffsetTop = 0;
var objControl = this.control;
while (objControl) {
// If we are IE, we don't want to include calculating
// controls who's wrappers are position:relative
if ((objControl.wrapper) && (objControl.wrapper.style.position == "relative")) {
} else {
intOffsetLeft += objControl.offsetLeft;
intOffsetTop += objControl.offsetTop;
};
objControl = objControl.offsetParent;
};
return {x:intOffsetLeft, y:intOffsetTop};
};
objWrapper.setAbsolutePosition = function(intNewX, intNewY, blnBindToParent) {
var objControl = this.offsetParent;
while (objControl) {
intNewX -= objControl.offsetLeft;
intNewY -= objControl.offsetTop;
objControl = objControl.offsetParent;
};
if (blnBindToParent) {
if (this.parentNode.nodeName.toLowerCase() != 'form') {
// intNewX and intNewY must be within the parent's control
intNewX = Math.max(intNewX, 0);
intNewY = Math.max(intNewY, 0);
intNewX = Math.min(intNewX, this.offsetParent.offsetWidth - this.offsetWidth);
intNewY = Math.min(intNewY, this.offsetParent.offsetHeight - this.offsetHeight);
};
};
this.updateStyle("left", intNewX + "px");
this.updateStyle("top", intNewY + "px");
};
// Toggle Display / Enabled
objWrapper.toggleDisplay = function(strShowOrHide) {
// Toggles the display/hiding of the entire control (including any design/wrapper HTML)
// If ShowOrHide is blank, then we toggle
// Otherwise, we'll execute a "show" or a "hide"
if (strShowOrHide) {
if (strShowOrHide == "show")
this.updateStyle("display", true);
else
this.updateStyle("display", false);
} else
this.updateStyle("display", (this.style.display == "none") ? true : false);
};
objWrapper.toggleEnabled = function(strEnableOrDisable) {
if (strEnableOrDisable) {
if (strEnableOrDisable == "enable")
this.updateStyle("enabled", true);
else
this.updateStyle("enabled", false);
} else
this.updateStyle("enabled", (this.control.disabled) ? true : false);
};
objWrapper.registerClickPosition = function(objEvent) {
var intX = objEvent.pageX - this.control.offsetLeft;
var intY = objEvent.pageY - this.control.offsetTop;
$j('#' + this.control.id + "_x").val(intX);
$j('#' + this.control.id + "_y").val(intY);
};
// Focus
objWrapper.focus = function() {
$j('#' + this.control.id).focus();
};
// Select All (will only work for textboxes only)
objWrapper.select = function() {
$j('#' + this.control.id).select();
};
// Blink
objWrapper.blink = function(strFromColor, strToColor) {
$j('#' + this.control.id).css('background-color', '' + strFromColor);
$j('#' + this.control.id).animate({ backgroundColor: '' + strToColor }, 500)
};
}
qcubed.registerControlArray = function(mixControlArray) {
var intLength = mixControlArray.length;
for (var intIndex = 0; intIndex < intLength; intIndex++)
qcubed.registerControl(mixControlArray[intIndex]);
};
//////////////////
// Qcodo Shortcuts
//////////////////
qc.getC = qcubed.getControl;
qc.getW = qcubed.getWrapper;
qc.regC = qcubed.registerControl;
qc.regCA = qcubed.registerControlArray;
qcubed.altRegisterControl = function(mixControl) {
var objControl;
objControl = qcubed.getControl(mixControl);
// Link the Wrapper and the Control together
var objWrapper = this.getWrapper(mixControl);
if(!objWrapper) return;
if(objControl !== null)
objControl.wrapper = objWrapper;
objWrapper.control = objControl;
}
</script>
Preparation code output
Test runner
Warning! For accurate results, please disable Firebug before running the tests. (Why?)
Java applet disabled.
| Test | Ops/sec | |
|---|---|---|
default qcubed behaviour |
|
pending… |
version that does not create functions on each QControl dom node |
|
pending… |
You can edit these tests or add even more tests to this page by appending /edit to the URL.
0 comments