From f0bf38675b200ec3942d37818a462fa2b6d10f03 Mon Sep 17 00:00:00 2001 From: Andrey Popp <8mayday@gmail.com> Date: Wed, 13 Mar 2013 14:18:29 +0400 Subject: [PATCH] remove auto digest from DOM events, sometimes we need to use $.prop --- backbone.viewdsl.coffee | 43 ++++++++++++------------------ backbone.viewdsl.js | 58 ++++++++++++++--------------------------- tests/lib/tests.js | 11 +------- tests/tests.coffee | 6 ----- 4 files changed, 36 insertions(+), 82 deletions(-) diff --git a/backbone.viewdsl.coffee b/backbone.viewdsl.coffee index d10a2eb..dcb74ae 100644 --- a/backbone.viewdsl.coffee +++ b/backbone.viewdsl.coffee @@ -21,7 +21,7 @@ ) this, (_, Backbone, require) -> - {some, every, extend, toArray, isEqual, isBoolean, isString} = _ + {some, every, extend, toArray, isEqual, isBoolean, isString, contains} = _ resolvePath = (o, p) -> p = p.trim() @@ -196,6 +196,8 @@ $node + domProperties = ['value', 'checked', 'disabled'] + Directives = compileInterpolation: ($node, value) -> @@ -225,17 +227,21 @@ observe = true attrName = name.substring(5) $node.removeAttr(name) + {attr, removeAttr} = if contains(domProperties, attrName) + {attr: 'prop', removeAttr: 'removeProp'} + else + {attr: 'attr', removeAttr: 'removeAttr'} (scope, $node) -> scope.reactOn value, observe: observe react: (got) -> if isBoolean(got) if got - $node.attr(attrName, '') + $node[attr](attrName, '') else - $node.removeAttr(attrName) + $node[removeAttr](attrName) else - $node.attr(attrName, got) + $node[attr](attrName, got) compileClass: ($node, name, value) -> observe = false @@ -330,21 +336,22 @@ template: undefined constructor: (options = {}) -> - super this.template = options.template if options.template? this.parent = options.parent this.views = [] this.compiler = new Compiler(this.constructor) - if this.model? - this.listenTo this.model, 'change' + if options.model? + this.listenTo options.model, 'change' - if this.collection? - this.listenTo this.collection, 'change add remove reset sort' + if options.collection? + this.listenTo options.collection, 'change add remove reset sort' this.digestScheduled = false this.observe = {} + super + renderTemplate: (template) -> if not (template instanceof Template) template = this.compiler.compile($parseHTML template) @@ -401,24 +408,6 @@ if options.observe this.listenTo this, "change:#{p}", options.react - delegateEvents: (events) -> - if not (events or (events = _.result(this, 'events'))) - return this - this.undelegateEvents() - for key, method of events - method = this[events[key]] unless _.isFunction(method) - throw new Error("Method \"#{events[key]}\" does not exist") unless method - match = key.match(delegateEventSplitter) - eventName = match[1] - selector = match[2] - method = @mutating _.bind(method, this) - eventName += '.delegateEvents' + this.cid - if selector == '' - this.$el.on(eventName, method) - else - this.$el.on(eventName, selector, method) - this - listenTo: (obj, name, cb) -> if typeof name == 'object' for k, v of name diff --git a/backbone.viewdsl.js b/backbone.viewdsl.js index f1e6567..d0263dd 100644 --- a/backbone.viewdsl.js +++ b/backbone.viewdsl.js @@ -26,8 +26,8 @@ var __hasProp = {}.hasOwnProperty, return root.Backbone.ViewDSL = factory(root._, root.Backbone); } })(this, function(_, Backbone, require) { - var $fromArray, $isEmpty, $nodify, $parseHTML, CollectionView, Compiler, Directives, Template, View, delegateEventSplitter, every, extend, hypensToCamelCase, isBoolean, isEqual, isString, knownAttrs, knownTags, resolvePath, resolveSpec, some, textNodeSplitRe, toArray; - some = _.some, every = _.every, extend = _.extend, toArray = _.toArray, isEqual = _.isEqual, isBoolean = _.isBoolean, isString = _.isString; + var $fromArray, $isEmpty, $nodify, $parseHTML, CollectionView, Compiler, Directives, Template, View, contains, delegateEventSplitter, domProperties, every, extend, hypensToCamelCase, isBoolean, isEqual, isString, knownAttrs, knownTags, resolvePath, resolveSpec, some, textNodeSplitRe, toArray; + some = _.some, every = _.every, extend = _.extend, toArray = _.toArray, isEqual = _.isEqual, isBoolean = _.isBoolean, isString = _.isString, contains = _.contains; resolvePath = function(o, p) { var n, _i, _len, _ref; p = p.trim(); @@ -279,6 +279,7 @@ var __hasProp = {}.hasOwnProperty, return Template; })(); + domProperties = ['value', 'checked', 'disabled']; Directives = { compileInterpolation: function($node, value) { var observe; @@ -308,7 +309,7 @@ var __hasProp = {}.hasOwnProperty, }; }, compileAttr: function($node, name, value) { - var attrName, observe; + var attr, attrName, observe, removeAttr, _ref; observe = false; if (value.substring(0, 5) === 'bind:') { value = value.substring(5); @@ -316,18 +317,25 @@ var __hasProp = {}.hasOwnProperty, } attrName = name.substring(5); $node.removeAttr(name); + _ref = contains(domProperties, attrName) ? { + attr: 'prop', + removeAttr: 'removeProp' + } : { + attr: 'attr', + removeAttr: 'removeAttr' + }, attr = _ref.attr, removeAttr = _ref.removeAttr; return function(scope, $node) { return scope.reactOn(value, { observe: observe, react: function(got) { if (isBoolean(got)) { if (got) { - return $node.attr(attrName, ''); + return $node[attr](attrName, ''); } else { - return $node.removeAttr(attrName); + return $node[removeAttr](attrName); } } else { - return $node.attr(attrName, got); + return $node[attr](attrName, got); } } }); @@ -458,21 +466,21 @@ var __hasProp = {}.hasOwnProperty, if (options == null) { options = {}; } - View.__super__.constructor.apply(this, arguments); if (options.template != null) { this.template = options.template; } this.parent = options.parent; this.views = []; this.compiler = new Compiler(this.constructor); - if (this.model != null) { - this.listenTo(this.model, 'change'); + if (options.model != null) { + this.listenTo(options.model, 'change'); } - if (this.collection != null) { - this.listenTo(this.collection, 'change add remove reset sort'); + if (options.collection != null) { + this.listenTo(options.collection, 'change add remove reset sort'); } this.digestScheduled = false; this.observe = {}; + View.__super__.constructor.apply(this, arguments); } View.prototype.renderTemplate = function(template) { @@ -563,34 +571,6 @@ var __hasProp = {}.hasOwnProperty, } }; - View.prototype.delegateEvents = function(events) { - var eventName, key, match, method, selector; - if (!(events || (events = _.result(this, 'events')))) { - return this; - } - this.undelegateEvents(); - for (key in events) { - method = events[key]; - if (!_.isFunction(method)) { - method = this[events[key]]; - } - if (!method) { - throw new Error("Method \"" + events[key] + "\" does not exist"); - } - match = key.match(delegateEventSplitter); - eventName = match[1]; - selector = match[2]; - method = this.mutating(_.bind(method, this)); - eventName += '.delegateEvents' + this.cid; - if (selector === '') { - this.$el.on(eventName, method); - } else { - this.$el.on(eventName, selector, method); - } - } - return this; - }; - View.prototype.listenTo = function(obj, name, cb) { var k, v; if (typeof name === 'object') { diff --git a/tests/lib/tests.js b/tests/lib/tests.js index 382a6b2..276a0e8 100644 --- a/tests/lib/tests.js +++ b/tests/lib/tests.js @@ -163,7 +163,7 @@ define(function(require) { v.render(); return v; }; - it('should digest on object event handling', function() { + return it('should digest on object event handling', function() { var v; v = renderV('
Hello, {{bind:name}}!
', { name: 'World' @@ -175,15 +175,6 @@ define(function(require) { et.trigger('event'); return expect(v.$el.html()).to.be.equal('
Hello, Andrey!
'); }); - return it('should digest on DOM event handling', function() { - var v; - v = renderV('
Hello, {{bind:name}}!
', { - name: 'World' - }); - expect(v.$el.html()).to.be.equal('
Hello, World!
'); - v.$el.trigger('event'); - return expect(v.$el.html()).to.be.equal('
Hello, Andrey!
'); - }); }); }); describe('View', function() { diff --git a/tests/tests.coffee b/tests/tests.coffee index 8e23b62..6a24ea9 100644 --- a/tests/tests.coffee +++ b/tests/tests.coffee @@ -116,12 +116,6 @@ define (require) -> et.trigger 'event' expect(v.$el.html()).to.be.equal '
Hello, Andrey!
' - it 'should digest on DOM event handling', -> - v = renderV '
Hello, {{bind:name}}!
', {name: 'World'} - expect(v.$el.html()).to.be.equal '
Hello, World!
' - v.$el.trigger('event') - expect(v.$el.html()).to.be.equal '
Hello, Andrey!
' - describe 'View', -> render = (t, s) ->