/bower_components/backbone.marionette/src/marionette.view.js
JavaScript | 216 lines | 113 code | 45 blank | 58 comment | 18 complexity | 763ba6966893bfae81aeba9ce8ac5995 MD5 | raw file
- // Marionette.View
- // ---------------
- // The core view type that other Marionette views extend from.
- Marionette.View = Backbone.View.extend({
- constructor: function(options){
- _.bindAll(this, "render");
- var args = Array.prototype.slice.apply(arguments);
- // this exposes view options to the view initializer
- // this is a backfill since backbone removed the assignment
- // of this.options
- // at some point however this may be removed
- this.options = _.extend({}, this.options, options);
- // parses out the @ui DSL for events
- this.events = this.normalizeUIKeys(_.result(this, 'events'));
- Backbone.View.prototype.constructor.apply(this, args);
- Marionette.MonitorDOMRefresh(this);
- this.listenTo(this, "show", this.onShowCalled, this);
- },
- // import the "triggerMethod" to trigger events with corresponding
- // methods if the method exists
- triggerMethod: Marionette.triggerMethod,
- // Get the template for this view
- // instance. You can set a `template` attribute in the view
- // definition or pass a `template: "whatever"` parameter in
- // to the constructor options.
- getTemplate: function(){
- return Marionette.getOption(this, "template");
- },
- // Mix in template helper methods. Looks for a
- // `templateHelpers` attribute, which can either be an
- // object literal, or a function that returns an object
- // literal. All methods and attributes from this object
- // are copies to the object passed in.
- mixinTemplateHelpers: function(target){
- target = target || {};
- var templateHelpers = Marionette.getOption(this, "templateHelpers");
- if (_.isFunction(templateHelpers)){
- templateHelpers = templateHelpers.call(this);
- }
- return _.extend(target, templateHelpers);
- },
- // allows for the use of the @ui. syntax within
- // a given key for triggers and events
- // swaps the @ui with the associated selector
- normalizeUIKeys: function(hash) {
- if (typeof(hash) === "undefined") {
- return;
- }
- _.each(_.keys(hash), function(v) {
- var split = v.split("@ui.");
- if (split.length === 2) {
- hash[split[0]+this.ui[split[1]]] = hash[v];
- delete hash[v];
- }
- }, this);
- return hash;
- },
- // Configure `triggers` to forward DOM events to view
- // events. `triggers: {"click .foo": "do:foo"}`
- configureTriggers: function(){
- if (!this.triggers) { return; }
- var triggerEvents = {};
- // Allow `triggers` to be configured as a function
- var triggers = this.normalizeUIKeys(_.result(this, "triggers"));
- // Configure the triggers, prevent default
- // action and stop propagation of DOM events
- _.each(triggers, function(value, key){
- var hasOptions = _.isObject(value);
- var eventName = hasOptions ? value.event : value;
- // build the event handler function for the DOM event
- triggerEvents[key] = function(e){
- // stop the event in its tracks
- if (e) {
- var prevent = e.preventDefault;
- var stop = e.stopPropagation;
- var shouldPrevent = hasOptions ? value.preventDefault : prevent;
- var shouldStop = hasOptions ? value.stopPropagation : stop;
- if (shouldPrevent && prevent) { prevent.apply(e); }
- if (shouldStop && stop) { stop.apply(e); }
- }
- // build the args for the event
- var args = {
- view: this,
- model: this.model,
- collection: this.collection
- };
- // trigger the event
- this.triggerMethod(eventName, args);
- };
- }, this);
- return triggerEvents;
- },
- // Overriding Backbone.View's delegateEvents to handle
- // the `triggers`, `modelEvents`, and `collectionEvents` configuration
- delegateEvents: function(events){
- this._delegateDOMEvents(events);
- Marionette.bindEntityEvents(this, this.model, Marionette.getOption(this, "modelEvents"));
- Marionette.bindEntityEvents(this, this.collection, Marionette.getOption(this, "collectionEvents"));
- },
- // internal method to delegate DOM events and triggers
- _delegateDOMEvents: function(events){
- events = events || this.events;
- if (_.isFunction(events)){ events = events.call(this); }
- var combinedEvents = {};
- var triggers = this.configureTriggers();
- _.extend(combinedEvents, events, triggers);
- Backbone.View.prototype.delegateEvents.call(this, combinedEvents);
- },
- // Overriding Backbone.View's undelegateEvents to handle unbinding
- // the `triggers`, `modelEvents`, and `collectionEvents` config
- undelegateEvents: function(){
- var args = Array.prototype.slice.call(arguments);
- Backbone.View.prototype.undelegateEvents.apply(this, args);
- Marionette.unbindEntityEvents(this, this.model, Marionette.getOption(this, "modelEvents"));
- Marionette.unbindEntityEvents(this, this.collection, Marionette.getOption(this, "collectionEvents"));
- },
- // Internal method, handles the `show` event.
- onShowCalled: function(){},
- // Default `close` implementation, for removing a view from the
- // DOM and unbinding it. Regions will call this method
- // for you. You can specify an `onClose` method in your view to
- // add custom code that is called after the view is closed.
- close: function(){
- if (this.isClosed) { return; }
- // allow the close to be stopped by returning `false`
- // from the `onBeforeClose` method
- var shouldClose = this.triggerMethod("before:close");
- if (shouldClose === false){
- return;
- }
- // mark as closed before doing the actual close, to
- // prevent infinite loops within "close" event handlers
- // that are trying to close other views
- this.isClosed = true;
- this.triggerMethod("close");
- // unbind UI elements
- this.unbindUIElements();
- // remove the view from the DOM
- this.remove();
- },
- // This method binds the elements specified in the "ui" hash inside the view's code with
- // the associated jQuery selectors.
- bindUIElements: function(){
- if (!this.ui) { return; }
- // store the ui hash in _uiBindings so they can be reset later
- // and so re-rendering the view will be able to find the bindings
- if (!this._uiBindings){
- this._uiBindings = this.ui;
- }
- // get the bindings result, as a function or otherwise
- var bindings = _.result(this, "_uiBindings");
- // empty the ui so we don't have anything to start with
- this.ui = {};
- // bind each of the selectors
- _.each(_.keys(bindings), function(key) {
- var selector = bindings[key];
- this.ui[key] = this.$(selector);
- }, this);
- },
- // This method unbinds the elements specified in the "ui" hash
- unbindUIElements: function(){
- if (!this.ui || !this._uiBindings){ return; }
- // delete all of the existing ui bindings
- _.each(this.ui, function($el, name){
- delete this.ui[name];
- }, this);
- // reset the ui element to the original bindings configuration
- this.ui = this._uiBindings;
- delete this._uiBindings;
- }
- });