Created
March 1, 2013 02:08
-
-
Save DrSammyD/5061957 to your computer and use it in GitHub Desktop.
jquery plugin that provides a way to notify parents of different types of callbacks defined by the plugin user
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
(($, window) -> | |
hasArgs = () -> arguments.length > 0 | |
noArgs = () -> arguments.length == 0 | |
class DomCallbacks | |
###* | |
* Defines the jQuery functions to create callbacks for, and which type of callback they contain | |
* @type {defaults} | |
* @properties {array of jQuery function names, and test to determine if the callback | |
* should be run based on input to the jQuery function, passed the same arguments that the jQuery | |
* function is} | |
### | |
defaults: | |
Mutate: | |
jqfuncs: ["addClass","append","appendTo","attr","clone","css","detach","empty","hasClass","height","html","innerHeight","innerWidth","insertAfter","insertBefore","offset","outerHeight","outerWidth","position","prepend","prependTo","prop","remove","removeAttr","removeClass","removeProp","replaceAll","replaceWith","scrollLeft","scrollTop","text","toggleClass","unwrap","val","width","wrap","wrapAll","wrapInner"] | |
defaultCheck: hasArgs | |
Look: | |
jqfuncs:["addClass","after",'append',"appendTo","attr","before","clone","css","detach","empty","hasClass","height","html","innerHeight","innerWidth","insertAfter","insertBefore","offset","outerHeight","outerWidth","position","prepend","prependTo","prop","remove","removeAttr","removeClass","removeProp","replaceAll","replaceWith","scrollLeft","scrollTop","text","toggleClass","unwrap","val","width","wrap","wrapAll","wrapInner"] | |
defaultCheck: noArgs | |
constructor: (options) -> | |
@categories = $.extend({}, @defaults, options) | |
originals: {} | |
###* | |
* Creates a function in jQuery's function object by replacing the name with a wrapper function | |
* and then calling the original function, and has the new function call each category of callback | |
* for the starting element and it's parents | |
* @param {string} name the name/key of the function being replaced | |
* @param {string} categories the type of callback that the function should notify | |
### | |
addCallback: (name, categories) -> | |
pairs = (obj) -> | |
pairs = [] | |
for key of obj | |
if (hasOwnProperty.call(obj, key)) | |
pairs.push([key, obj[key]]) | |
pairs | |
if !@originals[name]? | |
@originals[name] = $.fn[name] | |
_this = @ | |
categories = $.grep pairs(categories), (pair) -> | |
$.grep(pair[1].jqfuncs, (val) -> val.name == name || val == name).length > 0 | |
###* | |
* The actual wrapper function being created | |
* @return {object} returns the original functions return | |
### | |
$.fn[name] = () -> | |
options = {args: arguments} | |
ittr = [] | |
if !$.fn[name].peek | |
ittrArray = for category in categories | |
key = category[0] | |
val = category[1] | |
funcs = ($.grep(val.jqfuncs, (checking) -> checking.name == name || checking == name)).slice(0,1)[0].check | |
{key:key, val: val ,funcs:funcs} | |
for ittr in ittrArray | |
if !ittr.funcs? | |
ittr.funcs = ittr.val.defaultCheck | |
if !ittr.funcs? or ittr.funcs.apply(@,arguments) | |
@["pre"+ittr.key](null, options) | |
@parents()["pre"+ittr.key](null, options) | |
funcRet = _this.originals[name].apply(@, arguments) | |
options.funcRet = funcRet | |
if !$.fn[name].peek | |
for ittr in ittrArray | |
if !ittr.funcs? | |
ittr.funcs = ittr.val.defaultCheck | |
if !ittr.funcs? or ittr.funcs.apply(@,arguments) | |
@["on"+ittr.key](null, options) | |
@parents()["on"+ittr.key](null, options) | |
funcRet | |
$.fn[name].peek = false | |
###* | |
* restores the original function to it's property in the jQuery function object | |
* @param {string} name key used to find function to restore | |
* @return {[type]} [description] | |
### | |
removeCallback: (name) -> | |
if @originals[name]? | |
$.fn[name] = @originals[name] | |
delete @originals[name] | |
###* | |
* Creates a jQuery plugin capable of subscribing to and calling callbacks | |
* for each node | |
* @param {string} precedence names the function to run before or after the subscripton function | |
* @param {string} category the name of the type of | |
* @return {function} returns the function capable of setting and running callbacks for individual elements | |
### | |
createCallbackPlugin = (precedence, category) -> | |
###* | |
* A jQuery plugin which creates a sets callbacks for elements and calls them if none are passed in | |
* @param {function} callback the callback to be set (optional) | |
* @param {object} options options to be sent to the callback, set by the trigger function | |
* @return {jQuery} returns jQuery object for chaining | |
### | |
return (callback, options) -> | |
@each (i, el) -> | |
if callback? | |
if !el['domCallbacks']? | |
el['domCallbacks'] = {} | |
if !el['domCallbacks']['_'+precedence+category]? | |
el['domCallbacks']['_'+precedence+category] = [] | |
el['domCallbacks']['_'+precedence+category].push callback | |
else | |
if el['domCallbacks']? && el['domCallbacks']['_'+precedence+category]? | |
for cb in el['domCallbacks']['_'+precedence+category] | |
cb(options, el) | |
@ | |
@ | |
domCallbacks = new DomCallbacks() | |
###* | |
* This creates each function inside of jQuery capable of setting and running callbacks on | |
* individual elements. | |
* @param {[type]} options [description] | |
* @return {[type]} [description] | |
### | |
$.extend createDomCallbacks: (options) -> | |
$.extend({}, domCallbacks.categories, options) | |
categoryFunctions = {} | |
for key, category of domCallbacks.categories | |
categoryFunctions['pre'+key] = createCallbackPlugin('pre',key) | |
categoryFunctions['on'+key] = createCallbackPlugin('on',key) | |
$.extend $.fn, categoryFunctions | |
for key, category of domCallbacks.categories | |
for val in category.jqfuncs | |
domCallbacks.addCallback( (if val.name then val.name else val) , domCallbacks.categories) | |
###* | |
* removes any callbacks each element in the jquery object | |
* @param {object} options an object conatining keys for the type of callback to be removed (e.g. options = {Mutate: {}}) | |
* @return {[type]} returns jquery object for chaining | |
### | |
$.extend $.fn, removeDomCallbacks: (options) -> | |
@each (i, el) -> | |
if el['domCallbacks']? | |
if !options? | |
delete el['domCallbacks'] | |
for category of options | |
delete el['domCallbacks']["_pre"+category] | |
delete el['domCallbacks']["_on"+category] | |
@ | |
@ | |
###* | |
* turns off all callbacks for performing actions without notifying up the dom | |
* @return {jQuery} for chaining | |
### | |
$.extend $.fn, peek: () -> | |
for key,val of domCallbacks.originals | |
$.fn[key].peek = true | |
@each (i, el) -> | |
@ | |
@ | |
###* | |
* turns off all callbacks for performing actions without notifying up the dom | |
* @return {jQuery} for chaining | |
### | |
$.extend $.fn, unpeek: () -> | |
for key,val of domCallbacks.originals | |
$.fn[key].peek = false | |
@each (i, el) -> | |
@ | |
@ | |
) @jQuery, @ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment