/** * Core application class designed and intended to be extended at a project level. * * @author Michael White * @copyright Copyright 2011 Media Macros Inc. */ MMI.Util.namespace('MMI.App.Core'); MMI.App.Core = MMI.stdClass.extend({ _liveEvents : {}, __construct: function() { MMI.App.setInstance(this); this._liveEvents = []; this._handlerClasses = []; this._windowResizeTimeout = false; this._windowResizeUpdateDelayMilliseconds = 100; this.registerLiveEvents(['resize', 'hover']); this._setUpSystemInitialization(); }, _setUpSystemInitialization: function() { jQuery(document).ready(this._handleDocumentReady); jQuery(window).bind('resize', this._handleRealWindowResize); }, registerHandlerClass: function(object) { if(object && typeof(object) == 'object') { this._handlerClasses[this._handlerClasses.length] = object; } }, _bindLiveEvents: function() { var eventName = ''; for(var i in this._liveEvents) { if(this._liveEvents.hasOwnProperty(i)) { eventName = this._liveEvents[i]; if(typeof(eventName) == 'string') { var jqelTarget = jQuery('.live_'+eventName); if(eventName != 'hover') { jqelTarget.live(eventName, this._handleLiveEvent); } else { jqelTarget .live('mouseenter mouseover', this._handleHoverStartEvent) .live('mouseleave mouseout', this._handleHoverEndEvent); } } } } }, _bindLiveEvent: function(eventName) { if(typeof(eventName) == 'string' && this._liveEvents.hasOwnProperty(eventName)) { var jqelTarget = jQuery('.live_'+eventName); if(eventName != 'hover') { jqelTarget.live(eventName, this._handleLiveEvent); } else { jqelTarget .live('mouseenter mouseover', this._handleHoverStartEvent) .live('mouseleave mouseout', this._handleHoverEndEvent); } } }, /* @todo Change scope of this method to use the APP */ _handleDocumentReady: function(event) { MMI.App.getInstance().handleDocumentReady(event); // Trigger initial create event jQuery('.live_create').trigger('create'); }, handleDocumentReady: function(event) { // Deliberately empty }, _handleRealWindowResize: function(event) { var self = MMI.App.getInstance(); clearTimeout(this._windowResizeTimeout); self._windowResizeTimeout = setTimeout(function() { var w = jQuery(window); jQuery('.live_resize').trigger('resize', [w.width(), w.height()]); }, this._windowResizeUpdateDelayMilliseconds); }, _handleHoverStartEvent: function(event) { var self = MMI.App.getInstance(); var jqel = jQuery(this); var handler = jqel.data('live_hover_start_handler'); if(!handler) { handler = '_defaultHandleHoverStart'; } self._callEventHandler(event, handler, jqel); }, _handleHoverEndEvent: function(event) { var self = MMI.App.getInstance(); var jqel = jQuery(this); var handler = jqel.data('live_hover_end_handler'); if(!handler) { handler = '_defaultHandleHoverEnd'; } self._callEventHandler(event, handler, jqel); }, /** * This is needed for cases (like keydown) where the system needs to capture something at the document level but still * have it run through the app system. * * @param eventName * @param jqelDataSource */ documentLive: function(eventName) { jQuery(document).ready(function() { jQuery(document).bind(eventName, function() { MMI.App.getInstance()._handleLiveEvent.apply(jQuery('body'), arguments); }); }); }, _handleLiveEvent: function(event) { var self = MMI.App.getInstance(); var jqel = jQuery(this); var data = jQuery.extend(true, {}, jqel.data()); var parents = jqel.parents(); parents.each(function(i, el){ var tmpData = jQuery.extend({}, jQuery(el).data()); data = jQuery.extend(tmpData, data); }); /* Remove create or remove class if special events */ if(event.type == 'create') { jqel.removeClass('live_create'); } else if(event.type == 'remove') { jqel.removeClass('live_remove'); } var handler = data['live_'+event.type+'_handler']; var customEventParams = []; for(var i=1; i < arguments.length; i++) { if(arguments.hasOwnProperty(i)) { customEventParams[customEventParams.length] = arguments[i]; } } self._callEventHandler(event, handler, jqel, data, customEventParams); return false; }, _callEventHandler: function(event, handler, jqel, data, customEventParams) { var handlers = []; if(typeof(handler) == 'string') { handlers = handler.split(';'); } else if(typeof(handler) == 'function') { handlers[handlers.length] = handler; } else { clog('Invalid handler for `'+event.type+'` on:', jqel); return; } if(handlers.length > 1) { for(var h in handlers) { if(handlers.hasOwnProperty(h)) { this._callEventHandler(event, handlers[h], jqel, data, customEventParams); } } return; /* Don't complete this round, multiple-handlers provided */ } var result = null; var domTarget = jqel.get(0); if(typeof(customEventParams) == 'undefined') { customEventParams = []; } /* Base is the event, the app object, jqel, the data */ var eventParams = [event, this, jqel, data]; for(var i=0; i < customEventParams.length; i++) { if(customEventParams.hasOwnProperty(i)) { eventParams[eventParams.length] = customEventParams[i]; } } if(typeof(handler) == 'string') { if(handler.search(/\./) != -1) { clog('!!!!!! Evil eval() - Change your handler if you can. !!!!!!', handler); result = eval(handler); } else { var foundClassedHandler = false; for(var key in this._handlerClasses) { if(this._handlerClasses.hasOwnProperty(key)) { if(typeof(this._handlerClasses[key][handler]) == 'function') { result = this._handlerClasses[key][handler].apply(domTarget, eventParams); foundClassedHandler = true; break; /* Once we find a handler we don't look for it anywhere else. */ } } } if(!foundClassedHandler && typeof(this[handler]) == 'function') { result = this[handler].apply(domTarget, eventParams); } } } else if(typeof(handler) == 'function') { result = handler.apply(domTarget, eventParams); } if(result !== false) { /* If the event has NOT been canceled - run the default event handler also. */ handler = this._getDefaultEventHandler(event.type); if(typeof(handler) == 'function') { result = handler.apply(domTarget, eventParams); } } return result; }, _getDefaultEventHandler: function(eventName) { eventName = eventName.charAt(0).toUpperCase() + eventName.slice(1); return this['_defaultHandle'+eventName+'Event']; }, _defaultHandleHoverStart: function(event) { jQuery(this).addClass('hover'); }, _defaultHandleHoverEnd: function(event) { jQuery(this).removeClass('hover'); }, setWindowResizeUpdateDelay: function(delayInMilliseconds) { this._windowResizeUpdateDelayMilliseconds = delayInMilliseconds; }, registerLiveEvent: function(eventName) { eventName = eventName.toLowerCase(); if(!this._liveEvents.hasOwnProperty(eventName)) { this._liveEvents[eventName] = eventName; this._bindLiveEvent(eventName); } }, registerLiveEvents: function(eventNameList) { for(var i in eventNameList) { if(eventNameList.hasOwnProperty(i)) { this.registerLiveEvent(eventNameList[i]); } } }, unRegisterLiveEvent: function(eventName) { if(this._liveEvents.hasOwnProperty(eventName)) { delete this._liveEvents[eventName]; } }, unRegisterLiveEvents: function(eventNameList) { for(var i in eventNameList) { if(eventNameList.hasOwnProperty(i)) { this.unRegisterLiveEvent(eventNameList[i]); } } } });