twine-rails 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4386189c38efbea2da170dd03b7d30d11c69d0e7
4
- data.tar.gz: 90f46d3522191a2e65f21f9bc0accef50accc453
3
+ metadata.gz: 538a0c1b2f074d00d9402091cd8903e88a8c89f8
4
+ data.tar.gz: b966ba3ac32c35b34ab8cde4a05677e7d3b2ccfc
5
5
  SHA512:
6
- metadata.gz: a841a7bc1f7a30ddd0dd06dbb317f4aef580ae384865bf6a7f3df2c1789c36ef22df1bc4a4ece8501f4b6349100994bc0d6bb48f1cb5d79bf5172f58ed41c09c
7
- data.tar.gz: f66a43f275158666c7012acd90ca5a634c379ef8545c6255a6efb920f9cb82109c42ef7c7a98b492880949ea92af60eaab5f736acf5edffa490f247a44ea6194
6
+ metadata.gz: e272cf342cddbff047c8f3cff87f81a50631ab71559d3b17d7d12255689aa7fe72f1ed1b885060f04f1cb88f355a31efddf77ef5ae148a31977ce9c25438f099
7
+ data.tar.gz: 6d792404c98c19676b3d1f16b38d1e48874d4c691f8fe9c1a78e1b0a489c1475193ea1cf3181d994f018a3b6de1e90b83e4cd53d9ff75b31dfc40c98babe46f0
@@ -56,6 +56,7 @@
56
56
 
57
57
  bind = (context, node, indexes, forceSaveContext) ->
58
58
  currentBindingCallbacks = []
59
+ element = null
59
60
  if node.bindingId
60
61
  Twine.unbind(node)
61
62
 
@@ -69,13 +70,29 @@
69
70
  element = findOrCreateElementForNode(node)
70
71
  element.indexes = indexes
71
72
 
72
- for type, binding of Twine.bindingTypes when definition = Twine.getAttribute(node, type)
73
- element = findOrCreateElementForNode(node)
73
+ bindingConstructors = null
74
+ for attribute in node.attributes
75
+ type = attribute.name
76
+ type = type.slice(5) if isDataAttribute(type)
77
+
78
+ constructor = Twine.bindingTypes[type]
79
+ continue unless constructor
80
+
81
+ bindingConstructors ?= []
82
+ definition = attribute.value
83
+ if type == 'bind'
84
+ bindingConstructors.unshift([constructor, definition])
85
+ else
86
+ bindingConstructors.push([constructor, definition])
87
+
88
+ if bindingConstructors
89
+ element ?= findOrCreateElementForNode(node)
74
90
  element.bindings ?= []
75
91
  element.indexes ?= indexes
76
92
 
77
- fn = binding(node, context, definition, element)
78
- element.bindings.push(fn) if fn
93
+ for [constructor, definition] in bindingConstructors
94
+ binding = constructor(node, context, definition, element)
95
+ element.bindings.push(binding) if binding
79
96
 
80
97
  if newContextKey = Twine.getAttribute(node, 'context')
81
98
  keypath = keypathForKey(node, newContextKey)
@@ -85,7 +102,7 @@
85
102
  context = getValue(context, keypath) || setValue(context, keypath, {})
86
103
 
87
104
  if element || newContextKey || forceSaveContext
88
- element = findOrCreateElementForNode(node)
105
+ element ?= findOrCreateElementForNode(node)
89
106
  element.childContext = context
90
107
  element.indexes ?= indexes if indexes?
91
108
 
@@ -108,7 +125,6 @@
108
125
  findOrCreateElementForNode = (node) ->
109
126
  node.bindingId ?= ++nodeCount
110
127
  elements[node.bindingId] ?= {}
111
- elements[node.bindingId]
112
128
 
113
129
  # Queues a refresh of the DOM, batching up calls for the current synchronous block.
114
130
  Twine.refresh = ->
@@ -187,7 +203,7 @@
187
203
  addKey(rootContext) if node == rootNode
