Created
March 16, 2011 00:09
-
-
Save jankuca/871775 to your computer and use it in GitHub Desktop.
JavaScript Kit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
if (!Object.defineProperty) return; | |
Object.defineProperty(Function.prototype, 'initializing', { | |
value: false, | |
writable: true | |
}); | |
Object.defineProperty(Function.prototype, '$super', { | |
value: function () { | |
throw new Error('The $super method is not available.'); | |
}, | |
writable: true | |
}); | |
Function.prototype.inherit = function (init, props, reverse) { | |
if (arguments[1] === undefined && typeof init !== 'function') { | |
props = arguments[0]; | |
init = undefined; | |
} | |
props = props || {}; | |
var parent = this, | |
prototype; | |
try { | |
this.initializing = true; | |
prototype = new this(); | |
this.initializing = false; | |
} catch (exc) { | |
throw new Error('Not possible to inherit from this function'); | |
} | |
var createChildMethod = function (key, fn) { | |
return function () { | |
var tmp = this.$super, | |
_parent = parent.prototype, | |
_super; | |
do { | |
_super = _parent; | |
if (_parent.constructor === Object) { | |
break; | |
} | |
_parent = Object.getPrototypeOf(_parent); | |
} while (_super[key] === undefined); | |
if (_super[key] !== undefined) { | |
this.$super = _super[key]; | |
} | |
var res = fn.apply(this, Array.prototype.slice.call(arguments)); | |
this.$super = tmp; | |
return res; | |
}; | |
}; | |
Object.getOwnPropertyNames(props).forEach(function (key) { | |
if (typeof props[key] === 'function') { | |
prototype[key] = createChildMethod(key, props[key]); | |
} else { | |
var desc = Object.getOwnPropertyDescriptor(prototype, key); | |
if (desc === undefined || desc.configurable) { | |
Object.defineProperty(prototype, key, Object.getOwnPropertyDescriptor(props, key)); | |
} | |
} | |
}); | |
var Function = function () { | |
if (!this.constructor.initializing) { | |
var args = Array.prototype.slice.call(arguments); | |
if (!reverse && parent !== window.Function) { | |
parent.apply(this, args); | |
} | |
if (typeof init === 'function') { | |
init.apply(this, args); | |
} | |
if (reverse && parent !== window.Function) { | |
parent.apply(this, args); | |
} | |
} | |
}; | |
var skip = Object.getOwnPropertyNames(function () {}).concat(['__children__']); | |
Object.getOwnPropertyNames(parent).forEach(function (key) { | |
var desc = Object.getOwnPropertyDescriptor(this, key); | |
if ((desc === undefined || desc.configurable) && skip.indexOf(key) === -1) { | |
Object.defineProperty(this, key, Object.getOwnPropertyDescriptor(parent, key)); | |
} | |
}, Function); | |
Function.prototype = prototype; | |
prototype.constructor = Function; | |
if (Object.getOwnPropertyDescriptor(this, '__children__') === undefined) { | |
Object.defineProperty(this, '__children__', { | |
value: [] | |
}); | |
} | |
this.__children__.push(Function); | |
return Function; | |
}; | |
Function.prototype.getChildFunctions = function () { | |
return (this.__children__ !== undefined) ? this.__children__.slice() : []; | |
}; | |
var CustomEvent = function (type) { | |
var e; | |
try { | |
e = document.createEvent('CustomEvent'); | |
e.initCustomEvent.apply(e, Array.prototype.slice.call(arguments)); | |
} catch (exc) { | |
e = document.createEvent('UIEvents'); | |
e.initUIEvent.call(e, arguments[0], arguments[1], arguments[2], null, 1); | |
Object.defineProperty(e, 'detail', { | |
value: arguments[3] | |
}); | |
} | |
return e; | |
}; | |
var MouseEvent = function (type) { | |
var e = document.createEvent('MouseEvent'); | |
e.initMouseEvent.apply(e, Array.prototype.slice.call(arguments)); | |
return e; | |
}; | |
MouseEvent.prototype = window.MouseEvent.prototype; | |
Object.defineProperty(Object.prototype, 'eventReceiver', { | |
get: function () { | |
var desc = Object.getOwnPropertyDescriptor(this, '_eventReceiver'); | |
if (desc === undefined) { | |
var rcv = document.createElement('span'); | |
try { | |
Object.defineProperty(rcv, '_listeners', { | |
value: {} | |
}); | |
} catch (exc) {} | |
Object.defineProperty(this, '_eventReceiver', { | |
value: rcv, | |
writable: false | |
}); | |
} | |
return this._eventReceiver; | |
}, | |
set: function () { | |
} | |
}); | |
Object.defineProperty(Object.prototype, 'addEventListener', { | |
value: function (type, listener) { | |
var obj = this; | |
this.eventReceiver.addEventListener(type, function (e) { | |
listener.call(obj, e); | |
e._dispatched = true; | |
}, false); | |
var listeners = this.eventReceiver._listeners; | |
if (listeners !== void 0) { | |
if (listeners[type] === void 0) { | |
listeners[type] = [listener]; | |
} else { | |
listeners[type].push(listener); | |
} | |
} | |
return this; | |
} | |
}); | |
Object.defineProperty(Object.prototype, 'removeEventListener', { | |
value: function (type, listener) { | |
this.eventReceiver.removeEventListener(type, listener, false); | |
listeners = this.eventReceiver._listeners; | |
if (listeners !== void 0) { | |
listeners = listeners[type]; | |
if (listeners !== void 0 && listeners.length !== 0) { | |
listeners.forEach(function (l, i) { | |
if (listener === void 0 || listener === l) { | |
delete listeners[i]; | |
} | |
}); | |
} | |
} | |
return this; | |
} | |
}); | |
Object.defineProperty(Object.prototype, 'dispatchEvent', { | |
value: function (e) { | |
var res = this.eventReceiver.dispatchEvent(e); | |
if (!e._dispatched && this.eventReceiver._listeners) { | |
var listeners = this.eventReceiver._listeners[e.type]; | |
if (listeners !== void 0) { | |
listeners.forEach(function (listener) { | |
listener.call(this, e); | |
}, this); | |
} | |
} | |
return res; | |
} | |
}); | |
Object.defineProperty(Object.prototype, 'fire', { | |
value: function (e, detail) { | |
if (e instanceof Event) { | |
if (detail !== undefined) { | |
throw new Error('Invalid usage.'); | |
} | |
if (['click', 'mouseover', 'mouseout', 'mousedown', 'mouseup', 'dblclick'].indexOf(e.type) !== -1) { | |
e = new MouseEvent(e.type, true, true, window, detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 0, null); | |
} | |
return this.dispatchEvent(e); | |
} | |
e = new CustomEvent(e, true, true, detail); | |
return this.dispatchEvent(e); | |
}, | |
writable: true | |
}); | |
if (Function.prototype.bind === undefined) { | |
Function.prototype.bind = function (ctx /* , params... */) { | |
var fn = this; | |
var args = Array.prototype.slice.call(arguments, 1); | |
return function () { | |
return fn.apply(ctx, args.concat( | |
Array.prototype.slice.call(arguments) | |
)); | |
}; | |
}; | |
} | |
var chainify = { | |
'Element': [ | |
'addEventListener', | |
'removeEventListener' | |
] | |
}; | |
Object.keys(chainify).forEach(function (key) { | |
var obj = window[key], | |
__slice = Array.prototype.slice; | |
/*if (typeof obj !== 'function') { | |
throw new Error('Only functions can be chainified.'); | |
}*/ | |
chainify[key].forEach(function (key) { | |
var fn = this[key]; | |
if (typeof fn === 'function') { | |
this[key] = function () { | |
fn.apply(this, __slice.call(arguments)); | |
return this; | |
}; | |
} | |
}, obj.prototype); | |
}); | |
if (Array.prototype.first === undefined) { | |
Array.prototype.first = function () { | |
return this[0] || undefined; | |
}; | |
} | |
if (Array.prototype.last === undefined) { | |
Array.prototype.last = function () { | |
return this.length ? this[this.length - 1] : undefined; | |
}; | |
} | |
if (Array.prototype.compact === undefined) { | |
Array.prototype.compact = function () { | |
return this.filter(function (a) { | |
return (a !== void 0 && a !== null); | |
}); | |
}; | |
} | |
var NativeElement = Element; | |
window.Element = function(tagName, attrs) { | |
tagName = tagName.toLowerCase(); | |
var el = document.createElement(tagName); | |
if (attrs !== undefined) { | |
Object.getOwnPropertyNames(attrs).forEach(function (key) { | |
this.setAttribute(key, attrs[key]); | |
}, el); | |
} | |
return el; | |
}; | |
Element.prototype = NativeElement.prototype; | |
Element.prototype.html = function (html) { | |
if (html === undefined) { | |
return this.innerHTML; | |
} | |
this.innerHTML = (html !== null) ? html : ''; | |
return this; | |
}; | |
Element.prototype.attr = function (key, value) { | |
if (value === undefined) { | |
return this.getAttribute(key); | |
} | |
this.setAttribute(key, value); | |
return this; | |
}; | |
Element.prototype.data = function (key, value) { | |
return this.attr('data-' + key, value); | |
}; | |
Element.prototype.hasClassName = function (className) { | |
return new RegExp('(^|\\s)' + className + '(\\s|$)').test(this.className); | |
}; | |
Element.prototype.addClassName = function (className) { | |
if (!this.hasClassName(className)) { | |
this.className += ' ' + className; | |
this.className = this.className.replace(/(^\s+|\s+$)/g, ''); | |
} | |
return this; | |
}; | |
Element.prototype.removeClassName = function (className) { | |
var e = this.className.split(/\s+/), | |
index = e.indexOf(className); | |
if (index > -1) { | |
delete e[index]; | |
this.className = e.join(' '); | |
} | |
return this; | |
}; | |
Element.prototype.show = function () { | |
if (this.style.display === 'none') { | |
this.style.display = ''; | |
} | |
return this; | |
}; | |
Element.prototype.hide = function () { | |
if (this.style.display !== 'none') { | |
this.style.display = 'none'; | |
} | |
return this; | |
}; | |
Element.prototype.insert = function () { | |
var input = arguments[0]; | |
switch (typeof input) { | |
case 'undefined': | |
throw new Error('Missing input'); | |
case 'string': | |
case 'number': | |
this.appendChild(document.createTextNode(input)); | |
break; | |
case 'object': | |
if (input instanceof Element || input instanceof DocumentFragment) { | |
this.appendChild(input) | |
} else { | |
Object.getOwnPropertyNames(input).forEach(function (pos) { | |
var els = input[pos], | |
parent; | |
els = (els instanceof Array) ? els : [els]; | |
switch (pos) { | |
case 'top': | |
els.forEach(function (el) { | |
this.firstChild ? this.insertBefore(el, this.firstChild) : this.appendChild(el); | |
}, this); | |
break; | |
case 'bottom': | |
els.forEach(function (el) { | |
this.appendChild(el); | |
}, this); | |
break; | |
case 'before': | |
parent = this.parentNode; | |
if (!parent) { | |
throw new Error('No parent node'); | |
} | |
els.forEach(function (el) { | |
parent.insertBefore(el, this); | |
}, this); | |
break; | |
case 'after': | |
parent = this.parentNode; | |
if (!parent) { | |
throw new Error('No parent node'); | |
} | |
if (parent.lastChild === this) { | |
els.forEach(function (el) { | |
parent.appendChild(el); | |
}); | |
} else { | |
var next = this.nextSibling; | |
els.forEach(function (el) { | |
parent.insertBefore(el, next); | |
}); | |
} | |
break; | |
} | |
}, this); | |
} | |
break; | |
} | |
return this; | |
}; | |
Element.prototype.appendTo = function (target) { | |
target.appendChild(this); | |
return this; | |
}; | |
Element.prototype.find = function () { | |
var node_list = this.querySelectorAll.apply(this, arguments); | |
return Array.prototype.slice.call(node_list); | |
}; | |
DocumentFragment.prototype.find = Element.prototype.find; | |
Element.prototype.findOne = function () { | |
return this.querySelector.apply(this, arguments); | |
}; | |
DocumentFragment.prototype.findOne = Element.prototype.findOne; | |
Element.prototype.remove = function () { | |
var parent = this.parentNode; | |
if (!parent) { | |
throw new Error('No parent node'); | |
} | |
parent.removeChild(this); | |
return this; | |
}; | |
if (new Element('span').innerText === undefined) { | |
Object.defineProperty(Element.prototype, 'innerText', { | |
get: function () { | |
return this.textContent; | |
}, | |
set: function (value) { | |
this.textContent = value; | |
} | |
}); | |
} | |
NodeList.prototype.forEach = function () { | |
return Array.prototype.forEach.apply(this, arguments); | |
}; | |
NodeList.prototype.some = function () { | |
return Array.prototype.some.apply(this, arguments); | |
}; | |
NodeList.prototype.every = function () { | |
return Array.prototype.every.apply(this, arguments); | |
}; | |
NodeList.prototype.map = function () { | |
return Array.prototype.map.apply(this, arguments); | |
}; | |
NodeList.prototype.reduce = function () { | |
return Array.prototype.reduce.apply(this, arguments); | |
}; | |
NodeList.prototype.filter = function () { | |
return Array.prototype.filter.apply(this, arguments); | |
}; | |
NodeList.prototype.first = Array.prototype.first; | |
NodeList.prototype.last = Array.prototype.last; | |
if (window.FileList !== void 0) { | |
FileList.prototype.forEach = Array.prototype.forEach; | |
} | |
if (Range.prototype.reapply === undefined) { | |
Range.prototype.reapply = function () { | |
var sel = window.getSelection(), | |
range = document.createRange(); | |
range.setStart(this.startContainer, this.startOffset); | |
range.setEnd(this.endContainer,this.endOffset); | |
sel.removeAllRanges(); | |
sel.addRange(range); | |
return range; | |
}; | |
} | |
if (String.prototype.escapeHTML === undefined) { | |
String.prototype.escapeHTML = function () { | |
return this | |
.replace(/&/g, "&") | |
.replace(/</g, "<") | |
.replace(/>/g, ">") | |
.replace(/"/g, """) | |
.replace(/'/g, "'"); | |
}; | |
} | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment