Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

converted Backbone.ViewModel to CS

  • Loading branch information...
commit 47b6d3f7122a455fc002b22e64e8f6447dfa9380 1 parent 53fa47b
Hunter Loftis authored
1  Makefile
@@ -21,7 +21,6 @@ test: js
21 21
22 22 js: clean
23 23 coffee --output lib --compile .
24   - cp *.js lib
25 24
26 25 clean:
27 26 rm -rf dist/*
110 backbone.viewmodel.coffee
... ... @@ -0,0 +1,110 @@
  1 +do (Backbone) ->
  2 +
  3 + proto = Backbone.Model::
  4 +
  5 + argMap = {
  6 + 'undefined': undefined
  7 + 'null': null
  8 + 'true': true
  9 + 'false': false
  10 + }
  11 +
  12 + class Backbone.ViewModel extends Backbone.Model
  13 + constructor: (attributes, options) ->
  14 + @_virtuals = {}
  15 + @_bindings = []
  16 + super
  17 +
  18 + set: (key, value, options) ->
  19 + unless options && options.dependency
  20 + virtual = @_virtuals?.hasOwnProperty(key) && @_virtuals[key]
  21 + if virtual then return virtual.set.call(this, key, value, options, virtual)
  22 + return proto.set.apply(this, arguments)
  23 +
  24 + bindView: (attribute, container = 'body') ->
  25 + selector = '*[' + attribute + ']'
  26 + nodes = $(container).find(selector)
  27 + if $(container).is(selector) then nodes = $(container).add(nodes)
  28 + @bindToNode(attribute, node) for node in nodes
  29 + return nodes
  30 +
  31 + unbindView: ->
  32 + binding.stop() for binding in @_bindings
  33 + @_bindings = []
  34 +
  35 + isBoundTo: (node) ->
  36 + for binding in @_bindings
  37 + if binding.node == node then return true
  38 + return false
  39 +
  40 + bindToNode: (attribute, node) =>
  41 + if @isBoundTo(node) then return
  42 + bindingString = $(node).attr(attribute)
  43 + bindingList = bindingString.split(';')
  44 + descriptions = (@parseBinding(node, attribute, pair) for pair in bindingList)
  45 + @createBinding(description) for description in descriptions
  46 +
  47 + parseBinding: (node, attribute, pair) =>
  48 + typeSplit = pair.split('(')
  49 + type = typeSplit[0].trim()
  50 + argString = typeSplit[1].trim().slice(0, -1)
  51 + args = (@parseArgument(arg) for arg in argString.split(','))
  52 + return {
  53 + node: node
  54 + viewModel: this
  55 + type: type
  56 + bindingAttr: attribute
  57 + args: args
  58 + }
  59 +
  60 + parseArgument: (arg) ->
  61 + arg = arg.trim()
  62 + if argMap.hasOwnProperty(arg)
  63 + arg = argMap[arg]
  64 + else if !isNaN(arg)
  65 + arg = Number(arg)
  66 + return arg
  67 +
  68 + createBinding: (description) ->
  69 + Binding = Backbone.Binding[description.type]
  70 + if Binding?
  71 + binding = new Binding(description)
  72 + binding.start()
  73 + @_bindings.push(binding)
  74 + return binding
  75 + else
  76 + throw new Error('Trying to create a binding of unknown type "' + description.type + '"')
  77 +
  78 + get: (attr) ->
  79 + Backbone.Virtual.track(this, 'change:' + attr)
  80 + return @attributes[attr]
  81 +
  82 + compute: ->
  83 + args = _.toArray(arguments)
  84 + get = args.pop()
  85 + args.push({ get: get })
  86 + @virtual.apply(this, args)
  87 +
  88 + pass: ->
  89 + args = _.toArray(arguments)
  90 + reference = args.pop()
  91 + args.push({ reference: reference })
  92 + @virtual.apply(this, args)
  93 +
  94 + virtual: ->
  95 + attrs = _.toArray(arguments)
  96 + options = attrs.pop()
  97 + options.model = this
  98 + return (@createVirtual(attr, options) for attr in attrs)
  99 +
  100 + createVirtual: (attr, options) =>
  101 + opts = _.extend({}, options, { attr: attr })
  102 + newVirtual = new Backbone.Virtual(opts)
  103 + @_virtuals[attr] = newVirtual
  104 + newVirtual.on('change', @onVirtual)
  105 + newVirtual.run()
  106 +
  107 + onVirtual: (virtual) =>
  108 + @set(virtual.attr, virtual.result, { dependency: true })
  109 +
  110 + Backbone.Model = Backbone.ViewModel
168 backbone.viewmodel.js
... ... @@ -1,168 +0,0 @@
1   -(function(Backbone) {
2   -
3   - // Store reference to old methods
4   - var proto = Backbone.Model.prototype;
5   -
6   - Backbone.ViewModel = Backbone.Model.extend({
7   -
8   - constructor: function(attributes, options) {
9   - this._virtuals = {};
10   - this._bindings = [];
11   - proto.constructor.apply(this, arguments);
12   - },
13   -
14   - // TODO: This probably gets called twice whenever a virtual value is manually set()
15   - // Once for when the property is initially set, then when the property triggers its referenced model to change
16   - // the model change will trigger this set() again. Try to eliminate this inefficiency.
17   - set: function(key, value, options) {
18   - var virtual;
19   - // Call virtual's set() unless this was triggered by a dependency change
20   - if (!(options && options.dependency)) {
21   - virtual = this._virtuals && this._virtuals.hasOwnProperty(key) && this._virtuals[key];
22   - if (virtual) {
23   - return virtual.set.call(this, key, value, options, virtual);
24   - }
25   - }
26   - return proto.set.apply(this, arguments);
27   - },
28   -
29   - bindView: function(attribute, container) {
30   - container = container || 'body';
31   - var selector = '*[' + attribute + ']';
32   - var nodes = $(container).find(selector);
33   - if ($(container).is(selector)) {
34   - nodes = $(container).add(nodes);
35   - }
36   - _.each(nodes, this.bindToNode(attribute));
37   - return nodes;
38   - },
39   -
40   - unbindView: function() {
41   - _.each(this._bindings, function(binding) {
42   - binding.stop();
43   - });
44   - this._bindings = [];
45   - },
46   -
47   - isBoundTo: function(node) {
48   - return _.any(this._bindings, function(binding) {
49   - return binding.node === node;
50   - });
51   - },
52   -
53   - bindToNode: function(attribute) {
54   - var self = this;
55   - return function(node) {
56   - if (self.isBoundTo(node)) return;
57   -
58   - var bindingString = $(node).attr(attribute);
59   - var bindingList = bindingString.split(';');
60   - var descriptions = _.map(bindingList, self.parseBinding(node, attribute));
61   -
62   - _.each(descriptions, self.createBinding, self);
63   - };
64   - },
65   -
66   - parseBinding: function(node, attribute) {
67   - var self = this;
68   - return function(bindingPair) {
69   - var typeSplit = bindingPair.split('(');
70   - var type = typeSplit[0].trim();
71   - var argString = typeSplit[1].trim().slice(0, -1);
72   - var args = argString.split(',');
73   - args = _.map(args, self.parseArgument);
74   - // example:
75   - // <div id='foo' data-bind='visible(bar)'></div>
76   - // vm.bindView('#foobar');
77   - return {
78   - node: node, // <div id='foo' ... >
79   - viewModel: self, // vm
80   - type: type, // "visible"
81   - bindingAttr: attribute, // "data-bind"
82   - args: args // ["bar"]
83   - };
84   - };
85   - },
86   -
87   - parseArgument: function(arg) {
88   - arg = arg.trim();
89   - var map = {
90   - 'undefined': undefined,
91   - 'null': null,
92   - 'true': true,
93   - 'false': false
94   - };
95   - if (map.hasOwnProperty(arg)) {
96   - arg = map[arg];
97   - }
98   - else if (arg.charAt[0] === '"' || arg.charAt[0] === "'") {
99   - // TODO: figure out what to do about string literals
100   - }
101   - else if (!isNaN(arg)) {
102   - arg = Number(arg);
103   - }
104   - return arg;
105   - },
106   -
107   - createBinding: function(description) {
108   - var Binding = Backbone.Binding[description.type];
109   - if (Binding) {
110   - var binding = new Binding(description);
111   - if (binding) {
112   - binding.start();
113   - this._bindings.push(binding);
114   - return binding;
115   - }
116   - throw new Error("Unable to create '" + description.type + "' binding");
117   - }
118   - throw new Error("Trying to create a binding of unknown type '" + description.type + "'");
119   - },
120   -
121   - // Get the value of an attribute.
122   - get: function(attr) {
123   - Backbone.Virtual.track(this, 'change:' + attr);
124   - return this.attributes[attr];
125   - },
126   -
127   - compute: function() {
128   - var args = _.toArray(arguments);
129   - var get = args.pop();
130   - args.push({ get: get });
131   - this.virtual.apply(this, args);
132   - },
133   -
134   - pass: function() {
135   - var args = _.toArray(arguments);
136   - var reference = args.pop();
137   - args.push({ reference: reference });
138   - this.virtual.apply(this, args);
139   - },
140   -
141   - virtual: function() {
142   - var attrs = _.toArray(arguments);
143   - var options = attrs.pop();
144   - options.model = this;
145   - return _.map(attrs, this.createVirtual(options), this);
146   - },
147   -
148   - createVirtual: function(options) {
149   - var self = this;
150   - return function(attr) {
151   - var opts = _.extend({}, options, { attr: attr });
152   - var newVirtual = new Backbone.Virtual(opts);
153   - self._virtuals[attr] = newVirtual;
154   - newVirtual.on('change', self.onVirtual, self);
155   - newVirtual.run();
156   - };
157   - },
158   -
159   - onVirtual: function(virtual) {
160   - this.set(virtual.attr, virtual.result, { dependency: true });
161   - }
162   -
163   - });
164   -
165   - // Alias ViewModel to Model
166   - Backbone.Model = Backbone.ViewModel;
167   -
168   -})(Backbone);
356 lib/backbone.viewmodel.js
... ... @@ -1,168 +1,218 @@
1   -(function(Backbone) {
2   -
3   - // Store reference to old methods
4   - var proto = Backbone.Model.prototype;
5   -
6   - Backbone.ViewModel = Backbone.Model.extend({
7   -
8   - constructor: function(attributes, options) {
9   - this._virtuals = {};
10   - this._bindings = [];
11   - proto.constructor.apply(this, arguments);
12   - },
13   -
14   - // TODO: This probably gets called twice whenever a virtual value is manually set()
15   - // Once for when the property is initially set, then when the property triggers its referenced model to change
16   - // the model change will trigger this set() again. Try to eliminate this inefficiency.
17   - set: function(key, value, options) {
18   - var virtual;
19   - // Call virtual's set() unless this was triggered by a dependency change
20   - if (!(options && options.dependency)) {
21   - virtual = this._virtuals && this._virtuals.hasOwnProperty(key) && this._virtuals[key];
22   - if (virtual) {
23   - return virtual.set.call(this, key, value, options, virtual);
24   - }
25   - }
26   - return proto.set.apply(this, arguments);
27   - },
28   -
29   - bindView: function(attribute, container) {
30   - container = container || 'body';
31   - var selector = '*[' + attribute + ']';
32   - var nodes = $(container).find(selector);
33   - if ($(container).is(selector)) {
34   - nodes = $(container).add(nodes);
  1 +// Generated by CoffeeScript 1.3.3
  2 +(function() {
  3 + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  4 + __hasProp = {}.hasOwnProperty,
  5 + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
  6 +
  7 + (function(Backbone) {
  8 + var argMap, proto;
  9 + proto = Backbone.Model.prototype;
  10 + argMap = {
  11 + 'undefined': void 0,
  12 + 'null': null,
  13 + 'true': true,
  14 + 'false': false
  15 + };
  16 + Backbone.ViewModel = (function(_super) {
  17 +
  18 + __extends(ViewModel, _super);
  19 +
  20 + function ViewModel(attributes, options) {
  21 + this.onVirtual = __bind(this.onVirtual, this);
  22 +
  23 + this.createVirtual = __bind(this.createVirtual, this);
  24 +
  25 + this.parseBinding = __bind(this.parseBinding, this);
  26 +
  27 + this.bindToNode = __bind(this.bindToNode, this);
  28 + this._virtuals = {};
  29 + this._bindings = [];
  30 + ViewModel.__super__.constructor.apply(this, arguments);
35 31 }
36   - _.each(nodes, this.bindToNode(attribute));
37   - return nodes;
38   - },
39   -
40   - unbindView: function() {
41   - _.each(this._bindings, function(binding) {
42   - binding.stop();
43   - });
44   - this._bindings = [];
45   - },
46   -
47   - isBoundTo: function(node) {
48   - return _.any(this._bindings, function(binding) {
49   - return binding.node === node;
50   - });
51   - },
52   -
53   - bindToNode: function(attribute) {
54   - var self = this;
55   - return function(node) {
56   - if (self.isBoundTo(node)) return;
57   -
58   - var bindingString = $(node).attr(attribute);
59   - var bindingList = bindingString.split(';');
60   - var descriptions = _.map(bindingList, self.parseBinding(node, attribute));
61   -
62   - _.each(descriptions, self.createBinding, self);
  32 +
  33 + ViewModel.prototype.set = function(key, value, options) {
  34 + var virtual, _ref;
  35 + if (!(options && options.dependency)) {
  36 + virtual = ((_ref = this._virtuals) != null ? _ref.hasOwnProperty(key) : void 0) && this._virtuals[key];
  37 + if (virtual) {
  38 + return virtual.set.call(this, key, value, options, virtual);
  39 + }
  40 + }
  41 + return proto.set.apply(this, arguments);
  42 + };
  43 +
  44 + ViewModel.prototype.bindView = function(attribute, container) {
  45 + var node, nodes, selector, _i, _len;
  46 + if (container == null) {
  47 + container = 'body';
  48 + }
  49 + selector = '*[' + attribute + ']';
  50 + nodes = $(container).find(selector);
  51 + if ($(container).is(selector)) {
  52 + nodes = $(container).add(nodes);
  53 + }
  54 + for (_i = 0, _len = nodes.length; _i < _len; _i++) {
  55 + node = nodes[_i];
  56 + this.bindToNode(attribute, node);
  57 + }
  58 + return nodes;
  59 + };
  60 +
  61 + ViewModel.prototype.unbindView = function() {
  62 + var binding, _i, _len, _ref;
  63 + _ref = this._bindings;
  64 + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  65 + binding = _ref[_i];
  66 + binding.stop();
  67 + }
  68 + return this._bindings = [];
  69 + };
  70 +
  71 + ViewModel.prototype.isBoundTo = function(node) {
  72 + var binding, _i, _len, _ref;
  73 + _ref = this._bindings;
  74 + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  75 + binding = _ref[_i];
  76 + if (binding.node === node) {
  77 + return true;
  78 + }
  79 + }
  80 + return false;
  81 + };
  82 +
  83 + ViewModel.prototype.bindToNode = function(attribute, node) {
  84 + var bindingList, bindingString, description, descriptions, pair, _i, _len, _results;
  85 + if (this.isBoundTo(node)) {
  86 + return;
  87 + }
  88 + bindingString = $(node).attr(attribute);
  89 + bindingList = bindingString.split(';');
  90 + descriptions = (function() {
  91 + var _i, _len, _results;
  92 + _results = [];
  93 + for (_i = 0, _len = bindingList.length; _i < _len; _i++) {
  94 + pair = bindingList[_i];
  95 + _results.push(this.parseBinding(node, attribute, pair));
  96 + }
  97 + return _results;
  98 + }).call(this);
  99 + _results = [];
  100 + for (_i = 0, _len = descriptions.length; _i < _len; _i++) {
  101 + description = descriptions[_i];
  102 + _results.push(this.createBinding(description));
  103 + }
  104 + return _results;
63 105 };
64   - },
65   -
66   - parseBinding: function(node, attribute) {
67   - var self = this;
68   - return function(bindingPair) {
69   - var typeSplit = bindingPair.split('(');
70   - var type = typeSplit[0].trim();
71   - var argString = typeSplit[1].trim().slice(0, -1);
72   - var args = argString.split(',');
73   - args = _.map(args, self.parseArgument);
74   - // example:
75   - // <div id='foo' data-bind='visible(bar)'></div>
76   - // vm.bindView('#foobar');
  106 +
  107 + ViewModel.prototype.parseBinding = function(node, attribute, pair) {
  108 + var arg, argString, args, type, typeSplit;
  109 + typeSplit = pair.split('(');
  110 + type = typeSplit[0].trim();
  111 + argString = typeSplit[1].trim().slice(0, -1);
  112 + args = (function() {
  113 + var _i, _len, _ref, _results;
  114 + _ref = argString.split(',');
  115 + _results = [];
  116 + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  117 + arg = _ref[_i];
  118 + _results.push(this.parseArgument(arg));
  119 + }
  120 + return _results;
  121 + }).call(this);
77 122 return {
78   - node: node, // <div id='foo' ... >
79   - viewModel: self, // vm
80   - type: type, // "visible"
81   - bindingAttr: attribute, // "data-bind"
82   - args: args // ["bar"]
  123 + node: node,
  124 + viewModel: this,
  125 + type: type,
  126 + bindingAttr: attribute,
  127 + args: args
83 128 };
84 129 };
85   - },
86   -
87   - parseArgument: function(arg) {
88   - arg = arg.trim();
89   - var map = {
90   - 'undefined': undefined,
91   - 'null': null,
92   - 'true': true,
93   - 'false': false
  130 +
  131 + ViewModel.prototype.parseArgument = function(arg) {
  132 + arg = arg.trim();
  133 + if (argMap.hasOwnProperty(arg)) {
  134 + arg = argMap[arg];
  135 + } else if (!isNaN(arg)) {
  136 + arg = Number(arg);
  137 + }
  138 + return arg;
94 139 };
95   - if (map.hasOwnProperty(arg)) {
96   - arg = map[arg];
97   - }
98   - else if (arg.charAt[0] === '"' || arg.charAt[0] === "'") {
99   - // TODO: figure out what to do about string literals
100   - }
101   - else if (!isNaN(arg)) {
102   - arg = Number(arg);
103   - }
104   - return arg;
105   - },
106   -
107   - createBinding: function(description) {
108   - var Binding = Backbone.Binding[description.type];
109   - if (Binding) {
110   - var binding = new Binding(description);
111   - if (binding) {
  140 +
  141 + ViewModel.prototype.createBinding = function(description) {
  142 + var Binding, binding;
  143 + Binding = Backbone.Binding[description.type];
  144 + if (Binding != null) {
  145 + binding = new Binding(description);
112 146 binding.start();
113 147 this._bindings.push(binding);
114 148 return binding;
  149 + } else {
  150 + throw new Error('Trying to create a binding of unknown type "' + description.type + '"');
115 151 }
116   - throw new Error("Unable to create '" + description.type + "' binding");
117   - }
118   - throw new Error("Trying to create a binding of unknown type '" + description.type + "'");
119   - },
120   -
121   - // Get the value of an attribute.
122   - get: function(attr) {
123   - Backbone.Virtual.track(this, 'change:' + attr);
124   - return this.attributes[attr];
125   - },
126   -
127   - compute: function() {
128   - var args = _.toArray(arguments);
129   - var get = args.pop();
130   - args.push({ get: get });
131   - this.virtual.apply(this, args);
132   - },
133   -
134   - pass: function() {
135   - var args = _.toArray(arguments);
136   - var reference = args.pop();
137   - args.push({ reference: reference });
138   - this.virtual.apply(this, args);
139   - },
140   -
141   - virtual: function() {
142   - var attrs = _.toArray(arguments);
143   - var options = attrs.pop();
144   - options.model = this;
145   - return _.map(attrs, this.createVirtual(options), this);
146   - },
147   -
148   - createVirtual: function(options) {
149   - var self = this;
150   - return function(attr) {
151   - var opts = _.extend({}, options, { attr: attr });
152   - var newVirtual = new Backbone.Virtual(opts);
153   - self._virtuals[attr] = newVirtual;
154   - newVirtual.on('change', self.onVirtual, self);
155   - newVirtual.run();
156 152 };
157   - },
158 153
159   - onVirtual: function(virtual) {
160   - this.set(virtual.attr, virtual.result, { dependency: true });
161   - }
  154 + ViewModel.prototype.get = function(attr) {
  155 + Backbone.Virtual.track(this, 'change:' + attr);
  156 + return this.attributes[attr];
  157 + };
  158 +
  159 + ViewModel.prototype.compute = function() {
  160 + var args, get;
  161 + args = _.toArray(arguments);
  162 + get = args.pop();
  163 + args.push({
  164 + get: get
  165 + });
  166 + return this.virtual.apply(this, args);
  167 + };
  168 +
  169 + ViewModel.prototype.pass = function() {
  170 + var args, reference;
  171 + args = _.toArray(arguments);
  172 + reference = args.pop();
  173 + args.push({
  174 + reference: reference
  175 + });
  176 + return this.virtual.apply(this, args);
  177 + };
  178 +
  179 + ViewModel.prototype.virtual = function() {
  180 + var attr, attrs, options;
  181 + attrs = _.toArray(arguments);
  182 + options = attrs.pop();
  183 + options.model = this;
  184 + return (function() {
  185 + var _i, _len, _results;
  186 + _results = [];
  187 + for (_i = 0, _len = attrs.length; _i < _len; _i++) {
  188 + attr = attrs[_i];
  189 + _results.push(this.createVirtual(attr, options));
  190 + }
  191 + return _results;
  192 + }).call(this);
  193 + };
  194 +
  195 + ViewModel.prototype.createVirtual = function(attr, options) {
  196 + var newVirtual, opts;
  197 + opts = _.extend({}, options, {
  198 + attr: attr
  199 + });
  200 + newVirtual = new Backbone.Virtual(opts);
  201 + this._virtuals[attr] = newVirtual;
  202 + newVirtual.on('change', this.onVirtual);
  203 + return newVirtual.run();
  204 + };
  205 +
  206 + ViewModel.prototype.onVirtual = function(virtual) {
  207 + return this.set(virtual.attr, virtual.result, {
  208 + dependency: true
  209 + });
  210 + };
162 211
163   - });
  212 + return ViewModel;
164 213
165   - // Alias ViewModel to Model
166   - Backbone.Model = Backbone.ViewModel;
  214 + })(Backbone.Model);
  215 + return Backbone.Model = Backbone.ViewModel;
  216 + })(Backbone);
167 217
168   -})(Backbone);
  218 +}).call(this);

0 comments on commit 47b6d3f

Please sign in to comment.
Something went wrong with that request. Please try again.