Created
October 11, 2015 23:56
-
-
Save ryan-scott-dev/1e030804042046d2c2a0 to your computer and use it in GitHub Desktop.
Handy JS
This file contains hidden or 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.prototype.method = function (name, func) { | |
this.prototype[name] = func; | |
return this; | |
}; | |
Function.method('mixin', function (properties) { | |
Object.keys(properties).forEach(function(property) { | |
if (!this.prototype.hasOwnProperty(property)) { | |
this.prototype[property] = properties[property]; | |
} | |
}.bind(this)); | |
}); | |
Function.method('override', function (properties) { | |
Object.keys(properties).forEach(function(property) { | |
this.prototype[property] = properties[property]; | |
}.bind(this)); | |
}); | |
Function.method('properties', function (propertyDefinitions) { | |
Object.keys(propertyDefinitions).forEach(function(property) { | |
Object.defineProperty(this.prototype, property, propertyDefinitions[property]); | |
}.bind(this)); | |
}); | |
Function.method('delegate', function (properties) { | |
Object.keys(properties).forEach(function(property) { | |
var delegatedMethods = properties[property]; | |
for (var i = 0; i < delegatedMethods.length; i++) { | |
var delegatedMethod = delegatedMethods[i]; | |
this.method(delegatedMethod, function(property, delegatedMethod) { | |
/* Nested in a function so that the variables are pushed to the stack, otherwise delegatedMethod is always the last value */ | |
return function() { | |
var delegate = this[property](); | |
return delegate[delegatedMethod].apply(delegate, arguments); | |
}; | |
}(property, delegatedMethod)); | |
} | |
}); | |
}); |
This file contains hidden or 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
Prototype = (function() { | |
function createPropertyDefinitions(properties) { | |
return Object.keys(properties) | |
.reduce(function(reducedProperties, property) { | |
if (typeof properties[property] === 'function') { | |
reducedProperties[property] = { | |
get: properties[property] | |
}; | |
} else { | |
reducedProperties[property] = { | |
value: properties[property], | |
writable: true, | |
configurable: true, | |
enumerable: true | |
}; | |
} | |
return reducedProperties; | |
}, {}); | |
} | |
return function(params) { | |
params = params || {}; | |
var base = params.base ? params.base.prototype : Object; | |
var events = params.events || []; | |
var constructor = params.constructor; | |
var methods = params.methods || {}; | |
var staticMethods = params.static || {}; | |
var properties = params.properties || {}; | |
var name = params.name || (params.base ? params.base.name : 'unknown'); | |
var builtPrototype = (new Function("return function (call) { return function " + name + | |
" () { return call(this, arguments) }; };")())(Function.apply.bind(function() { | |
if (events && events.length > 0) { | |
this.events = {}; | |
events.forEach(function(eventName) { | |
this.events[eventName] = new Signal(); | |
}.bind(this)); | |
} | |
constructor.apply(this, arguments); | |
})); | |
builtPrototype.prototype = Object.create(base); | |
builtPrototype.prototype.constructor = builtPrototype; | |
builtPrototype.prototype.name = name; | |
if (base) { | |
builtPrototype.prototype.base = base; | |
builtPrototype.prototype.superConstructor = function() { base.constructor.apply(this, arguments) }; | |
} | |
var propertyDefinitions = createPropertyDefinitions(properties); | |
builtPrototype.properties(propertyDefinitions); | |
Object.keys(staticMethods).forEach(function(staticMethodName) { | |
builtPrototype[staticMethodName] = staticMethods[staticMethodName]; | |
}); | |
builtPrototype.mixin(methods); | |
builtPrototype.mixin({ | |
clearEventHandlers: function() { | |
Object.keys(this.events).forEach(function(eventName) { | |
this.events[eventName].removeAll(); | |
}.bind(this)); | |
} | |
}); | |
return builtPrototype; | |
}; | |
})(); |
This file contains hidden or 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
// https://github.com/Hypercubed/mini-signals | |
/** | |
* Representation of a single Signal function. | |
* | |
* @param {Function} fn Event handler to be called. | |
* @param {Mixed} context Context for function execution. | |
* @api private | |
*/ | |
function Node(fn, context) { | |
this.fn = fn; | |
this.context = context; | |
this.next = this.prev = null; | |
} | |
/** | |
* Minimal Signal interface modeled against the js-signals | |
* interface. | |
*/ | |
function Signal() { | |
this._head = this._tail = undefined; | |
} | |
Signal.mixin({ | |
/** | |
* Return a list of assigned event listeners. | |
* | |
* @param {Boolean} exists We only need to know if there are listeners. | |
* @returns {Array|Boolean} | |
* @api public | |
*/ | |
listeners: function(exists) { | |
var node = this._head; | |
if (exists) { return !!node; } | |
var ee = []; | |
while (node) { | |
ee.push(node.fn); | |
node = node.next; | |
} | |
return ee; | |
}, | |
/** | |
* Emit an event to all registered event listeners. | |
* | |
* @returns {Boolean} Indication if we've emitted an event. | |
* @api public | |
*/ | |
dispatch: function() { | |
var node = this._head; | |
if (!node) { return false; } | |
while (node) { | |
node.fn.apply(node.context, arguments); | |
node = node.next; | |
} | |
return true; | |
}, | |
/** | |
* Register a new EventListener. | |
* | |
* @param {Functon} fn Callback function. | |
* @param {Mixed} context The context of the function. | |
* @api public | |
*/ | |
add: function(fn, context) { | |
var node = new Node(fn, context || this); | |
if (!this._head) { | |
this._head = node; | |
this._tail = node; | |
} else { | |
this._tail.next = node; | |
node.prev = this._tail; | |
this._tail = node; | |
} | |
return this; | |
}, | |
/** | |
* Remove event listeners. | |
* | |
* @param {Function} fn The listener that we need to find. | |
* @param {Mixed} context Only remove listeners matching this context. | |
* @api public | |
*/ | |
remove: function(fn, context) { | |
if (!fn) { return this.removeAll(); } // maybe change this | |
var node = this._head; | |
while (node) { | |
if (node.fn === fn && (!context || node.context === context)) { | |
this._removeNode(node); | |
} | |
node = node.next; | |
} | |
return this; | |
}, | |
/** | |
* Remove all event listeners with the matching contexts. | |
* | |
* @param {Mixed} context Remove all listeners matching this context. | |
* @api public | |
*/ | |
removeAllWithContext: function(context) { | |
var node = this._head; | |
while (node) { | |
if (node.context === context) { | |
this._removeNode(node); | |
} | |
node = node.next; | |
} | |
return this; | |
}, | |
_removeNode: function(node) { | |
if (node === this._head) { // first node | |
this._head = node.next; | |
if (!this._head){ | |
this._tail = null; | |
} else { | |
this._head.prev = null; | |
} | |
} else if (node === this._tail) { // last node | |
this._tail = node.prev; | |
this._tail.next = null; | |
} else { // middle | |
node.prev.next = node.next; | |
node.next.prev = node.prev; | |
} | |
}, | |
/** | |
* Remove all listeners. | |
* | |
* @api public | |
*/ | |
removeAll: function() { | |
var node = this._head; | |
if (!node) { return this; } | |
this._head = this._tail = null; | |
return this; | |
} | |
}); |
This file contains hidden or 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
/* | |
_ _ | |
| | (_) | |
| |_ _ ___ | |
| __| | / __| | |
| |_ _| \__ \ | |
\__(_) |___/ | |
_/ | | |
|__/ | |
t.js | |
a micro-templating framework in ~400 bytes gzipped | |
@author Jason Mooberry <[email protected]> | |
@license MIT | |
@version 0.1.0 | |
*/ | |
(function() { | |
var blockregex = /\{\{(([@!]?)(.+?))\}\}(([\s\S]+?)(\{\{:\1\}\}([\s\S]+?))?)\{\{\/\1\}\}/g, | |
valregex = /\{\{([=%])(.+?)\}\}/g; | |
function t(template) { | |
this.t = template; | |
} | |
function scrub(val) { | |
return new Option(val).innerHTML.replace(/"/g,"""); | |
} | |
function get_value(vars, key) { | |
var parts = key.split('.'); | |
while (parts.length) { | |
if (!(parts[0] in vars)) { | |
return false; | |
} | |
vars = vars[parts.shift()]; | |
} | |
return vars; | |
} | |
function render(fragment, vars) { | |
return fragment | |
.replace(blockregex, function(_, __, meta, key, inner, if_true, has_else, if_false) { | |
var val = get_value(vars,key), temp = "", i; | |
if (!val) { | |
// handle if not | |
if (meta == '!') { | |
return render(inner, vars); | |
} | |
// check for else | |
if (has_else) { | |
return render(if_false, vars); | |
} | |
return ""; | |
} | |
// regular if | |
if (!meta) { | |
return render(if_true, vars); | |
} | |
// process array/obj iteration | |
if (meta == '@') { | |
// store any previous vars | |
// reuse existing vars | |
_ = vars._key; | |
__ = vars._val; | |
for (i in val) { | |
if (val.hasOwnProperty(i)) { | |
vars._key = i; | |
vars._val = val[i]; | |
temp += render(inner, vars); | |
} | |
} | |
vars._key = _; | |
vars._val = __; | |
return temp; | |
} | |
}) | |
.replace(valregex, function(_, meta, key) { | |
var val = get_value(vars,key); | |
if (val || val === 0) { | |
return meta == '%' ? scrub(val) : val; | |
} | |
return ""; | |
}); | |
} | |
t.prototype.render = function (vars) { | |
return render(this.t, vars); | |
}; | |
window.t = t; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment