From: Ben Beltran Date: Wed, 18 Feb 2015 04:26:20 +0000 (-0600) Subject: Adds new assets for dynamic headers X-Git-Url: https://git.r.bdr.sh/rbdr/r.bdr.sh/commitdiff_plain/0982546d752f52084c5956ea937db36e161ac2e3?ds=inline Adds new assets for dynamic headers --- diff --git a/jekyll/js/unlimited_pizza.js b/jekyll/js/unlimited_pizza.js new file mode 100644 index 0000000..2dc7a7c --- /dev/null +++ b/jekyll/js/unlimited_pizza.js @@ -0,0 +1,56 @@ +'use strict'; + +Class("UnlimitedPizza").inherits(Widget)({ + + /** + * Gets instance, creates it if not available. + */ + instance : function getInstance(config) { + if (!this._mainInstance) { + this._mainInstance = new this(config); + } + return this._mainInstance; + }, + + prototype : { + _loaded : false, + + init : function (config) { + Widget.prototype.init.call(this, config) + + this._bindInternalEvents(); + }, + + _bindInternalEvents : function bindInternalEvents() { + this.bind('activate', this._onActivate.bind(this)); + }, + + _onActivate : function _activate() { + // If this is the first time activating it... then load + if (!this._loaded) { + this._load(); + } + }, + + /* + * Loads everything. + */ + _load : function _load() { + + // Melty cheese is our header image widget. + this._loadMeltyCheese(); + }, + + _loadMeltyCheese : function() { + this.element.find('.post-image').each(function (i, headerElement) { + + // Create and activate + this.appendChild(new UnlimitedPizza.MeltyCheese({ + element : $(headerElement), + name : 'header-' + i + })); + this['header-' + i].activate(); + }.bind(this)); + } + } +}); diff --git a/jekyll/js/unlimited_pizza/melty_cheese.js b/jekyll/js/unlimited_pizza/melty_cheese.js new file mode 100644 index 0000000..9c8a1e8 --- /dev/null +++ b/jekyll/js/unlimited_pizza/melty_cheese.js @@ -0,0 +1,89 @@ +'use strict'; + +Class(UnlimitedPizza, "MeltyCheese").inherits(Widget)({ + prototype : { + min : 60, // min height of the element + max : 480, // max height of the element + minThreshold : 200, // distance from bottom before we start + maxThreshold : 500, // distance from bottom before we stop + _loaded : false, + + init : function (config) { + Widget.prototype.init.call(this, config) + + this._bindInternalEvents(); + }, + + _bindInternalEvents : function bindInternalEvents() { + this.bind('activate', this._onActivate.bind(this)); + this.bind('deactivate', this._onDeactivate.bind(this)); + }, + + _onActivate : function _activate() { + // If this is the first time activating it... then load + if (!this._loaded) { + this._load(); + } + }, + + _onDeactivate : function _deactivate() { + this._unload(); + }, + + /* + * Loads everything. + */ + _load : function _load() { + this._bindEvents(); + + this.image = this.element.find('img') + }, + + _unload : function _unload() { + this._loaded = false; + this._unbindEvents(); + }, + + _bindEvents : function bindEvents() { + $(window).on('scroll', this._onScroll.bind(this)); + $(window).on('resize', this._onScroll.bind(this)); + }, + + _unbindEvents : function unbindEvents() { + $(window).off('scroll'); + $(window).off('resize'); + }, + + /* Listeners beyond */ + + _onScroll : function onScroll() { + var documentTop, documentBottom, elementTop, diff, height; + + + documentTop = $(window).scrollTop(); + documentBottom = documentTop + $(window).height(); + elementTop = this.element.offset().top; + diff = documentBottom - elementTop; + + this.max = this.image.height(); + this.min = this.max / 10; + + diff -= this.minThreshold; + + height = diff * this.max / this.maxThreshold; + + if (height < this.min) { + height = this.min; + } + + if (height > this.max) { + height = this.max; + } + + console.log("I, ", this.name, "should be ", height); + + this.element.height(height); + }, + + } +}); diff --git a/jekyll/js/unlimitedpizza.js b/jekyll/js/unlimitedpizza.js new file mode 100644 index 0000000..b2bf6ab --- /dev/null +++ b/jekyll/js/unlimitedpizza.js @@ -0,0 +1,28 @@ +Class("Unlimitedpizza").inherits(Widget)({ + prototype : { + _loaded : false, + + init : function (config) { + Widget.constructor.prototype.init.call(this, config) + + this._bindInternalEvents(); + }, + + _bindInternalEvents : function bindInternalEvents() { + this.bind('activate', this._onActivate.bind(this)); + this.bind('deactivate', this._onDeactivate.bind(this)); + }, + + _onActivate : function _activate() { + if (!this._loaded) { + this._load(); + } + }, + + _load : function _load() { + var meltyCheese; + + meltyCheese = new Unlimitedpizza.MeltyCheese + } + } +}); diff --git a/jekyll/js/vendor/neon/neon.js b/jekyll/js/vendor/neon/neon.js new file mode 100644 index 0000000..bf0b94c --- /dev/null +++ b/jekyll/js/vendor/neon/neon.js @@ -0,0 +1,234 @@ + +if (typeof global === "undefined") { + global = window; +} + +global.Interface = function Interface(nameOrNameSpace, name) { + var nameSpace, interfaceName, factory; + nameSpace = (nameOrNameSpace && name) ? nameOrNameSpace : this; + interfaceName = (nameOrNameSpace && name) ? name : + (nameOrNameSpace) ? nameOrNameSpace : 'interface' + Math.random().toString(); + factory = function(definition) { + definition.isInterface = true; + definition.name = interfaceName; + nameSpace[interfaceName] = definition; + return nameSpace[interfaceName]; + }; + return factory; +}; + +global.Module = function Module(nameOrNameSpace, name) { + var nameSpace, moduleName, factory, newModule; + + nameSpace = (nameOrNameSpace && name) ? nameOrNameSpace : this; + moduleName = (nameOrNameSpace && name) ? name : + (nameOrNameSpace) ? nameOrNameSpace : 'module' + Math.random().toString(); + + newModule = { + moduleName : moduleName, + prototype : {}, + __includedModules : [], + include : function(module) { + var property; + for (property in module) { + if (module.hasOwnProperty(property) + && property !== 'prototype' + && property !== 'isModule' + && property !== '__includedModules' + && property !== 'include' + && property !== 'moduleName') { + newModule[property] = module[property]; + } + } + + if (module.hasOwnProperty('prototype') && module.prototype) { + for (property in module.prototype) { + if (module.prototype.hasOwnProperty(property)) { + newModule.prototype[property] = module.prototype[property]; + } + } + } + else { + module.prototype = {}; + } + + this.__includedModules.push(module); + + return this; + } + } + + factory = function(definition){ + var property; + + newModule.isModule = true; + + for (property in definition) { + if (definition.hasOwnProperty(property) + && property !== 'prototype' + && property !== 'isModule' + && property !== '__includedModules' + && property !== 'include' + && property !== 'moduleName') { + newModule[property] = definition[property]; + } + } + + if (definition.hasOwnProperty('prototype') && definition.prototype) { + for (property in definition.prototype) { + if (definition.prototype.hasOwnProperty(property)) { + newModule.prototype[property] = definition.prototype[property]; + } + } + } + + nameSpace[moduleName] = newModule; + + return nameSpace[moduleName]; + }; + + factory.includes = function () { + for(var i = 0; i < arguments.length; i++){ + newModule.include(arguments[i]); + } + return factory; + }; + + return factory; +}; + +global.Class = function Class(classNameOrNameSpace, className) { + var nameSpace, newClass, classFactory; + nameSpace = (classNameOrNameSpace && className) ? classNameOrNameSpace : global; + className = (classNameOrNameSpace && className) ? className : + (classNameOrNameSpace) ? classNameOrNameSpace : 'class' + Math.random().toString(); + + newClass = function() { + if (this.init) { + this.init.apply(this, arguments); + } + }; + + newClass.__descendants = []; + newClass.__implementedInterfaces = []; + newClass.__includedModules = []; + newClass.className = className; + newClass.include = function(module) { + var property; + for (property in module) { + if (module.hasOwnProperty(property) + && property != 'prototype' + && property != 'constructor' + && property != 'isModule' + && property != 'superClass' + && property != 'include') { + newClass[property] = module[property]; + } + } + + if (module.hasOwnProperty('prototype') && module.prototype) { + for (property in module.prototype) { + if (module.prototype.hasOwnProperty(property)) { + newClass.prototype[property] = module.prototype[property]; + } + } + } else { + module.prototype = {}; + } + + newClass.__includedModules.push(module); + return this; + }; + + classFactory = function(classDefinition) { + var i, il, j, jl, property, classPrototype = classDefinition.prototype; + if (classPrototype) { + for (property in classPrototype) { + if (classPrototype.hasOwnProperty(property)) { + newClass.prototype[property] = classPrototype[property]; + } + } + delete classDefinition.prototype; + } + for (property in classDefinition) { + if (classDefinition.hasOwnProperty(property)) { + newClass[property] = classDefinition[property]; + } + } + + for (i = 0, il = newClass.__implementedInterfaces.length; i < il; i++) { + for (j = 0, jl = newClass.__implementedInterfaces[i].constructor.length; j < jl; j++) { + if (!newClass[ newClass.__implementedInterfaces[i].constructor[j] ]) { + console.log('must implement static ' + newClass.__implementedInterfaces[i].name); + break; + } + } + + if (newClass.__implementedInterfaces[i].hasOwnProperty('prototype') + && newClass.__implementedInterfaces[i].prototype) { + for (j = 0, jl = newClass.__implementedInterfaces[i].prototype.length; j < jl; j++) { + if (!newClass.prototype[newClass.__implementedInterfaces[i].prototype[j]]) { + console.log('must implement prototype ' + newClass.__implementedInterfaces[i].name); + break; + } + } + } + } + + try { + if (Li && Li.ObjectSpy && Li.Spy) { + newClass.__objectSpy = new Li.ObjectSpy(); + newClass.__objectSpy.spy(newClass); + newClass.__objectSpy.spy(newClass.prototype); + } + } catch (error) {} + + nameSpace[className] = newClass; + return newClass; + }; + + classFactory.inherits = function(superClass) { + var i, inheritedClass; + newClass.superClass = superClass; + if (superClass.hasOwnProperty('__descendants')) { + superClass.__descendants.push(newClass); + } + inheritedClass = function() { + }; + inheritedClass.prototype = superClass.prototype; + newClass.prototype = new inheritedClass(); + newClass.prototype.constructor = newClass; + + for (i in superClass) { + if (superClass.hasOwnProperty(i) + && i != 'prototype' + && i !== 'className' + && i !== 'superClass' + && i !== 'include' + && i != '__descendants') { + newClass[i] = superClass[i]; + } + } + + delete this.inherits; + return this; + }; + + classFactory.ensures = function(interfaces) { + for (var i = 0; i < arguments.length; i++) { + newClass.__implementedInterfaces.push(arguments[i]); + } + delete this.ensures; + return classFactory; + }; + + classFactory.includes = function() { + for (var i = 0; i < arguments.length; i++) { + newClass.include(arguments[i]); + } + return classFactory; + }; + + return classFactory; + +}; diff --git a/jekyll/js/vendor/neon/stdlib/bubbling_support.js b/jekyll/js/vendor/neon/stdlib/bubbling_support.js new file mode 100644 index 0000000..30e0f5d --- /dev/null +++ b/jekyll/js/vendor/neon/stdlib/bubbling_support.js @@ -0,0 +1,32 @@ +Module('BubblingSupport')({ + dispatch : function (type, data) { + data = data || {}; + var event = CustomEventSupport.prototype.dispatch.call(this, type, data); + if (event.isPropagationStopped === false) { + if (this.parent && this.parent.dispatch) { + data.target = event.target; + data.currentTarget = this.parent; + this.parent.dispatch(event.type, data); + } + } + return event; + }, + + prototype : { + dispatch : function (type, data) { + data = data || {}; + + var event = CustomEventSupport.prototype.dispatch.call(this, type, data); + + if (event.isPropagationStopped === false && event.bubbles === true) { + if (this.parent && this.parent.dispatch) { + data.target = event.target; + data.currentTarget = this.parent; + this.parent.dispatch(event.type, data); + } + } + + return event; + } + } + }); diff --git a/jekyll/js/vendor/neon/stdlib/custom_event.js b/jekyll/js/vendor/neon/stdlib/custom_event.js new file mode 100644 index 0000000..c3c033c --- /dev/null +++ b/jekyll/js/vendor/neon/stdlib/custom_event.js @@ -0,0 +1,37 @@ +Class('CustomEvent')({ + prototype : { + bubbles : true, + cancelable : true, + currentTarget : null, + timeStamp : 0, + target : null, + type : '', + isPropagationStopped : false, + isDefaultPrevented : false, + isImmediatePropagationStopped : false, + areImmediateHandlersPrevented : false, + init : function init(type, data) { + this.type = type; + if (typeof data !== 'undefined') { + for(var property in data) { + if (data.hasOwnProperty(property)) { + this[property] = data[property]; + } + } + } + }, + stopPropagation : function stopPropagation() { + this.isPropagationStopped = true; + }, + preventDefault : function preventDefault() { + this.isDefaultPrevented = true; + }, + stopImmediatePropagation : function stopImmediatePropagation() { + this.preventImmediateHandlers(); + this.stopPropagation(); + }, + preventImmediateHandlers : function preventImmediateHandlers() { + this.areImmediateHandlersPrevented = true; + } + } +}); diff --git a/jekyll/js/vendor/neon/stdlib/custom_event_support.js b/jekyll/js/vendor/neon/stdlib/custom_event_support.js new file mode 100644 index 0000000..fecbd71 --- /dev/null +++ b/jekyll/js/vendor/neon/stdlib/custom_event_support.js @@ -0,0 +1,180 @@ +Module('CustomEventSupport')({ + + eventListeners : null, + + bind : function(type, eventHandler) { + var found, i, listeners; + + if(!this.eventListeners) { + this.eventListeners = {}; + } + + if(!this.eventListeners[type]) { + this.eventListeners[type] = []; + } + + found = false; + + listeners = this.eventListeners[type]; + for (i = 0; i < listeners.length; i++) { + if (listeners[i] === eventHandler) { + found = true; + break; + } + } + + if(!found) { + this.eventListeners[type].push(eventHandler); + } + + return this; + }, + + unbind : function(type, eventHandler) { + var i, found, listeners; + + found = false; + + if(!this.eventListeners) { + this.eventListeners = {}; + } + + if(typeof eventHandler == 'undefined') { + this.eventListeners[type] = []; + } + + listeners = this.eventListeners[type]; + for (i = 0; i < listeners.length; i++) { + if(listeners[i] === eventHandler) { + found = true; + break; + } + } + + if(found) { + this.eventListeners[type].splice(i, 1); + } + + return this; + }, + + dispatch : function(type, data) { + var event, listeners, instance, i; + + if (this.eventListeners === null) { + this.eventListeners = {}; + } + + if (typeof data === 'undefined') { + data = {}; + } + + if (data.hasOwnProperty('target') === false) { + data.target = this; + } + + event = new CustomEvent(type, data); + listeners = this.eventListeners[type] || []; + instance = this; + + for (i = 0; i < listeners.length; i = i + 1) { + listeners[i].call(instance, event); + if (event.areImmediateHandlersPrevented === true) { + break; + } + } + + return event; + }, + + prototype : { + + eventListeners : null, + + bind : function(type, eventHandler) { + var found, i, listeners; + + if(!this.eventListeners) { + this.eventListeners = {}; + } + + if(!this.eventListeners[type]) { + this.eventListeners[type] = []; + } + + found = false; + + listeners = this.eventListeners[type]; + for (i = 0; i < listeners.length; i++) { + if(listeners[i] === eventHandler) { + found = true; + break; + } + } + + if(!found) { + this.eventListeners[type].push(eventHandler); + } + + return this; + }, + + unbind : function(type, eventHandler) { + var i, found, listeners; + + found = false; + i = 0; + + if(!this.eventListeners) { + this.eventListeners = {}; + } + + if(typeof eventHandler == 'undefined') { + this.eventListeners[type] = []; + } + + listeners = this.eventListeners[type]; + for (i = 0; i < listeners.length; i++) { + if(listeners[i] == eventHandler) { + found = true; + break; + } + } + + if(found) { + this.eventListeners[type].splice(i, 1); + } + + return this; + }, + + dispatch : function(type, data) { + var event, listeners, instance, i; + + if (this.eventListeners === null) { + this.eventListeners = {}; + } + + if (typeof data === 'undefined') { + data = {}; + } + + if (data.hasOwnProperty('target') === false) { + data.target = this; + } + + event = new CustomEvent(type, data); + listeners = this.eventListeners[type] || []; + instance = this; + + for (i = 0; i < listeners.length; i = i + 1) { + listeners[i].call(instance, event); + if (event.areImmediateHandlersPrevented === true) { + break; + } + } + + return event; + } + } +}); diff --git a/jekyll/js/vendor/neon/stdlib/index.js b/jekyll/js/vendor/neon/stdlib/index.js new file mode 100644 index 0000000..862193b --- /dev/null +++ b/jekyll/js/vendor/neon/stdlib/index.js @@ -0,0 +1,7 @@ +// This file is node only +if(typeof require !== 'undefined'){ + require('./custom_event'); + require('./custom_event_support'); + require('./node_support'); + require('./bubbling_support'); +} diff --git a/jekyll/js/vendor/neon/stdlib/node_support.js b/jekyll/js/vendor/neon/stdlib/node_support.js new file mode 100644 index 0000000..b1e9473 --- /dev/null +++ b/jekyll/js/vendor/neon/stdlib/node_support.js @@ -0,0 +1,123 @@ +Module('NodeSupport')({ + prototype : { + parent : null, + + children : [], + + appendChild : function(child) { + if(child.parent) { + child.parent.removeChild(child); + } + + if(!this.hasOwnProperty('children')) { + this.children = []; + } + + this.children.push(child); + this[child.name] = child; + child.setParent(this); + return child; + }, + + insertBefore : function (child, beforeChild) { + var position; + + if (child.parent) { + child.parent.removeChild(child); + } + + if (!this.hasOwnProperty('children')) { + this.children = []; + } + + if (typeof beforeChild === 'undefined') { + this.appendChild(child); + } else { + position = this.children.indexOf(beforeChild); + this.children.splice(position, 0, child); + + this[child.name] = child; + child.setParent(this); + } + + return child; + + }, + + insertChild : function(child, position) { + console.warn('NodeSupport insertChild method is deprecated, try insertBefore'); + + if (child.parent) { + child.parent.removeChild(child); + } + + if (!this.hasOwnProperty('children')) { + this.children = []; + } + + if (typeof position == 'undefined') { + this.children.push(child); + this[child.name] = child; + child.setParent(this); + return child; + } + + this.children.splice(position, 0, child); + this[child.name] = child; + child.setParent(this); + return child; + }, + + removeChild : function (child) { + var position = this.children.indexOf(child); + + if (position !== -1) { + this.children.splice(position, 1); + delete this[child.name]; + child.parent = null; + } + + return child; + }, + + setParent : function (parent) { + this.parent = parent; + return this; + }, + + getDescendants : function () { + var nodes = []; + this.children.forEach(function (node) { + nodes.push(node); + }); + this.children.forEach(function (node) { + nodes = nodes.concat(node.getDescendants()); + }); + return nodes; + }, + + getPreviousSibling : function () { + if (typeof this.parent === 'undefined') { + return; + } + + if (this.parent.children[0] === this) { + return; + } + + return this.parent.children[ this.parent.children.indexOf(this) - 1 ]; + }, + + getNextSibling : function () { + if (typeof this.parent === 'undefined') { + return; + } + + if (this.parent.children[ this.parent.children.length - 1 ] === this) { + return; + } + + return this.parent.children[ this.parent.children.indexOf(this) + 1 ]; + } + } +}); diff --git a/jekyll/js/vendor/neon/stdlib/widget.js b/jekyll/js/vendor/neon/stdlib/widget.js new file mode 100644 index 0000000..2ee6355 --- /dev/null +++ b/jekyll/js/vendor/neon/stdlib/widget.js @@ -0,0 +1,328 @@ +/** +Base Class from which almost all widgets are based overall the project + +The main idea behind constructing a new widget toolkit instead of using one of the many high quality widget +toolkits avaliable is that we considered that currently, no widget system provides all the features that where +required for this project. + +Features of the widget system +* A custom and easy to handle event binding, dispatching and manipulation, with some sort of bubbling support +* A module system which we can use to include specific behaviour to any widget and reuse the code where needed +* A tree structure support for the widgets that the event system could bubble, and that also serves as +* A navigation system. +* The widgets must be able to be grouped to form more complex widgets +* Remove the complexity of DOM manipulation and handling +* A way to wrap widgets at our convenience to reuse widgets avaliable and make them comly to our needs +without the need to hack those widgets, that would force us to maintain the new versions of those widgets +and that is a very complex task when widgets become so complex. +* A widget system that would allow us to start wrapping some widgets for a fast start and later code our own widgets +at will. +* expose a consistent API that allow us to choose the use of widgets by API calls and user interaction at will and with the same +clearance and capacity +* an easy way to allow subclasing widgets +* an easy way to provide new html, class, and css for a specific instance of a widget that would remove us the need +to create complex inheritance structures that are hard to maintain. + +Usage Example. + +The most basic usage of a widget is to simply create an instance and render it at a target element +in this case body +var myWidgetInstance = new Breezi.Widget(); +myWidgetInstance.render(document.body); + +like this widget does renders does not display anything so lets give it something to display first +var myWidgetInstance = new Breezi.Widget(); +myWidgetInstance.element.html('Im a simple widget'); +myWidgetInstance.render(document.body); + +this reveals that internally every widget has an element property that is initialized by default to a jQuery Instance +this allow easy DOM manipulation, animation and operations handled by a high quality third party library. +@class Widget +@namespace Breezi +@inlcudes CustomEventSupport +@includes NodeSupport +@dependency Neon +@dependency CustomEventSupport +@dependency NodeSupport +**/ +Class('Widget').includes(CustomEventSupport, NodeSupport)({ + + /** + The default html for the widget, at the most simple case this is just a div. + @name HTML + @attribute_type CONSTANT + @type String + */ + HTML : '
', + + /** + the widget container default class for all widgets is widget + @name ELEMENT_CLASS + @constant + @type String + **/ + ELEMENT_CLASS : 'widget', + + /** + @property prototype + @type Object + **/ + prototype : { + /** + Holds the active status of the widget + By default all widgets are deactivated waiting + for an action to activate it. + @property active [Boolean] (false) + **/ + active : false, + + /** + Holds the disabled status of the widget + By default all widgets are enabled and only by + API could be disabled. + @property disabled [Boolean] (false) + **/ + disabled : false, + + __destroyed : false, + + init : function init(config) { + var property; + + Object.keys(config || {}).forEach(function (propertyName) { + this[propertyName] = config[propertyName]; + }, this); + + if (this.element == null) { + this.element = $(this.constructor.HTML.replace(/\s\s+/g, '')); + this.element.addClass(this.constructor.ELEMENT_CLASS); + } + + if (this.hasOwnProperty('className') === true) { + this.element.addClass(this.className); + } + }, + + /** + implementation of the activate method, when you need an override, do it + over this method instead of doing it on activate + @property _activate [Function] + @return undefined [undefined] + **/ + _activate : function _activate() { + this.active = true; + this.element.addClass('active'); + }, + + /** + Public activation method for widget, you can listen to this event + to take some other actions, but the most important part of this + method is that it runs its default action, (its activation) + this method uses _activate as its implementation to maintain + the events order intact. + @property activate [Function] + @method + @dispatch beforeActivate + @dispatch activate + @return this [Widget] + **/ + activate : function activate() { + if (this.__destroyed === true) { + console.warn('calling on destroyed object'); + } + this.dispatch('beforeActivate'); + this._activate(); + this.dispatch('activate'); + return this; + }, + + /** + deactivation implementation + this is the oposite of activation method and as such it must be + treated as important as that. + @property _deactivate [Function] + @method + @return undefined [undefined] + **/ + _deactivate : function _deactivate() { + this.active = false; + this.element.removeClass('active'); + }, + + /** + Public deactivation method for widget, you can listen to this event + to take some other actions, but the most important part of this + method is that it runs its default action, (its activation) + this method uses _deactivate as its implementation to maintain + the events order intact. + @property activate [Function] + @method + @dispatch beforeDeactivatee + @dispatch deactivate + @return this [Widget] + **/ + deactivate : function deactivate() { + if (this.__destroyed === true) { + console.warn('calling on destroyed object'); + } + this.dispatch('beforeDeactivate'); + this._deactivate(); + this.dispatch('deactivate'); + return this; + }, + + /** + Enable implementation method + if you need to provide a different procedure for enable + you must override this method and call "super" + @property _enable [Function] + @method + @return undefined [undefined] + **/ + _enable : function _enable() { + this.disabled = false; + this.element.removeClass('disable'); + }, + + /** + Public enable method, this method should not be + overriden. + @property enable [Function] + @method + @return this [Widget] + **/ + enable : function enable() { + if (this.__destroyed === true) { + console.warn('calling on destroyed object'); + } + this.dispatch('beforeEnable'); + this._enable(); + this.dispatch('enable'); + + return this; + }, + + /** + Disable implementation + @property _disable [Function] + @return undefined [undefined] + **/ + _disable : function _disable() { + this.disabled = true; + this.element.addClass('disable'); + }, + + /** + Disables the widget, the idea behind disabling a widget + comes from DOM form elements. so following this idea + all widgets can be disabled and queried for its disabled + state via the disabled property. + Same as DOM form elements there is feedback and that is why + the default implementation sets the "disable" class + on the element so proper visual feedback can be provided + to the user. + @property disable [Function] + @method + @return this [Widget] + **/ + disable : function disable() { + if (this.__destroyed === true) { + console.warn('calling on destroyed object'); + } + this.dispatch('beforeDisable'); + this._disable(); + this.dispatch('disable'); + + return this; + }, + + /** + Destroy implementation. Its main responsabilities are cleaning + all references to other objects so garbage collector can collect + the memory used by this and the other objects + @property _destroy [Function] + @method + @return undefined [undefined] + **/ + _destroy : function _destroy() { + var childrenLength; + + if (this.element) { + this.element.remove(); + } + + if (this.children !== null){ + childrenLength = this.children.length; + while(childrenLength > 0){ + this.children[0].destroy(); + if (this.children.length === childrenLength) { + this.children.shift(); + } + childrenLength--; + } + } + + if (this.parent) { + this.parent.removeChild(this); + } + + this.children = null; + this.element = null; + }, + + /** + Destroy public method, this one should not be replaced + @property destroy [Function] + @method + @return null [null] + **/ + destroy : function destroy() { + if (this.__destroyed === true) { + console.warn('calling on destroyed object'); + } + + this.dispatch('beforeDestroy'); + this._destroy(); + this.dispatch('destroy'); + + this.eventListeners = null; + this.__destroyed = true; + + return null; + }, + + /** + The render method is the mechanism by which you pass a widget from + living only on memory to get into the DOM and with this into the + application flow. The recomendation is that render is the last method + of the setup of a widget, including appending its children. this is + because once a widget gets renderer, further operations cause browser + reflows, and DOM operations are slower than memory operations. + This method shoudl not be replaced by its children. + @property render [Function] + @method + @argument element [JQuery] (undefined) This is the element + into which the widget will be appended. + @argument beforeElement [jQuery] (undefined) this is the element + that will be used as a reference to insert the widgets element. this argument + must be a child of the "element" argument. + @return this [Widget] + **/ + render : function render(element, beforeElement) { + if (this.__destroyed === true) { + console.warn('calling on destroyed object'); + } + this.dispatch('beforeRender', { + element : element, + beforeElement : beforeElement + }); + if (beforeElement) { + this.element.insertBefore(beforeElement); + } else { + this.element.appendTo(element); + } + this.dispatch('render'); + return this; + } + } +});