b42c7d98 by Michael Richards

Move the utility functions into a Rivets.Util object. Better comment the code for annotated source.

1 parent 66980201
...@@ -4,7 +4,7 @@ module.exports = (grunt) -> ...@@ -4,7 +4,7 @@ module.exports = (grunt) ->
4 4
5 meta: 5 meta:
6 banner: 6 banner:
7 '// rivets.js\n' + 7 '// Rivets.js\n' +
8 '// version: <%= pkg.version %>\n' + 8 '// version: <%= pkg.version %>\n' +
9 '// author: <%= pkg.author %>\n' + 9 '// author: <%= pkg.author %>\n' +
10 '// license: <%= pkg.licenses[0].type %>\n' 10 '// license: <%= pkg.licenses[0].type %>\n'
......
1 # rivets.js 1 # Rivets.js
2 # version : 0.5.0 2 # =========
3 # author : Michael Richards 3
4 # license : MIT 4 # > version: 0.5.0
5 # > author: Michael Richards
6 # > license: MIT
7 # >
8 # > http://rivetsjs.com/
9
10 # ---
5 11
6 # The Rivets namespace. 12 # The Rivets namespace.
7 Rivets = {} 13 Rivets = {}
8 14
9 # Polyfill For String::trim. 15 # Polyfill For `String::trim`.
10 unless String::trim then String::trim = -> @replace /^\s+|\s+$/g, '' 16 unless String::trim then String::trim = -> @replace /^\s+|\s+$/g, ''
11 17
18 # Rivets.Binding
19 # --------------
20
12 # A single binding between a model attribute and a DOM element. 21 # A single binding between a model attribute and a DOM element.
13 class Rivets.Binding 22 class Rivets.Binding
14 # All information about the binding is passed into the constructor; the 23 # All information about the binding is passed into the constructor; the
...@@ -67,7 +76,7 @@ class Rivets.Binding ...@@ -67,7 +76,7 @@ class Rivets.Binding
67 76
68 # Publishes the value currently set on the input element back to the model. 77 # Publishes the value currently set on the input element back to the model.
69 publish: => 78 publish: =>
70 value = getInputValue @el 79 value = Rivets.Util.getInputValue @el
71 80
72 for formatter in @formatters.slice(0).reverse() 81 for formatter in @formatters.slice(0).reverse()
73 args = formatter.split /\s+/ 82 args = formatter.split /\s+/
...@@ -128,7 +137,10 @@ class Rivets.Binding ...@@ -128,7 +137,10 @@ class Rivets.Binding
128 @model = @view.models[@key] 137 @model = @view.models[@key]
129 @bind() 138 @bind()
130 139
131 # A collection of bindings built from a set of parent elements. 140 # Rivets.View
141 # -----------
142
143 # A collection of bindings built from a set of parent nodes.
132 class Rivets.View 144 class Rivets.View
133 # The DOM elements and the model objects for binding are passed into the 145 # The DOM elements and the model objects for binding are passed into the
134 # constructor along with any local options that should be used throughout the 146 # constructor along with any local options that should be used throughout the
...@@ -148,9 +160,9 @@ class Rivets.View ...@@ -148,9 +160,9 @@ class Rivets.View
148 prefix = @config.prefix 160 prefix = @config.prefix
149 if prefix then new RegExp("^data-#{prefix}-") else /^data-/ 161 if prefix then new RegExp("^data-#{prefix}-") else /^data-/
150 162
151 # Parses the DOM tree and builds Rivets.Binding instances for every matched 163 # Parses the DOM tree and builds `Rivets.Binding` instances for every matched
152 # binding declaration. Subsequent calls to build will replace the previous 164 # binding declaration. Subsequent calls to build will replace the previous
153 # Rivets.Binding instances with new ones, so be sure to unbind them first. 165 # `Rivets.Binding` instances with new ones, so be sure to unbind them first.
154 build: => 166 build: =>
155 @bindings = [] 167 @bindings = []
156 skipNodes = [] 168 skipNodes = []
...@@ -233,40 +245,39 @@ class Rivets.View ...@@ -233,40 +245,39 @@ class Rivets.View
233 @models[key] = model 245 @models[key] = model
234 binding.update() for binding in @select (b) -> b.key is key 246 binding.update() for binding in @select (b) -> b.key is key
235 247
236 # Cross-browser event binding. 248 # Rivets.Util
237 bindEvent = (el, event, handler, context) -> 249 # -----------
250
251 # Houses common utility functions used internally by Rivets.js.
252 Rivets.Util =
253 # Create a single DOM event binding.
254 bindEvent: (el, event, handler, context) ->
238 fn = (e) -> handler.call context, e 255 fn = (e) -> handler.call context, e
239 256
240 # Check to see if jQuery is loaded.
241 if window.jQuery? 257 if window.jQuery?
242 el = jQuery el 258 el = jQuery el
243 if el.on? then el.on event, fn else el.bind event, fn 259 if el.on? then el.on event, fn else el.bind event, fn
244 # Check to see if addEventListener is available.
245 else if window.addEventListener? 260 else if window.addEventListener?
246 el.addEventListener event, fn, false 261 el.addEventListener event, fn, false
247 else 262 else
248 # Assume we are in IE and use attachEvent.
249 event = 'on' + event 263 event = 'on' + event
250 el.attachEvent event, fn 264 el.attachEvent event, fn
251 265
252 fn 266 fn
253 267
254 # Cross-browser event unbinding. 268 # Remove a single DOM event binding.
255 unbindEvent = (el, event, fn) -> 269 unbindEvent: (el, event, fn) ->
256 # Check to see if jQuery is loaded.
257 if window.jQuery? 270 if window.jQuery?
258 el = jQuery el 271 el = jQuery el
259 if el.off? then el.off event, fn else el.unbind event, fn 272 if el.off? then el.off event, fn else el.unbind event, fn
260 # Check to see if addEventListener is available.
261 else if window.removeEventListener 273 else if window.removeEventListener
262 el.removeEventListener event, fn, false 274 el.removeEventListener event, fn, false
263 else 275 else
264 # Assume we are in IE and use attachEvent.
265 event = 'on' + event 276 event = 'on' + event
266 el.detachEvent event, fn 277 el.detachEvent event, fn
267 278
268 # Cross-browser input value getter. 279 # Get the current value of an input node.
269 getInputValue = (el) -> 280 getInputValue: (el) ->
270 if window.jQuery? 281 if window.jQuery?
271 el = jQuery el 282 el = jQuery el
272 283
...@@ -279,7 +290,12 @@ getInputValue = (el) -> ...@@ -279,7 +290,12 @@ getInputValue = (el) ->
279 when 'select-multiple' then o.value for o in el when o.selected 290 when 'select-multiple' then o.value for o in el when o.selected
280 else el.value 291 else el.value
281 292
282 # Core binding routines. 293 # Rivets.binders
294 # --------------
295
296 # Core binders that are included with Rivets.js, publicly available on
297 # `module.binders`. Can be overridden globally or local to a `Rivets.View`
298 # instance.
283 Rivets.binders = 299 Rivets.binders =
284 enabled: (el, value) -> 300 enabled: (el, value) ->
285 el.disabled = !value 301 el.disabled = !value
...@@ -290,9 +306,9 @@ Rivets.binders = ...@@ -290,9 +306,9 @@ Rivets.binders =
290 checked: 306 checked:
291 publishes: true 307 publishes: true
292 bind: (el) -> 308 bind: (el) ->
293 @currentListener = bindEvent el, 'change', @publish 309 @currentListener = Rivets.Util.bindEvent el, 'change', @publish
294 unbind: (el) -> 310 unbind: (el) ->
295 unbindEvent el, 'change', @currentListener 311 Rivets.Util.unbindEvent el, 'change', @currentListener
296 routine: (el, value) -> 312 routine: (el, value) ->
297 if el.type is 'radio' 313 if el.type is 'radio'
298 el.checked = el.value?.toString() is value?.toString() 314 el.checked = el.value?.toString() is value?.toString()
...@@ -302,9 +318,9 @@ Rivets.binders = ...@@ -302,9 +318,9 @@ Rivets.binders =
302 unchecked: 318 unchecked:
303 publishes: true 319 publishes: true
304 bind: (el) -> 320 bind: (el) ->
305 @currentListener = bindEvent el, 'change', @publish 321 @currentListener = Rivets.Util.bindEvent el, 'change', @publish
306 unbind: (el) -> 322 unbind: (el) ->
307 unbindEvent el, 'change', @currentListener 323 Rivets.Util.unbindEvent el, 'change', @currentListener
308 routine: (el, value) -> 324 routine: (el, value) ->
309 if el.type is 'radio' 325 if el.type is 'radio'
310 el.checked = el.value?.toString() isnt value?.toString() 326 el.checked = el.value?.toString() isnt value?.toString()
...@@ -323,9 +339,9 @@ Rivets.binders = ...@@ -323,9 +339,9 @@ Rivets.binders =
323 value: 339 value:
324 publishes: true 340 publishes: true
325 bind: (el) -> 341 bind: (el) ->
326 @currentListener = bindEvent el, 'change', @publish 342 @currentListener = Rivets.Util.bindEvent el, 'change', @publish
327 unbind: (el) -> 343 unbind: (el) ->
328 unbindEvent el, 'change', @currentListener 344 Rivets.Util.unbindEvent el, 'change', @currentListener
329 routine: (el, value) -> 345 routine: (el, value) ->
330 if window.jQuery? 346 if window.jQuery?
331 el = jQuery el 347 el = jQuery el
...@@ -347,8 +363,8 @@ Rivets.binders = ...@@ -347,8 +363,8 @@ Rivets.binders =
347 "on-*": 363 "on-*":
348 function: true 364 function: true
349 routine: (el, value) -> 365 routine: (el, value) ->
350 unbindEvent el, @args[0], @currentListener if @currentListener 366 Rivets.Util.unbindEvent el, @args[0], @currentListener if @currentListener
351 @currentListener = bindEvent el, @args[0], value, @model 367 @currentListener = Rivets.Util.bindEvent el, @args[0], value, @model
352 368
353 "each-*": 369 "each-*":
354 block: true 370 block: true
...@@ -400,15 +416,27 @@ Rivets.binders = ...@@ -400,15 +416,27 @@ Rivets.binders =
400 else 416 else
401 el.removeAttribute @type 417 el.removeAttribute @type
402 418
403 # Default configuration. 419 # Rivets.config
420 # -------------
421
422 # Default configuration, publicly accessible on `module.config`. Can be
423 # overridden globally or local to a `Rivets.View` instance.
404 Rivets.config = 424 Rivets.config =
405 preloadData: true 425 preloadData: true
406 426
407 # Default formatters. There aren't any. 427 # Rivets.formatters
428 # -----------------
429
430 # Default formatters (there aren't any), publicly accessible on
431 # `module.formatters`. Can be overridden globally or local to a `Rivets.View`
432 # instance.
408 Rivets.formatters = {} 433 Rivets.formatters = {}
409 434
410 # The rivets module. This is the public interface that gets exported. 435 # Rivets.factory
411 factory = (exports) -> 436 # --------------
437
438 # The Rivets.js module factory.
439 Rivets.factory = (exports) ->
412 # Exposes the core binding routines that can be extended or stripped down. 440 # Exposes the core binding routines that can be extended or stripped down.
413 exports.binders = Rivets.binders 441 exports.binders = Rivets.binders
414 442
...@@ -425,19 +453,22 @@ factory = (exports) -> ...@@ -425,19 +453,22 @@ factory = (exports) ->
425 Rivets.config[property] = value 453 Rivets.config[property] = value
426 return 454 return
427 455
428 # Binds a set of model objects to a parent DOM element. Returns a Rivets.View 456 # Binds a set of model objects to a parent DOM element and returns a
429 # instance. 457 # `Rivets.View` instance.
430 exports.bind = (el, models = {}, options = {}) -> 458 exports.bind = (el, models = {}, options = {}) ->
431 view = new Rivets.View(el, models, options) 459 view = new Rivets.View(el, models, options)
432 view.bind() 460 view.bind()
433 view 461 view
434 462
435 # Exports rivets for CommonJS, AMD and the browser. 463 # Export
464 # ------
465
466 # Exports Rivets.js for CommonJS, AMD and the browser.
436 if typeof exports == 'object' 467 if typeof exports == 'object'
437 factory(exports) 468 Rivets.factory(exports)
438 else if typeof define == 'function' && define.amd 469 else if typeof define == 'function' && define.amd
439 define ['exports'], (exports) -> 470 define ['exports'], (exports) ->
440 factory(@rivets = exports) 471 Rivets.factory(@rivets = exports)
441 return exports 472 return exports
442 else 473 else
443 factory(@rivets = {}) 474 Rivets.factory(@rivets = {})
......