clearwater 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0dbe512477a239908316a57e35d45ee6071a644
4
- data.tar.gz: 1a1e20bb5da838c0e7abd7cb8f43394fde474763
3
+ metadata.gz: 11ea030584d8c9bbc61d8d81690140cc88fa6a6b
4
+ data.tar.gz: 7a2dc906feb4e2c005f0521c1e842592466edd18
5
5
  SHA512:
6
- metadata.gz: 974c1f2fba54d8cf8b0467fcaaae1ebfa4e92ad1ce419be6096dbe0869044ed402b24bf8fbb557b9ab44fa37ea0ed388f443bbddb97f1a6c0dcc60b8a4e5321a
7
- data.tar.gz: ff9e1f46a84c517f5984b0a7854add9ec298ef00dbbc206cede4b29866898b0b80d4c268e42d6af987bca27a3d565d4bf79330bd0e9fdf37c2df6f6587fa4edf
6
+ metadata.gz: 3b166c268e598a8f5179c05d33200ac7656ed153f49bb0da56e1a7f3e0e5a6d06c79e3e47ecd10b1c0f7be84136e74b7aa2e88490568aa5fb4cf54f1007d13bb
7
+ data.tar.gz: 65fa07556d0afacd3a63bfce7e49cb1d992fd31860afa1dbf8a61a4841a31bb0aa8bc203a7ffe900f36daa3dfc38ba56979b73eb8bd69561ee26fab8f164fff0
@@ -1,3 +1,3 @@
1
1
  module Clearwater
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/lib/clearwater.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "opal"
2
+ require "opal/browser"
2
3
 
3
4
  module Clearwater
4
5
  require_relative "clearwater/version"
@@ -1,7 +1,7 @@
1
1
  module Clearwater
2
2
  module CachedRender
3
3
  def cached_render
4
- if !@cached_render || should_render?
4
+ if !defined?(@cached_render) || should_render?
5
5
  @cached_render = sanitize_content(render)
6
6
  else
7
7
  @cached_render
@@ -141,6 +141,12 @@ module Clearwater
141
141
  end
142
142
 
143
143
  def tag tag_name, attributes=nil, content=nil