188
204
  keys.join('.')
189
205
 
190
- valueAttributeForNode = (node) ->
206
+ valuePropertyForNode = (node) ->
191
207
  name = node.nodeName.toLowerCase()
192
208
  if name in ['input', 'textarea', 'select']
193
209
  if node.getAttribute('type') in ['checkbox', 'radio'] then 'checked' else 'value'
@@ -232,14 +248,7 @@
232
248
  object[lastKey] = value
233
249
 
234
250
  stringifyNodeAttributes = (node) ->
235
- nAttributes = node.attributes.length
236
- i = 0
237
- result = ""
238
- while i < nAttributes
239
- attr = node.attributes.item(i)
240
- result += "#{attr.nodeName}='#{attr.textContent}'"
241
- i+=1
242
- result
251
+ [].map.call(node.attributes, (attr) -> "#{attr.name}=#{JSON.stringify(attr.value)}").join(' ')
243
252
 
244
253
  wrapFunctionString = (code, args, node) ->
245
254
  if isKeypath(code) && keypath = keypathForKey(node, code)
@@ -249,7 +258,7 @@
249
258
  ($context, $root) -> getValue($context, keypath)
250
259
  else
251
260
  code = "return #{code}"
252
- code = "with($arrayPointers) { #{code} }" if nodeHasArrayIndexes(node)
261
+ code = "with($arrayPointers) { #{code} }" if nodeArrayIndexes(node)
253
262
  code = "with($registry) { #{code} }" if requiresRegistry(args)
254
263
  try
255
264
  new Function(args, "with($context) { #{code} }")
@@ -258,14 +267,12 @@
258
267
 
259
268
  requiresRegistry = (args) -> /\$registry/.test(args)
260
269
 
261
- nodeHasArrayIndexes = (node) ->
262
- return unless node.bindingId?
263
- !!elements[node.bindingId]?.indexes?
270
+ nodeArrayIndexes = (node) ->
271
+ node.bindingId? && elements[node.bindingId]?.indexes
264
272
 
265
273
  arrayPointersForNode = (node, context) ->
266
- return {} unless node.bindingId?
267
- indexes = elements[node.bindingId]?.indexes
268
- return {} unless indexes?
274
+ indexes = nodeArrayIndexes(node)
275
+ return {} unless indexes
269
276
 
270
277
  result = {}
271
278
  for key, index of indexes
@@ -273,7 +280,14 @@
273
280
  result
274
281
 
275
282
  isKeypath = (value) ->
276
- value not in ['true', 'false', 'null', 'undefined'] and keypathRegex.test(value)
283
+ value not in ['true', 'false', 'null', 'undefined'] && keypathRegex.test(value)
284
+
285
+ isDataAttribute = (value) ->
286
+ value[0] == 'd' &&
287
+ value[1] == 'a' &&
288
+ value[2] == 't' &&
289
+ value[3] == 'a' &&
290
+ value[4] == '-'
277
291
 
278
292
  fireCustomChangeEvent = (node) ->
279
293
  event = document.createEvent('CustomEvent')
@@ -282,8 +296,8 @@
282
296
 
283
297
  Twine.bindingTypes =
284
298
  bind: (node, context, definition) ->
285
- valueAttribute = valueAttributeForNode(node)
286
- value = node[valueAttribute]
299
+ valueProp = valuePropertyForNode(node)
300
+ value = node[valueProp]
287
301
  lastValue = undefined
288
302
  teardown = undefined
289
303
 
@@ -296,9 +310,9 @@
296
310
  return if newValue == lastValue # return if we can and avoid a DOM operation
297
311
 
298
312
  lastValue = newValue
299
- return if newValue == node[valueAttribute]
313
+ return if newValue == node[valueProp]
300
314
 
301
- node[valueAttribute] = if checkedValueType then newValue == node.value else newValue
315
+ node[valueProp] = if checkedValueType then newValue == node.value else newValue
302
316
  fireCustomChangeEvent(node)
