(function() {
/**
* @namespace Helpers
* Helper/Utility functions.
*/
var Helpers = {
/**
* Returns an element to be created in the DOM and adds attributes.
*
* @param {string} tag Tag you want to created, i.e "div", "span", etc...
* @param {object} attrs Attributes you want on the tag, i.e. class="test", src="img.jpg", etc...
* @return {HTMLElement}
*/
create: function(element, attrs) {
var ele = document.createElement(element);
if (attrs) {
for (var attr in attrs) {
if (attr === 'html') {
ele.innerHTML = attrs[attr];
} else {
// IE does not support support setting class name with set attribute
([attr] == 'class') ? ele.className = attrs[attr] : ele.setAttribute([attr], attrs[attr]);
}
}
}
return ele;
},
/**
* @function removeClass
* Removes a class name from an element.
* Thanks to http://blkcreative.com/words/simple-javascript-addclass-removeclass-and-hasclass/
*
* @param {HTMLElement} elem - element of class name you want removed.
* @param {String} classN - class name to be removed.
*/
removeClass: function(elem, classN) {
var currClass = elem.className.replace(/(^\s+|\s+$)/g, '');
var regex = new RegExp("(^|\\s)" + classN + "(\\s|$)", "g");
elem.className = (currClass.replace(regex, " ")).replace(/(^\s+|\s+$)/g, '');
},
/**
* @function hasClass
* Returns true or false if an element has a specifc class name.
* Thanks to http://blkcreative.com/words/simple-javascript-addclass-removeclass-and-hasclass/
*
* @param {HTMLElement} elem - element that may have the class name specified.
* @param {String} classN - class name to be checked for.
*/
hasClass: function(elem, classN) {
var regex = new RegExp("(^|\\s)" + classN + "(\\s|$)");
return regex.test(elem.className);
},
/**
* @function addClass
* Adds a class name to a given element.
*
* @param {HTMLElement} elem - element that you want a class name added to.
* @param {String} classN - new class name you want added to element.
*/
addClass: function(elem, classN) {
var currClass = elem.className.replace(/(^\s+|\s+$)/g, '');
var addedClass = (currClass.length === 0) ? classN : currClass + ' ' + classN;
if (!this.hasClass(elem, classN)) elem.className = addedClass;
},
/**
* Returns true or false if we are viewing on a mobile or tablet device.
* @return {Boolean}
*/
isMobile: function() {
var devices = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
return (devices.test(navigator.userAgent)) ? true : false;
},
/**
* Returns an element based on id.
*
* @param {String} id The id of the element to return.
* @return {htmlelement}
*/
$: function(id) {
return document.getElementById(id);
},
/**
* Returns true/false if a node is an HTML tag.
*
* @param {object} p The node to test if it is an HTML tag.
* @return {Boolean}
*/
isHtmlEl: function(p) {
return ((p.length) ? p[0].nodeType : p.nodeType === 1) ? true : false;
},
/**
* Returns true or false if the browser is IE8 or IE9
* @credit http://blogs.msdn.com/b/giorgio/archive/2009/04/14/how-to-detect-ie8-using-javascript-client-side.aspx
* @return {Boolean}
*/
isIE8or9: function() {
var rv = -1; // Return value assumes failure.
if (navigator.appName == 'Microsoft Internet Explorer') {
var ua = navigator.userAgent;
var re = new RegExp('MSIE ([0-9]{1,}[\.0-9]{0,})');
if (re.exec(ua) !== null) rv = parseFloat(RegExp.$1);
}
return (rv === 8 || rv === 9) ? true : false;
},
/**
* Returns the viewport height of the browser window.
* @return {Number}
*/
getWinH: function() {
var winH = 0;
var win = window;
var doc = document;
var docEle = doc.documentElement;
if (typeof win.innerHeight != 'undefined') {
winH = window.innerHeight;
} else if (typeof docEle != 'undefined' && typeof docEle.clientHeight != 'undefined' && docEle.clientHeight !== 0) {
winH = docEle.clientHeight;
} else {
winH = doc.getElementsByTagName('body')[0].clientHeight;
}
return winH;
},
/**
* Returns an Object as a string
* Credits go to https://github.com/douglascrockford/JSON-js
* Code was modified to fit certain needs.
*
* @param {Object} obj Object being passed
* @return {String}
*/
ObjString: function(obj) {
var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
var gap = '';
var indent = '';
var meta = {
"\b": "\\b",
" ": "\\t",
"\n": "\\n",
"\f": "\\f",
"\r": "\\r",
'"': '\\"',
"\\": "\\\\"
};
// Returns the primitive value
String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function() {
return this.valueOf();
};
/**
* Returns string with quotes
*
* @param {String} string - string being passed to surround with quotes.
* @return {String}
*/
var quote = function(string) {
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function(a) {
var c = meta[a];
return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
};
// Responsible for indentation, set to 4 spaces
for (var i = 0; i < 2; i += 1) {
indent += ' ';
}
// Magic behind parsing objects
var str = function(key, holder) {
var i = 0; // The loop counter.
var k = null; // The member key.
var v = null; // The member value.
var length;
var mind = gap;
var partial;
var value = holder[key];
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
case 'function':
return String(value);
case 'object':
if (!value) {
return 'null';
}
gap += indent;
partial = [];
if (Object.prototype.toString.apply(value) === '[object Array]') {
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']';
gap = mind;
return v;
}
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
/* Removing quotes from key
partial.push(quote(k) + (gap ? ': ' : ':') + v);*/
partial.push(k + (gap ? ': ' : ':') + v);
}
}
}
v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}';
gap = mind;
return v;
}
};
var j = str('', {
'': obj
});
return j.replace(/\n/g, '
').replace(/ /g, ' ');
}
};
/**
* @namespace CL
* Functionality used for the custom console.
*
*/
var CL = {
show: true,
height: 0,
synColor: {
err: '#FF0000',
_null: '#808080',
obj: '#881391',
str: '#C41A16',
numBoo: '#1C00CF',
tag: '#881280',
tagAttr: '#994500',
tagVal: '#1A1AA6',
time: '#0080FF'
},
textareaVal: '',
funcs: {
log: function() {'[native code]';},
debug: function() {'[native code]';},
time: function() {'[native code]';},
timeEnd: function() {'[native code]';},
clear: function() {'[native code]';},
error: function() {'[native code]';},
warn: function() {'[native code]';},
assert: function() {'[native code]';},
count: function() {'[native code]';}
},
_el: null,
_liExec: null,
_entries: null,
/**
* Initializes the custom console functions.
*/
init: function() {
this.setup();
this.insertRules(document.styleSheets[document.styleSheets.length - 1], '.CL{position:fixed;bottom:0;width:100%;left:0;border-top:1px solid #a3a3a3;z-index:2;font-size:12px}* html{height:100%}* html body{margin:0;padding:0;height:100%;zoom:1}* html #customconsole{position:absolute;right:auto;bottom:auto;top:expression((0 - customconsole.offsetHeight + (document.documentElement.clientHeight ? document.documentElement.clientHeight:document.body.clientHeight) + (ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop:document.body.scrollTop)) + "px")}.CL-header{overflow:auto;background:#ececec;border-bottom:1px solid #a3a3a3;*height:32px}.CL-header,.CL-title{font-family:Lucida Grande;font-size:12px}.CL-title{margin:0 0 0 10px;line-height:15px;border:1px solid #a3a3a3;border-bottom:0;float:left;background:#fff;padding:5px 8px 6px;font-weight:400;*margin:0 0 0 5px}.CL-tog{color:#333;display:block;text-decoration:none;outline:none;padding:4px 0;text-align:right;font-family:Lucida Grande;font-size:12px}.CL-togtxt{background:#a3a3a3;color:#fff;font-size:11px;padding:4px;margin-right:4px;display:inline-block}.CL-menu{background:#fff;overflow:auto;border-bottom:1px solid #e6e6e6;*height:31px}.CL-label{float:left;font-size:11px;padding:4px 0 4px 8px;margin:4px 0;text-transform:uppercase;border-left:1px solid #a3a3a3}.CL-clear{color:#333;display:block;text-decoration:none;outline:none;padding:8px 10px;color:#666;float:left}.CL-inp{width:23px;padding:2px;margin:4px;float:left;border:0}.CL-rad{margin:8px;border:2px solid #a3a3a3}.CL-entries{background:#fff;overflow:auto;position:relative;margin:0;padding:0;list-style-type:none;font-family:Lucida Grande;font-size:12px;width:100%}.CL-entries.show-timestamps .CL-timest{display:block}.CL-entry{clear:both;position:relative;min-height:16px;list-style-type:none;font-size:11px;z-index:1;border-bottom:1px solid #f0f0f0;overflow:auto;*zoom:1}.CL-entry .CL-timest{display:none}.CL-entry.CL-err{color:red;background:#fff0f0;border-top:1px solid #ffd6d6;border-bottom:1px solid #ffd6d6;margin-top:-1px}.CL-entry.CL-err .CL-sym{color:red}.CL-entry.CL-cleared .CL-sym{display:none}.CL-entry.CL-warn{background:#fffbe6;color:#5c3b00}.CL-entry.CL-exec{overflow:hidden;border-bottom:0}.CL-entry.CL-exec .CL-sym{color:#2d7df9;top:0!important}.CL-entry.CL-exec .CL-entrytxt{overflow:auto;padding-right:0;*zoom:0}.CL-sym{border:0;position:absolute;margin-left:10px;font-family:Arial;font-weight:900;color:#939393;font-size:12px;padding:3px 0;left:0}.CL-sym2{color:#bababa}.CL-entrytxt{margin-left:24px;display:block;padding:4px 22px 4px 0;word-wrap:break-word;position:relative;font-family:Menlo,monospace,Lucida Sans Unicode,Courier,Courier New;font-size:11px;*zoom:1}.CL-entrytxt.CL-timest{padding-right:6px;color:gray;font-size:10px;padding-bottom:0;display:none;float:right}.CL-txtarea{width:76%;float:left;padding:3px;height:30px;border:0;font-family:Menlo,monospace,Lucida Sans Unicode,Courier,Courier New;font-size:11px}.CL-execbtn{color:#333;text-decoration:none;outline:none;display:block;float:right;width:21%;text-align:center;text-transform:uppercase;line-height:38px}'); // Replaced by gulp
this.scriptParams();
// Added because IE 8 & 9 does support console.log, just needs to be enabled.
if (Helpers.isIE8or9()) {
alert('IE 8 & 9 support the console. The developer tools need to be opened for the console to work.');
}
this.setHeight(this.height, true);
this.toggle();
this.bindEvents();
},
/**
* Creates the console markup and appends to the document.
*/
setup: function() {
var style = Helpers.create('style', {
'type': 'text/css'
});
this._entries = Helpers.create('ul', {
'class': 'CL-entries'
});
this._el = Helpers.create('div', {
'class': 'CL',
id: 'customconsole',
'html':
'