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,53 +245,57 @@ class Rivets.View ...@@ -233,53 +245,57 @@ 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 # -----------
238 fn = (e) -> handler.call context, e 250
239 251 # Houses common utility functions used internally by Rivets.js.
240 # Check to see if jQuery is loaded. 252 Rivets.Util =
241 if window.jQuery? 253 # Create a single DOM event binding.
242 el = jQuery el 254 bindEvent: (el, event, handler, context) ->
243 if el.on? then el.on event, fn else el.bind event, fn 255 fn = (e) -> handler.call context, e
244 # Check to see if addEventListener is available. 256
245 else if window.addEventListener? 257 if window.jQuery?
246 el.addEventListener event, fn, false 258 el = jQuery el
247 else 259 if el.on? then el.on event, fn else el.bind event, fn
248 # Assume we are in IE and use attachEvent. 260 else if window.addEventListener?
249 event = 'on' + event 261 el.addEventListener event, fn, false
250 el.attachEvent event, fn 262 else
251 263 event = 'on' + event
252 fn 264 el.attachEvent event, fn
253 265
254 # Cross-browser event unbinding. 266 fn
255 unbindEvent = (el, event, fn) -> 267
256 # Check to see if jQuery is loaded. 268 # Remove a single DOM event binding.
257 if window.jQuery? 269 unbindEvent: (el, event, fn) ->
258 el = jQuery el 270 if window.jQuery?
259 if el.off? then el.off event, fn else el.unbind event, fn 271 el = jQuery el
260 # Check to see if addEventListener is available. 272 if el.off? then el.off event, fn else el.unbind event, fn
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. 276 event = 'on' + event
265 event = 'on' + event 277 el.detachEvent event, fn
266 el.detachEvent event, fn 278
267 279 # Get the current value of an input node.
268 # Cross-browser input value getter. 280 getInputValue: (el) ->
269 getInputValue = (el) -> 281 if window.jQuery?
270 if window.jQuery? 282 el = jQuery el
271 el = jQuery el 283
272 284 switch el[0].type
273 switch el[0].type 285 when 'checkbox' then el.is ':checked'
274 when 'checkbox' then el.is ':checked' 286 else el.val()
275 else el.val() 287 else
276 else 288 switch el.type
277 switch el.type 289 when 'checkbox' then el.checked
278 when 'checkbox' then el.checked 290 when 'select-multiple' then o.value for o in el when o.selected
279 when 'select-multiple' then o.value for o in el when o.selected 291 else el.value
280 else el.value 292
281 293 # Rivets.binders
282 # Core binding routines. 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 = {})
......