generators/jelly/templates/javascripts/jelly.js in btakita-jelly-0.6.1 vs generators/jelly/templates/javascripts/jelly.js in btakita-jelly-0.8.5

- old
+ new

@@ -1,97 +1,151 @@ /** * Jelly. a sweet unobtrusive javascript framework * for jQuery and Rails * - * version 0.5 + * version 0.8.5 * * Copyright (c) 2009 Pivotal Labs * Licensed under the MIT license. * * * Date: 2009-07-20 9:50:50 (Mon, 20 Jul 2009) * */ -if(!window.Jelly) Jelly = new Object(); -Jelly.all = {}; - -Jelly.add = function(name) { - var page = new Jelly.Page(name); - for(var i=1; i < arguments.length; i++) { - $.extend(page, arguments[i]); +if (!window.Jelly) Jelly = new Object(); +if (!Function.prototype.bind) { + Function.prototype.bind = function(object) { + var self = this; + return function() { + return self.apply(object, arguments); + } } - return page; -}; +} +$.extend(Jelly, { + init: function() { + this.observers = []; + this.attach = this.Observers.attach; + this.notifyObservers = this.Observers.notify; + this.Pages.init(); + }, -var page; -Jelly.activatePage = function(controllerName, actionName) { - page = Jelly.all[controllerName] || new Jelly.Page(controllerName); - $(document).ready(function(){ - Jelly._activatePage(actionName); - }); -}; + Observers: { + attach: function() { + if (this == Jelly) { + return Jelly.Observers.attach.apply(this.observers, arguments); + } + for (var i = 0; i < arguments.length; i++) { + var definitionOrComponent = arguments[i]; + var observer; + if (definitionOrComponent.component) { + var component = Jelly.Observers.evaluateComponent(definitionOrComponent.component); + if (component.init) { + observer = component.init.apply(component, definitionOrComponent.arguments) || component; + } else { + observer = component; + } + } else { + observer = Jelly.Observers.evaluateComponent(definitionOrComponent); + } + this.push(observer); + } + }, -Jelly._activatePage = function(actionName){ - Jelly.initComponents(); - if(page.all) page.all(); - if(page[actionName]) page[actionName].call(page); - page.loaded = true; -}; + evaluateComponent: function(component) { + return (typeof component == "string") ? eval(component) : component; + }, -Jelly.initComponents = function() { - $.protify(page.components).each(function(componentAndArgs) { - var component = componentAndArgs[0]; - var args = componentAndArgs[1] || []; - if(component.init) component.init.apply(component, args); - }); -}; + notify: function(callbacks) { + if (this == Jelly) { + return Jelly.Observers.notify.apply(this.observers, arguments); + } + if (!$.isArray(callbacks)) { + callbacks = [callbacks]; + } -Jelly.notifyObservers = function(params) { - var context = params.on ? eval(params.on) : page; - if(context[params.method]) { - context[params.method].apply(context, params.arguments); - } - $.protify(page.components).each(function(componentAndArgs) { - var component = componentAndArgs[0]; - if(component[params.method]) { - component[params.method].apply(component, params.arguments); - } - }); -}; + var observers = this.slice(0); + for (var i = 0; i < callbacks.length; i++) { + var callback = callbacks[i]; -Jelly.Page = function(name) { - this.name = name; - this.components = []; - Jelly.all[name] = this; -}; + // Deprecate 'on' in favor of making each page action a Component. + if (callback.on) { + var additionalObserver = eval(callback.on); + if (observers.indexOf(additionalObserver) == -1) { + observers.push(additionalObserver); + } + } -Jelly.Page.prototype.loaded = false; -Jelly.Page.prototype.all = function() { -}; -Jelly.Page.prototype.documentHref = function() { - return document.location.href; -}; -Jelly.Page.prototype.on_redirect = function(location){ - top.location.href = location; -}; + if (callback.method) { + for (var j = 0; j < observers.length; j++) { + var observer = observers[j]; + if (observer[callback.method]) { + if (observer.detach && observer.detach()) { + Jelly.Observers.garbageCollectObserver.call(this, observer); + } else { + observer[callback.method].apply(observer, callback.arguments); + } + } + } + } -Jelly.Page.prototype.attach = function(component, args) { - var methodNames = []; - for(var methodName in component.pageMixin) { - methodNames.push(methodName); - } - var self = this; - $.protify(methodNames).each(function(methodName) { - // TODO: is anybody using these before_/after_ hooks? if not, delete them and use components as observers - self[methodName] = function() { - if(this['before_' + methodName]) { - this['before_' + methodName].apply(this, arguments); + if (callback.attach) { + Jelly.Observers.attach.apply(this, callback.attach); + } } - var returnValue = component.pageMixin[methodName].apply(this, arguments); - if(this['after_' + methodName]) { - this['after_' + methodName].apply(this, arguments); + }, + + garbageCollectObserver: function(observer) { + var index = this.indexOf(observer); + if (index > -1) { + Jelly.Observers.remove.call(this, index, index + 1); } - return returnValue; - }; - }); - page.components.push([component, args]); -}; + }, + + remove: function(from, to) { + var rest = this.slice((to || from) + 1 || this.length); + this.length = from < 0 ? this.length + from : from; + return this.push.apply(this, rest); + } + }, + + Pages: { + init: function() { + this.all = {}; + Jelly.all = this.all; // Deprecated + }, + + add: function(name) { + var page = new Jelly.Page.Constructor(name); + for (var i = 1; i < arguments.length; i++) { + $.extend(page, arguments[i]); + } + return page; + } + }, + + Page: { + init: function(controllerName, actionName) { + var page = Jelly.Pages.all[controllerName] || new Jelly.Page.Constructor(controllerName); + window.page = page; + if (page.all) page.all(); + if (page[actionName]) page[actionName].call(page); + page.loaded = true; + return page; + }, + Constructor: function(name) { + this.loaded = false; + this.documentHref = Jelly.Location.documentHref; + + this.name = name; + Jelly.Pages.all[name] = this; + } + }, + + Location: { + on_redirect: function(location) { + top.location.href = location; + } + } +}); +Jelly.add = Jelly.Pages.add; // Deprecated + +Jelly.init();