steal.plugins('jquery/class', 'jquery/lang', 'jquery/event/destroyed').then(function ($){ var bind = function (el, ev, callback){ var wrappedCallback; if (ev.indexOf(">") === 0) { ev = ev.substr(1); wrappedCallback = function (event){ if (_AN_Read_target("target", event) === el) { callback.apply(this, arguments); } else { event.handled = null ; } } ; } $(el).bind(ev, wrappedCallback || callback); return function (){ $(el).unbind(ev, wrappedCallback || callback); el = ev = callback = wrappedCallback = null ; } ; } , delegate = function (el, selector, ev, callback){ $(el).delegate(selector, ev, callback); return function (){ $(el).undelegate(selector, ev, callback); el = ev = callback = selector = null ; } ; } , binder = function (el, ev, callback, selector){ return selector? delegate(el, selector, ev, callback): bind(el, ev, callback); } , shifter = function shifter(cb){ return function (){ return cb.apply(null , [$(this)] .concat(Array.prototype.slice.call(arguments, 0))); } ; } , dotsReg = /\./g, controllersReg = /_?controllers?/ig, underscoreAndRemoveController = function (className){ return $.String.underscore(_AN_Call_replace("replace", _AN_Call_replace("replace", className, dotsReg, '_'), controllersReg, "")); } , actionMatcher = /[^\w]/, eventCleaner = /^(>?default\.)|(>)/, parameterReplacer = /\{([^\}]+)\}/g, breaker = /^(?:(.*?)\s)?([\w\.\:>]+)$/, basicProcessor; $.Class.extend("jQuery.Controller", { init: function (){ if (!this.shortName || this.fullName == "jQuery.Controller") { return ; } this._fullName = underscoreAndRemoveController(this.fullName); this._shortName = underscoreAndRemoveController(this.shortName); var controller = this, pluginname = this._fullName, funcName, forLint; if (!$.fn[pluginname]) { $.fn[pluginname] = function (options){ var args = $.makeArray(arguments), isMethod = typeof options == "string" && $.isFunction(controller.prototype[options]), meth = args[0]; this.each(function (){ var controllers = $.data(this, "controllers"), plugin = controllers && controllers[pluginname]; if (plugin) { if (isMethod) { plugin[meth].apply(plugin, args.slice(1)); } else { plugin.update.apply(plugin, args); } } else { controller.newInstance.apply(controller, [this] .concat(args)); } } ); return this; } ; } if (!$.isArray(this.listensTo)) { throw "listensTo is not an array in " + this.fullName } this.actions = { } ; for (funcName in this.prototype){ if (!$.isFunction(this.prototype[funcName])) { continue ; } if (this._isAction(funcName)) { this.actions[funcName] = this._getAction(funcName); } } if (this.onDocument) { forLint = new controller(document.documentElement); } } , hookup: function (el){ return new this(el); } , _isAction: function (methodName){ if (actionMatcher.test(methodName)) { return true ; } else { var cleanedEvent = _AN_Call_replace("replace", methodName, eventCleaner, ""); return $.inArray(cleanedEvent, this.listensTo) > -1 || $.event.special[cleanedEvent] || $.Controller.processors[cleanedEvent]; } } , _getAction: function (methodName, options){ parameterReplacer.lastIndex = 0; if (!options && parameterReplacer.test(methodName)) { return null ; } var convertedName = options? _AN_Call_replace("replace", methodName, parameterReplacer, function (whole, inside){ return $.Class.getObject(inside, options).toString(); } ): methodName, parts = convertedName.match(breaker), event = parts[2], processor = this.processors[event] || basicProcessor; return { processor: processor, parts: parts} ; } , processors: { } , listensTo: [] } , { setup: function (element, options){ var funcName, ready, cls = this.Class; element = element.jquery? element[0]: element; this.element = $(element).addClass(cls._fullName); ($.data(element, "controllers") || $.data(element, "controllers", { } ))[cls._fullName] = this; this._bindings = [] ; this.options = $.extend($.extend(true , { } , cls.defaults), options); for (funcName in cls.actions){ ready = cls.actions[funcName] || cls._getAction(funcName, this.options); this._bindings.push(ready.processor(element, ready.parts[2], ready.parts[1], this.callback(funcName), this)); } this.called = "init"; var destroyCB = shifter(this.callback("destroy")); this.element.bind("destroyed", destroyCB); this._bindings.push(function (el){ destroyCB.removed = true ; $(element).unbind("destroyed", destroyCB); } ); return this.element; } , bind: function (el, eventName, func){ if (typeof el == 'string') { func = eventName; eventName = el; el = this.element; } return this._binder(el, eventName, func); } , _binder: function (el, eventName, func, selector){ if (typeof func == 'string') { func = shifter(this.callback(func)); } this._bindings.push(binder(el, eventName, func, selector)); return _AN_Read_length('length', this._bindings); } , delegate: function (element, selector, eventName, func){ if (typeof element == 'string') { func = eventName; eventName = selector; selector = element; element = this.element; } return this._binder(element, eventName, func, selector); } , update: function (options){ $.extend(this.options, options); } , destroy: function (ev){ if (this._destroyed) { throw this.Class.shortName + " controller instance has been deleted" } var self = this, fname = this.Class._fullName; this._destroyed = true ; this.element.removeClass(fname); $.each(this._bindings, function (key, value){ if ($.isFunction(value)) { value(self.element[0]); } } ); delete this._actions; var controllers = this.element.data("controllers"); if (controllers && controllers[fname]) { delete controllers[fname]; } $(this).triggerHandler("destroyed"); this.element = null ; } , find: function (selector){ return this.element.find(selector); } , _set_called: true } ); basicProcessor = function (el, event, selector, cb, controller){ var c = controller.Class; if (c.onDocument && !/^Main(Controller)?$/.test(c.shortName)) { selector = selector? "#" + c._shortName + " " + selector: "#" + c._shortName; } return binder(el, event, shifter(cb), selector); } ; var processors = $.Controller.processors, windowEvent = function (el, event, selector, cb){ return binder(window, _AN_Call_replace("replace", event, /window/, ""), shifter(cb)); } ; $.each("change click contextmenu dblclick keydown keyup keypress mousedown mousemove mouseout mouseover mouseup reset windowresize resize windowscroll scroll select submit dblclick focusin focusout load unload ready hashchange mouseenter mouseleave".split(" "), function (i, v){ processors[v] = basicProcessor; } ); $.each(["windowresize", "windowscroll", "load", "ready", "unload", "hashchange"] , function (i, v){ processors[v] = windowEvent; } ); processors.ready = function (el, event, selector, cb){ $(shifter(cb)); } ; $.fn.mixin = function (){ var controllers = $.makeArray(arguments), forLint; return this.each(function (){ for (var i = 0; i < _AN_Read_length("length", controllers); i++ ){ forLint = new controllers[i](this); } } ); } ; var isAControllerOf = function (instance, controllers){ for (var i = 0; i < _AN_Read_length("length", controllers); i++ ){ if (typeof controllers[i] == 'string'? instance.Class._shortName == controllers[i]: instance instanceof controllers[i]) { return true ; } } return false ; } ; $.fn.controllers = function (){ var controllerNames = $.makeArray(arguments), instances = [] , controllers; this.each(function (){ controllers = $.data(this, "controllers"); if (!controllers) { return ; } for (var cname in controllers){ var c = controllers[cname]; if (!_AN_Read_length("length", controllerNames) || isAControllerOf(c, controllerNames)) { instances.push(c); } } } ); return instances; } ; $.fn.controller = function (controller){ return this.controllers.apply(this, arguments)[0]; } ; } );