144
+ case attributes
145
+ when Array, Component, Numeric, String
146
+ content = attributes
147
+ attributes = nil
148
+ end
149
+
144
150
  VirtualDOM.node(
145
151
  tag_name,
146
152
  sanitize_attributes(attributes),
@@ -157,7 +163,7 @@ module Clearwater
157
163
  end
158
164
 
159
165
  def sanitize_attributes attributes
160
- return nil if attributes.nil?
166
+ return attributes unless attributes.is_a? Hash
161
167
 
162
168
  # Allow specifying `class` instead of `class_name`.
163
169
  # Note: `class_name` is still allowed
@@ -171,7 +177,7 @@ module Clearwater
171
177
  end
172
178
 
173
179
  attributes.each do |key, handler|
174
- if key.start_with? 'on'
180
+ if key[0, 2] == 'on'
175
181
  attributes[key] = proc do |event|
176
182
  handler.call(Browser::Event.new(event))
177
183
  end
@@ -182,20 +188,28 @@ module Clearwater
182
188
  end
183
189
 
184
190
  def sanitize_content content
185
- case content
186
- when Numeric, String
187
- content.to_s
188
- when Array
189
- content.map { |c| sanitize_content(c) }.compact
190
- else
191
- if content.respond_to? :cached_render
192
- content.cached_render
193
- elsif content.respond_to? :render
194
- sanitize_content content.render
195
- else
196
- content
197
- end
198
- end
191
+ %x{
192
+ if(content.$$class) {
193
+ if(content.$$class === Opal.Array) {
194
+ return #{content.map { |c| `self.$sanitize_content(c)` }};
195
+ } else if(content === Opal.nil) {
196
+ return '';
197
+ } else {
198
+ var cached_render = content.$cached_render;
199
+ var render = content.$render;
200
+
201
+ if(cached_render && !cached_render.$$stub) {
202
+ return content.$cached_render();
203
+ } else if(render && !render.$$stub) {
204
+ return self.$sanitize_content(content.$render());
205
+ } else {
206
+ return content;
207
+ }
208
+ }
209
+ } else {
210
+ return content;
211
+ }
212
+ }
199
213
  end
200
214
 
201
215
  def call &block
@@ -86,7 +86,9 @@ class Link
86
86
  end
87
87
 
88
88
  def navigate event
89
- unless event.meta? || event.shift? || event.ctrl? || event.alt?
89
+ # Don't handle middle-button clicks and clicks with modifier keys. Let them
90
+ # pass through to the browser's default handling or the user's modified handling.
91
+ unless event.meta? || event.shift? || event.ctrl? || event.alt? || (event.respond_to?(:button) && event.button == 1)
90
92
  event.prevent
91
93
  if href != $window.location.path
92
94
  $window.history.push href
@@ -3,17 +3,17 @@ var createElement = require("./vdom/create-element.js")
3
3
 
4
4
  module.exports = createElement
5
5
 
6
- },{"./vdom/create-element.js":14}],2:[function(require,module,exports){
6
+ },{"./vdom/create-element.js":13}],2:[function(require,module,exports){
7
7
  var diff = require("./vtree/diff.js")
8
8
 
9
9
  module.exports = diff
10
10
 
11
- },{"./vtree/diff.js":34}],3:[function(require,module,exports){
11
+ },{"./vtree/diff.js":33}],3:[function(require,module,exports){
12
12
  var h = require("./virtual-hyperscript/index.js")
13
13
 
14
14
  module.exports = h
15
15
 
16
- },{"./virtual-hyperscript/index.js":21}],4:[function(require,module,exports){
16
+ },{"./virtual-hyperscript/index.js":20}],4:[function(require,module,exports){
17
17
  var diff = require("./diff.js")
18
18
  var patch = require("./patch.js")
19
19
  var h = require("./h.js")
@@ -30,115 +30,7 @@ module.exports = {
30
30
  VText: VText
31
31
  }
32
32
 
33
- },{"./create-element.js":1,"./diff.js":2,"./h.js":3,"./patch.js":12,"./vnode/vnode.js":30,"./vnode/vtext.js":32}],5:[function(require,module,exports){
34
- /*!
35
- * Cross-Browser Split 1.1.1
36
- * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
37
- * Available under the MIT License
38
- * ECMAScript compliant, uniform cross-browser split method
39
- */
40
-
41
- /**
42
- * Splits a string into an array of strings using a regex or string separator. Matches of the
43
- * separator are not included in the result array. However, if `separator` is a regex that contains
44
- * capturing groups, backreferences are spliced into the result each time `separator` is matched.
45
- * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
46
- * cross-browser.
47
- * @param {String} str String to split.
48
- * @param {RegExp|String} separator Regex or string to use for separating the string.
49
- * @param {Number} [limit] Maximum number of items to include in the result array.
50
- * @returns {Array} Array of substrings.
51
- * @example
52
- *
53
- * // Basic use
54
- * split('a b c d', ' ');
55
- * // -> ['a', 'b', 'c', 'd']
56
- *
57
- * // With limit
58
- * split('a b c d', ' ', 2);
59
- * // -> ['a', 'b']
60
- *
61
- * // Backreferences in result array
62
- * split('..word1 word2..', /([a-z]+)(\d+)/i);
63
- * // -> ['..', 'word', '1', ' ', 'word', '2', '..']
64
- */
65
- module.exports = (function split(undef) {
66
-
67
- var nativeSplit = String.prototype.split,
68
- compliantExecNpcg = /()??/.exec("")[1] === undef,
69
- // NPCG: nonparticipating capturing group
70
- self;
71
-
72
- self = function(str, separator, limit) {
73
- // If `separator` is not a regex, use `nativeSplit`
74
- if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
75
- return nativeSplit.call(str, separator, limit);
76
- }
77
- var output = [],
78
- flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6
79
- (separator.sticky ? "y" : ""),
80
- // Firefox 3+
81
- lastLastIndex = 0,
82
- // Make `global` and avoid `lastIndex` issues by working with a copy
83
- separator = new RegExp(separator.source, flags + "g"),
84
- separator2, match, lastIndex, lastLength;
85
- str += ""; // Type-convert
86
- if (!compliantExecNpcg) {
87
- // Doesn't need flags gy, but they don't hurt
88
- separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
89
- }
90
- /* Values for `limit`, per the spec:
91
- * If undefined: 4294967295 // Math.pow(2, 32) - 1
92
- * If 0, Infinity, or NaN: 0
93
- * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
94
- * If negative number: 4294967296 - Math.floor(Math.abs(limit))
95
- * If other: Type-convert, then use the above rules
96
- */
97
- limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1
98
- limit >>> 0; // ToUint32(limit)
99
- while (match = separator.exec(str)) {
100
- // `separator.lastIndex` is not reliable cross-browser
101
- lastIndex = match.index + match[0].length;
102
- if (lastIndex > lastLastIndex) {
103
- output.push(str.slice(lastLastIndex, match.index));
104
- // Fix browsers whose `exec` methods don't consistently return `undefined` for
105
- // nonparticipating capturing groups
106
- if (!compliantExecNpcg && match.length > 1) {
107
- match[0].replace(separator2, function() {
108
- for (var i = 1; i < arguments.length - 2; i++) {
109
- if (arguments[i] === undef) {
110
- match[i] = undef;
111
- }
112
- }
113
- });
114
- }
115
- if (match.length > 1 && match.index < str.length) {
116
- Array.prototype.push.apply(output, match.slice(1));
117
- }
118
- lastLength = match[0].length;
119
- lastLastIndex = lastIndex;
120
- if (output.length >= limit) {
121
- break;
122
- }
123
- }
124
- if (separator.lastIndex === match.index) {
125
- separator.lastIndex++; // Avoid an infinite loop
126
- }
127
- }
128
- if (lastLastIndex === str.length) {
129
- if (lastLength || !separator.test("")) {
130
- output.push("");
131
- }
132
- } else {
133
- output.push(str.slice(lastLastIndex));
134
- }
135
- return output.length > limit ? output.slice(0, limit) : output;
136
- };
137
-
138
- return self;
139
- })();
140
-
141
- },{}],6:[function(require,module,exports){
33
+ },{"./create-element.js":1,"./diff.js":2,"./h.js":3,"./patch.js":11,"./vnode/vnode.js":29,"./vnode/vtext.js":31}],5:[function(require,module,exports){
142
34
  'use strict';
143
35
 
144
36
  var OneVersionConstraint = require('individual/one-version');
@@ -160,7 +52,7 @@ function EvStore(elem) {
160
52
  return hash;
161
53
  }
162
54
 
163
- },{"individual/one-version":8}],7:[function(require,module,exports){
55
+ },{"individual/one-version":7}],6:[function(require,module,exports){
164
56
  (function (global){
165
57
  'use strict';
166
58
 
@@ -183,7 +75,7 @@ function Individual(key, value) {
183
75
  }
184
76
 
185
77
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
186
- },{}],8:[function(require,module,exports){
78
+ },{}],7:[function(require,module,exports){
187
79
  'use strict';
188
80
 
189
81
  var Individual = require('./index.js');
@@ -207,7 +99,7 @@ function OneVersion(moduleName, version, defaultValue) {
207
99
  return Individual(key, defaultValue);
208
100
  }
209
101
 
210
- },{"./index.js":7}],9:[function(require,module,exports){
102
+ },{"./index.js":6}],8:[function(require,module,exports){
211
103
  (function (global){
212
104
  var topLevel = typeof global !== 'undefined' ? global :
213
105
  typeof window !== 'undefined' ? window : {}
@@ -226,14 +118,14 @@ if (typeof document !== 'undefined') {
226
118
  }
227
119
 
228
120
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
229
- },{"min-document":35}],10:[function(require,module,exports){
121
+ },{"min-document":34}],9:[function(require,module,exports){
230
122
  "use strict";
231
123
 
232
124
  module.exports = function isObject(x) {
233
125
  return typeof x === "object" && x !== null;
234
126
  };
235
127
 
236
- },{}],11:[function(require,module,exports){
128
+ },{}],10:[function(require,module,exports){
237
129
  var nativeIsArray = Array.isArray
238
130
  var toString = Object.prototype.toString
239
131
 
@@ -243,12 +135,12 @@ function isArray(obj) {
243
135
  return toString.call(obj) === "[object Array]"
244
136
  }
245
137
 
246
- },{}],12:[function(require,module,exports){
138
+ },{}],11:[function(require,module,exports){
247
139
  var patch = require("./vdom/patch.js")
248
140
 
249
141
  module.exports = patch
250
142
 
251
- },{"./vdom/patch.js":17}],13:[function(require,module,exports){
143
+ },{"./vdom/patch.js":16}],12:[function(require,module,exports){
252
144
  var isObject = require("is-object")
253
145
  var isHook = require("../vnode/is-vhook.js")
254
146
 
@@ -347,7 +239,7 @@ function getPrototype(value) {
347
239
  }
348
240
  }
349
241
 
350
- },{"../vnode/is-vhook.js":25,"is-object":10}],14:[function(require,module,exports){
242
+ },{"../vnode/is-vhook.js":24,"is-object":9}],13:[function(require,module,exports){
351
243
  var document = require("global/document")
352
244
 
353
245
  var applyProperties = require("./apply-properties")
@@ -395,7 +287,7 @@ function createElement(vnode, opts) {
395
287
  return node
396
288
  }
397
289
 
398
- },{"../vnode/handle-thunk.js":23,"../vnode/is-vnode.js":26,"../vnode/is-vtext.js":27,"../vnode/is-widget.js":28,"./apply-properties":13,"global/document":9}],15:[function(require,module,exports){
290
+ },{"../vnode/handle-thunk.js":22,"../vnode/is-vnode.js":25,"../vnode/is-vtext.js":26,"../vnode/is-widget.js":27,"./apply-properties":12,"global/document":8}],14:[function(require,module,exports){
399
291
  // Maps a virtual DOM tree onto a real DOM tree in an efficient manner.
400
292
  // We don't want to read all of the DOM nodes in the tree so we use
401
293
  // the in-order tree indexing to eliminate recursion down certain branches.
@@ -482,13 +374,12 @@ function ascending(a, b) {
482
374
  return a > b ? 1 : -1
483
375
  }
484
376
 
485
- },{}],16:[function(require,module,exports){
377
+ },{}],15:[function(require,module,exports){
486
378
  var applyProperties = require("./apply-properties")
487
379
 
488
380
  var isWidget = require("../vnode/is-widget.js")
489
381
  var VPatch = require("../vnode/vpatch.js")
490
382
 
491
- var render = require("./create-element")
492
383
  var updateWidget = require("./update-widget")
493
384
 
494
385
  module.exports = applyPatch
@@ -536,7 +427,7 @@ function removeNode(domNode, vNode) {
536
427
  }
537
428
 
538
429
  function insertNode(parentNode, vNode, renderOptions) {
539
- var newNode = render(vNode, renderOptions)
430
+ var newNode = renderOptions.render(vNode, renderOptions)
540
431
 
541
432
  if (parentNode) {
542
433
  parentNode.appendChild(newNode)
@@ -553,7 +444,7 @@ function stringPatch(domNode, leftVNode, vText, renderOptions) {
553
444
  newNode = domNode
554
445
  } else {
555
446
  var parentNode = domNode.parentNode
556
- newNode = render(vText, renderOptions)
447
+ newNode = renderOptions.render(vText, renderOptions)
557
448
 
558
449
  if (parentNode && newNode !== domNode) {
559
450
  parentNode.replaceChild(newNode, domNode)
@@ -570,7 +461,7 @@ function widgetPatch(domNode, leftVNode, widget, renderOptions) {
570
461
  if (updating) {
571
462
  newNode = widget.update(leftVNode, domNode) || domNode
572
463
  } else {
573
- newNode = render(widget, renderOptions)
464
+ newNode = renderOptions.render(widget, renderOptions)
574
465
  }
575
466
 
576
467
  var parentNode = domNode.parentNode
@@ -588,7 +479,7 @@ function widgetPatch(domNode, leftVNode, widget, renderOptions) {
588
479
 
589
480
  function vNodePatch(domNode, leftVNode, vNode, renderOptions) {
590
481
  var parentNode = domNode.parentNode
591
- var newNode = render(vNode, renderOptions)
482
+ var newNode = renderOptions.render(vNode, renderOptions)
592
483
 
593
484
  if (parentNode && newNode !== domNode) {
594
485
  parentNode.replaceChild(newNode, domNode)
@@ -636,16 +527,21 @@ function replaceRoot(oldRoot, newRoot) {
636
527
  return newRoot;
637
528
  }
638
529
 
639
- },{"../vnode/is-widget.js":28,"../vnode/vpatch.js":31,"./apply-properties":13,"./create-element":14,"./update-widget":18}],17:[function(require,module,exports){
530
+ },{"../vnode/is-widget.js":27,"../vnode/vpatch.js":30,"./apply-properties":12,"./update-widget":17}],16:[function(require,module,exports){
640
531
  var document = require("global/document")
641
532
  var isArray = require("x-is-array")
642
533
 
534
+ var render = require("./create-element")
643
535
  var domIndex = require("./dom-index")
644
536
  var patchOp = require("./patch-op")
645
537
  module.exports = patch
646
538
 
647
- function patch(rootNode, patches) {
648
- return patchRecursive(rootNode, patches)
539
+ function patch(rootNode, patches, renderOptions) {
540
+ renderOptions = renderOptions || {}
541
+ renderOptions.patch = renderOptions.patch || patchRecursive
542
+ renderOptions.render = renderOptions.render || render
543
+
544
+ return renderOptions.patch(rootNode, patches, renderOptions)
649
545
  }
650
546
 
651
547
  function patchRecursive(rootNode, patches, renderOptions) {
@@ -658,11 +554,8 @@ function patchRecursive(rootNode, patches, renderOptions) {
658
554
  var index = domIndex(rootNode, patches.a, indices)
659
555
  var ownerDocument = rootNode.ownerDocument
660
556
 
661
- if (!renderOptions) {
662
- renderOptions = { patch: patchRecursive }
663
- if (ownerDocument !== document) {
664
- renderOptions.document = ownerDocument
665
- }
557
+ if (!renderOptions.document && ownerDocument !== document) {
558
+ renderOptions.document = ownerDocument
666
559
  }
667
560
 
668
561
  for (var i = 0; i < indices.length; i++) {
@@ -714,7 +607,7 @@ function patchIndices(patches) {
714
607
  return indices
715
608
  }
716
609
 
717
- },{"./dom-index":15,"./patch-op":16,"global/document":9,"x-is-array":11}],18:[function(require,module,exports){
610
+ },{"./create-element":13,"./dom-index":14,"./patch-op":15,"global/document":8,"x-is-array":10}],17:[function(require,module,exports){
718
611
  var isWidget = require("../vnode/is-widget.js")
719
612
 
720
613
  module.exports = updateWidget
@@ -731,7 +624,7 @@ function updateWidget(a, b) {
731
624
  return false
732
625
  }
733
626
 
734
- },{"../vnode/is-widget.js":28}],19:[function(require,module,exports){
627
+ },{"../vnode/is-widget.js":27}],18:[function(require,module,exports){
735
628
  'use strict';
736
629
 
737
630
  var EvStore = require('ev-store');
@@ -760,7 +653,7 @@ EvHook.prototype.unhook = function(node, propertyName) {
760
653
  es[propName] = undefined;
761
654
  };
762
655
 
763
- },{"ev-store":6}],20:[function(require,module,exports){
656
+ },{"ev-store":5}],19:[function(require,module,exports){
764
657
  'use strict';
765
658
 
766
659
  module.exports = SoftSetHook;
@@ -779,7 +672,7 @@ SoftSetHook.prototype.hook = function (node, propertyName) {
779
672
  }
780
673
  };
781
674
 
782
- },{}],21:[function(require,module,exports){
675
+ },{}],20:[function(require,module,exports){
783
676
  'use strict';
784
677
 
785
678
  var isArray = require('x-is-array');
@@ -845,6 +738,8 @@ function h(tagName, properties, children) {
845
738
  function addChild(c, childNodes, tag, props) {
846
739
  if (typeof c === 'string') {
847
740
  childNodes.push(new VText(c));
741
+ } else if (typeof c === 'number') {
742
+ childNodes.push(new VText(String(c)));
848
743
  } else if (isChild(c)) {
849
744
  childNodes.push(c);
850
745
  } else if (isArray(c)) {
@@ -916,14 +811,9 @@ function errorString(obj) {
916
811
  }
917
812
  }
918
813
 
919
- },{"../vnode/is-thunk":24,"../vnode/is-vhook":25,"../vnode/is-vnode":26,"../vnode/is-vtext":27,"../vnode/is-widget":28,"../vnode/vnode.js":30,"../vnode/vtext.js":32,"./hooks/ev-hook.js":19,"./hooks/soft-set-hook.js":20,"./parse-tag.js":22,"x-is-array":11}],22:[function(require,module,exports){
814
+ },{"../vnode/is-thunk":23,"../vnode/is-vhook":24,"../vnode/is-vnode":25,"../vnode/is-vtext":26,"../vnode/is-widget":27,"../vnode/vnode.js":29,"../vnode/vtext.js":31,"./hooks/ev-hook.js":18,"./hooks/soft-set-hook.js":19,"./parse-tag.js":21,"x-is-array":10}],21:[function(require,module,exports){
920
815
  'use strict';
921
816
 
922
- var split = require('browser-split');
923
-
924
- var classIdSplit = /([\.#]?[a-zA-Z0-9_:-]+)/;
925
- var notClassId = /^\.|#/;
926
-
927
817
  module.exports = parseTag;
928
818
 
929
819
  function parseTag(tag, props) {
@@ -933,16 +823,13 @@ function parseTag(tag, props) {
933
823
 
934
824
  var noId = !(props.hasOwnProperty('id'));
935
825
 
936
- var tagParts = split(tag, classIdSplit);
937
- var tagName = null;
826
+ var tagParts = splitTag(tag);
938
827
 
939
- if (notClassId.test(tagParts[1])) {
940
- tagName = 'DIV';
941
- }
828
+ var tagName = tagParts[0] || 'DIV';
942
829
 
943
830
  var classes, part, type, i;
944
831
 
945
- for (i = 0; i < tagParts.length; i++) {
832
+ for (i = 1; i < tagParts.length; i++) {
946
833
  part = tagParts[i];
947
834
 
948
835
  if (!part) {
@@ -951,9 +838,7 @@ function parseTag(tag, props) {
951
838
 
952
839
  type = part.charAt(0);
953
840
 
954
- if (!tagName) {
955
- tagName = part;
956
- } else if (type === '.') {
841
+ if (type === '.') {
957
842
  classes = classes || [];
958
843
  classes.push(part.substring(1, part.length));
959
844
  } else if (type === '#' && noId) {
@@ -972,7 +857,35 @@ function parseTag(tag, props) {
972
857
  return props.namespace ? tagName : tagName.toUpperCase();
973
858
  }
974
859
 
975
- },{"browser-split":5}],23:[function(require,module,exports){
860
+
861
+ function splitTag(tag) {
862
+
863
+ var classIndex, idIndex,
864
+ remaining = tag,
865
+ parts = [],
866
+ last = '';
867
+
868
+ do {
869
+ idIndex = remaining.indexOf('#');
870
+ classIndex = remaining.indexOf('.');
871
+ if ((idIndex === -1 || idIndex > classIndex) && classIndex !== -1) {
872
+ parts.push(last + remaining.substr(0, classIndex));
873
+ last = '.';
874
+ remaining = remaining.substr(classIndex + 1);
875
+ } else if (idIndex !== -1){
876
+ parts.push(last + remaining.substr(0, idIndex));
877
+ last = '#';
878
+ remaining = remaining.substr(idIndex + 1);
879
+ }
880
+
881
+ } while(idIndex !== -1 || classIndex !== -1)
882
+
883
+ parts.push(last + remaining);
884
+
885
+ return parts;
886
+ }
887
+
888
+ },{}],22:[function(require,module,exports){
976
889
  var isVNode = require("./is-vnode")
977
890
  var isVText = require("./is-vtext")
978
891
  var isWidget = require("./is-widget")
@@ -1014,14 +927,14 @@ function renderThunk(thunk, previous) {
1014
927
  return renderedThunk
1015
928
  }
1016
929
 
1017
- },{"./is-thunk":24,"./is-vnode":26,"./is-vtext":27,"./is-widget":28}],24:[function(require,module,exports){
930
+ },{"./is-thunk":23,"./is-vnode":25,"./is-vtext":26,"./is-widget":27}],23:[function(require,module,exports){
1018
931
  module.exports = isThunk
1019
932
 
1020
933
  function isThunk(t) {
1021
934
  return t && t.type === "Thunk"
1022
935
  }
1023
936
 
1024
- },{}],25:[function(require,module,exports){
937
+ },{}],24:[function(require,module,exports){
1025
938
  module.exports = isHook
1026
939
 
1027
940
  function isHook(hook) {
@@ -1030,7 +943,7 @@ function isHook(hook) {
1030
943
  typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook"))
1031
944
  }
1032
945
 
1033
- },{}],26:[function(require,module,exports){
946
+ },{}],25:[function(require,module,exports){
1034
947
  var version = require("./version")
1035
948
 
1036
949
  module.exports = isVirtualNode
@@ -1039,7 +952,7 @@ function isVirtualNode(x) {
1039
952
  return x && x.type === "VirtualNode" && x.version === version
1040
953
  }
1041
954
 
1042
- },{"./version":29}],27:[function(require,module,exports){
955
+ },{"./version":28}],26:[function(require,module,exports){
1043
956
  var version = require("./version")
1044
957
 
1045
958
  module.exports = isVirtualText
@@ -1048,17 +961,17 @@ function isVirtualText(x) {
1048
961
  return x && x.type === "VirtualText" && x.version === version
1049
962
  }
1050
963
 
1051
- },{"./version":29}],28:[function(require,module,exports){
964
+ },{"./version":28}],27:[function(require,module,exports){
1052
965
  module.exports = isWidget
1053
966
 
1054
967
  function isWidget(w) {
1055
968
  return w && w.type === "Widget"
1056
969
  }
1057
970
 
1058
- },{}],29:[function(require,module,exports){
971
+ },{}],28:[function(require,module,exports){
1059
972
  module.exports = "2"
1060
973
 
1061
- },{}],30:[function(require,module,exports){
974
+ },{}],29:[function(require,module,exports){
1062
975
  var version = require("./version")
1063
976
  var isVNode = require("./is-vnode")
1064
977
  var isWidget = require("./is-widget")
@@ -1132,7 +1045,7 @@ function VirtualNode(tagName, properties, children, key, namespace) {
1132
1045
  VirtualNode.prototype.version = version
1133
1046
  VirtualNode.prototype.type = "VirtualNode"
1134
1047
 
1135
- },{"./is-thunk":24,"./is-vhook":25,"./is-vnode":26,"./is-widget":28,"./version":29}],31:[function(require,module,exports){
1048
+ },{"./is-thunk":23,"./is-vhook":24,"./is-vnode":25,"./is-widget":27,"./version":28}],30:[function(require,module,exports){
1136
1049
  var version = require("./version")
1137
1050
 
1138
1051
  VirtualPatch.NONE = 0
@@ -1156,7 +1069,7 @@ function VirtualPatch(type, vNode, patch) {
1156
1069
  VirtualPatch.prototype.version = version
1157
1070
  VirtualPatch.prototype.type = "VirtualPatch"
1158
1071
 
1159
- },{"./version":29}],32:[function(require,module,exports){
1072
+ },{"./version":28}],31:[function(require,module,exports){
1160
1073
  var version = require("./version")
1161
1074
 
1162
1075
  module.exports = VirtualText
@@ -1168,7 +1081,7 @@ function VirtualText(text) {
1168
1081
  VirtualText.prototype.version = version
1169
1082
  VirtualText.prototype.type = "VirtualText"
1170
1083
 
1171
- },{"./version":29}],33:[function(require,module,exports){
1084
+ },{"./version":28}],32:[function(require,module,exports){
1172
1085
  var isObject = require("is-object")
1173
1086
  var isHook = require("../vnode/is-vhook")
1174
1087
 
@@ -1228,7 +1141,7 @@ function getPrototype(value) {
1228
1141
  }
1229
1142
  }
1230
1143
 
1231
- },{"../vnode/is-vhook":25,"is-object":10}],34:[function(require,module,exports){
1144
+ },{"../vnode/is-vhook":24,"is-object":9}],33:[function(require,module,exports){
1232
1145
  var isArray = require("x-is-array")
1233
1146
 
1234
1147
  var VPatch = require("../vnode/vpatch")
@@ -1657,7 +1570,7 @@ function appendPatch(apply, patch) {
1657
1570
  }
1658
1571
  }
1659
1572
 
1660
- },{"../vnode/handle-thunk":23,"../vnode/is-thunk":24,"../vnode/is-vnode":26,"../vnode/is-vtext":27,"../vnode/is-widget":28,"../vnode/vpatch":31,"./diff-props":33,"x-is-array":11}],35:[function(require,module,exports){
1573
+ },{"../vnode/handle-thunk":22,"../vnode/is-thunk":23,"../vnode/is-vnode":25,"../vnode/is-vtext":26,"../vnode/is-widget":27,"../vnode/vpatch":30,"./diff-props":32,"x-is-array":10}],34:[function(require,module,exports){
1661
1574
 
1662
1575
  },{}]},{},[4])(4)
1663
1576
  });
@@ -1,108 +1,80 @@
1
1
  require 'browser'
2
2
  require 'clearwater/virtual_dom/js/virtual_dom.js'
3
3
 
4
- module StringUtils
5
- def self.camelize string
6
- string.gsub(/_(\w)/) { |match| match.gsub(/_/, '').upcase }
4
+ module VirtualDOM
5
+ def self.node(tag_name, attributes, content)
6
+ content = sanitize_content(content)
7
+ attributes = HashUtils.camelize_keys(attributes).to_n
8
+ `virtualDom.h(tag_name, attributes, content)`
7
9
  end
8
- end
9
10
 
10
- module HashUtils
11
- def self.camelize_keys(hash)
12
- return nil if hash.nil?
13
-
14
- Hash[hash.map { |k,v|
15
- key = StringUtils.camelize(k)
16
- value = if Hash === v
17
- camelize_keys(v)
18
- else
19
- v
20
- end
21
-
22
- [key, value]
23
- }]
11
+ def self.diff first, second
12
+ `virtualDom.diff(first, second)`
24
13
  end
25
- end
26
14
 
27
- module VirtualDOM
28
- def self.node(tag_name, attributes, content)
29
- content = Array(content).map { |node|
30
- case node
31
- when Node
32
- node.node
33
- else
34
- node
35
- end
36
- }
37
- attributes = HashUtils.camelize_keys(attributes).to_n
38
- Node.new(`virtualDom.h(tag_name, attributes, content)`)
15
+ def self.patch node, diff
16
+ `virtualDom.patch(node, diff)`
39
17
  end
40
18
 
41
- def self.create_element node
42
- `virtualDom.create(node)`
19
+ def self.sanitize_content content
20
+ %x{
21
+ if(content === Opal.nil) return Opal.nil;
22
+ if(content.$$class === Opal.Array)
23
+ return #{content.map!{ |c| sanitize_content c }};
24
+ return content;
25
+ }
43
26
  end
44
27
 
45
28
  class Document
46
29
  def initialize(root=$document.create_element('div'))
47
30
  @root = root
48
- @rendered_nodes = {}
49
31
  end
50
32
 
51
33
  def render node
52
34
  if rendered?
53
- diff = @node.diff(node)
54
- @tree = Element.new(@tree.patch(diff))
35
+ diff = VirtualDOM.diff @node, node
36
+ VirtualDOM.patch @tree, diff
55
37
  @node = node
56
38
  else
57
39
  @node = node
58
- @tree = node.to_element
59
- @root.inner_dom = @tree.to_n
40
+ @tree = create_element(node)
41
+ @root.inner_dom = @tree
60
42
  @rendered = true
61
43
  end
62
44
  end
63
45
 
46
+ def create_element node
47
+ `virtualDom.create(node)`
48
+ end
49
+
64
50
  def rendered?
65
51
  @rendered
66
52
  end
67
53
  end
68
54
 
69
- class Node
70
- attr_reader :node
71
-
72
- def initialize(node)
73
- @node = node
74
- end
75
-
76
- def method_missing *args, &block
77
- node.send *args, &block
78
- end
79
-
80
- def to_element
81
- Element.new(VirtualDOM.create_element(node))
82
- end
83
-
84
- def diff other
85
- `virtualDom.diff(self.node, other.node)`
86
- end
87
-
88
- def patch diff
89
- `virtualDom.patch(#{to_element.to_n}, diff)`
55
+ module StringUtils
56
+ def self.camelize string
57
+ string.gsub(/_(\w)/) { |match| match.gsub(/_/, '').upcase }
90
58
  end
91
59
  end
92
60
 
93
- class Element
94
- attr_reader :element
61
+ module HashUtils
62
+ def self.camelize_keys(hash)
63
+ return hash unless hash.is_a? Hash
95
64
 
96
- def initialize(element)
97
- @element = element
98
- end
65
+ camelized = {}
66
+ hash.each do |k, v|
67
+ key = StringUtils.camelize(k)
68
+ value = if v.class == Hash
69
+ camelize_keys(v)
70
+ else
71
+ v
72
+ end
99
73
 
100
- def patch(diff)
101
- `virtualDom.patch(#{element}, diff)`
102
- end
74
+ camelized[key] = value
75
+ end
103
76
 
104
- def to_n
105
- @element
77
+ camelized
106
78
  end
107
79
  end
108
80
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clearwater
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamie Gaskins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-12 00:00:00.000000000 Z
11
+ date: 2015-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opal
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.7.0
19
+ version: '0.7'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.7.0
26
+ version: '0.7'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: opal-browser
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -139,7 +139,6 @@ files:
139
139
  - opal/clearwater/cgi.rb
140
140
  - opal/clearwater/component.rb
141
141
  - opal/clearwater/link.rb
142
- - opal/clearwater/model.rb
143
142
  - opal/clearwater/router.rb
144
143
  - opal/clearwater/router/route.rb
145
144
  - opal/clearwater/router/route_collection.rb
@@ -166,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
165
  version: '0'
167
166
  requirements: []
168
167
  rubyforge_project:
169
- rubygems_version: 2.4.6
168
+ rubygems_version: 2.4.8
170
169
  signing_key:
171
170
  specification_version: 4
172
171
  summary: Front-end web framework built on Opal
@@ -1,33 +0,0 @@
1
- require "clearwater/binding"
2
-
3
- module Clearwater
4
- class Model
5
- def initialize attributes={}
6
- @_bindings = Hash.new { |h,k| h[k] = [] }
7
- self.class.attributes.each do |attr|
8
- public_send "#{attr}=", attributes[attr]
9
- end
10
- end
11
-
12
- def add_binding attribute, &block
13
- binding = Binding.new(self, attribute, &block)
14
- @_bindings[attribute].delete_if(&:dead?)
15
- @_bindings[attribute] << binding
16
- binding
17
- end
18
-
19
- def self.attributes *args
20
- @attributes ||= []
21
- args.each do |attr|
22
- attr_reader attr
23
-
24
- define_method "#{attr}=" do |value|
25
- instance_variable_set "@#{attr}", value
26
- @_bindings[attr].each(&:call)
27
- @_bindings[attr].delete_if(&:dead?)
28
- end
29
- end
30
- @attributes.concat args
31
- end
32
- end
33
- end