303
317
 
304
318
  return {refresh} unless isKeypath(definition)
@@ -308,10 +322,10 @@
308
322
  return unless node.checked
309
323
  setValue(context, keypath, node.value)
310
324
  else
311
- setValue(context, keypath, node[valueAttribute])
325
+ setValue(context, keypath, node[valueProp])
312
326
 
313
327
  keypath = keypathForKey(node, definition)
314
- twoWayBinding = valueAttribute != 'textContent' && node.type != 'hidden'
328
+ twoWayBinding = valueProp != 'textContent' && node.type != 'hidden'
315
329
 
316
330
  if keypath[0] == '$root'
317
331
  context = rootContext
@@ -322,7 +336,7 @@
322
336
 
323
337
  if twoWayBinding
324
338
  changeHandler = ->
325
- return if getValue(context, keypath) == this[valueAttribute]
339
+ return if getValue(context, keypath) == this[valueProp]
326
340
  refreshContext()
327
341
  Twine.refreshImmediately()
328
342
  $(node).on 'input keyup change', changeHandler
@@ -383,24 +397,24 @@
383
397
 
384
398
  indexes
385
399
 
386
- setupAttributeBinding = (attributeName, bindingName) ->
387
- booleanAttribute = attributeName in ['checked', 'indeterminate', 'disabled', 'readOnly']
400
+ setupPropertyBinding = (attributeName, bindingName) ->
401
+ booleanProp = attributeName in ['checked', 'indeterminate', 'disabled', 'readOnly']
388
402
 
389
- Twine.bindingTypes["bind-#{bindingName}"] = (node, context, definition) ->
403
+ Twine.bindingTypes["bind-#{bindingName.toLowerCase()}"] = (node, context, definition) ->
390
404
  fn = wrapFunctionString(definition, '$context,$root,$arrayPointers', node)
391
405
  lastValue = undefined
392
406
  return refresh: ->
393
407
  newValue = fn.call(node, context, rootContext, arrayPointersForNode(node, context))
394
- newValue = !!newValue if booleanAttribute
408
+ newValue = !!newValue if booleanProp
395
409
  return if newValue == lastValue
396
410
  node[attributeName] = lastValue = newValue
397
411
 
398
412
  fireCustomChangeEvent(node) if attributeName == 'checked'
399
413
 
400
414
  for attribute in ['placeholder', 'checked', 'indeterminate', 'disabled', 'href', 'title', 'readOnly', 'src']
401
- setupAttributeBinding(attribute, attribute)
415
+ setupPropertyBinding(attribute, attribute)
402
416
 
403
- setupAttributeBinding('innerHTML', 'unsafe-html')
417
+ setupPropertyBinding('innerHTML', 'unsafe-html')
404
418
 
405
419
  preventDefaultForEvent = (event) ->
406
420
  (event.type == 'submit' || event.currentTarget.nodeName.toLowerCase() == 'a') &&
@@ -1,5 +1,4 @@
1
1
  require "rails"
2
- require "active_support"
3
2
 
4
3
  require "twine-rails/version"
5
4
 
@@ -1,3 +1,3 @@
1
1
  module TwineRails
2
- VERSION = '1.0.0'
2
+ VERSION = '1.0.1'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twine-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Li
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-06-23 00:00:00.000000000 Z
13
+ date: 2016-07-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: coffee-rails
@@ -26,6 +26,20 @@ dependencies:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: railties
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
29
43
  - !ruby/object:Gem::Dependency
30
44
  name: bundler
31
45
  requirement: !ruby/object:Gem::Requirement
@@ -86,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
100
  version: '0'
87
101
  requirements: []
88
102
  rubyforge_project:
89
- rubygems_version: 2.5.1
103
+ rubygems_version: 2.4.5.1
90
104
  signing_key:
91
105
  specification_version: 4
92
106
  summary: Minimalistic two-way bindings