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 +4 -4
- data/lib/clearwater/version.rb +1 -1
- data/lib/clearwater.rb +1 -0
- data/opal/clearwater/cached_render.rb +1 -1
- data/opal/clearwater/component.rb +30 -16
- data/opal/clearwater/link.rb +3 -1
- data/opal/clearwater/virtual_dom/js/virtual_dom.js +80 -167
- data/opal/clearwater/virtual_dom.rb +41 -69
- metadata +5 -6
- data/opal/clearwater/model.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11ea030584d8c9bbc61d8d81690140cc88fa6a6b
|
4
|
+
data.tar.gz: 7a2dc906feb4e2c005f0521c1e842592466edd18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b166c268e598a8f5179c05d33200ac7656ed153f49bb0da56e1a7f3e0e5a6d06c79e3e47ecd10b1c0f7be84136e74b7aa2e88490568aa5fb4cf54f1007d13bb
|
7
|
+
data.tar.gz: 65fa07556d0afacd3a63bfce7e49cb1d992fd31860afa1dbf8a61a4841a31bb0aa8bc203a7ffe900f36daa3dfc38ba56979b73eb8bd69561ee26fab8f164fff0
|
data/lib/clearwater/version.rb
CHANGED
data/lib/clearwater.rb
CHANGED
@@ -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
|
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
|
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
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
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
|
data/opal/clearwater/link.rb
CHANGED
@@ -86,7 +86,9 @@ class Link
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def navigate event
|
89
|
-
|
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":
|
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":
|
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":
|
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":
|
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":
|
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
|
-
},{}],
|
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":
|
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":
|
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
|
-
},{}],
|
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
|
-
},{}],
|
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":
|
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":
|
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":
|
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
|
-
},{}],
|
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":
|
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
|
-
|
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 =
|
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":
|
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":
|
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":
|
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
|
-
},{}],
|
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":
|
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 =
|
937
|
-
var tagName = null;
|
826
|
+
var tagParts = splitTag(tag);
|
938
827
|
|
939
|
-
|
940
|
-
tagName = 'DIV';
|
941
|
-
}
|
828
|
+
var tagName = tagParts[0] || 'DIV';
|
942
829
|
|
943
830
|
var classes, part, type, i;
|
944
831
|
|
945
|
-
for (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 (
|
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
|
-
|
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":
|
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
|
-
},{}],
|
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
|
-
},{}],
|
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":
|
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":
|
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
|
-
},{}],
|
971
|
+
},{}],28:[function(require,module,exports){
|
1059
972
|
module.exports = "2"
|
1060
973
|
|
1061
|
-
},{}],
|
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":
|
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":
|
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":
|
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":
|
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":
|
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
|
5
|
-
def self.
|
6
|
-
|
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
|
-
|
11
|
-
|
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
|
-
|
28
|
-
|
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.
|
42
|
-
|
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 =
|
54
|
-
@tree
|
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
|
59
|
-
@root.inner_dom = @tree
|
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
|
-
|
70
|
-
|
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
|
-
|
94
|
-
|
61
|
+
module HashUtils
|
62
|
+
def self.camelize_keys(hash)
|
63
|
+
return hash unless hash.is_a? Hash
|
95
64
|
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
-
|
101
|
-
|
102
|
-
end
|
74
|
+
camelized[key] = value
|
75
|
+
end
|
103
76
|
|
104
|
-
|
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.
|
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-
|
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
|
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
|
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.
|
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
|
data/opal/clearwater/model.rb
DELETED
@@ -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
|