tao_on_rails 0.1.1 → 0.2.0

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: 2b59124fa26b5e654fb672ef1fc59beee2a8b1aa
4
- data.tar.gz: d1ecab0813707fb29fce18a95fa4304395551dd4
3
+ metadata.gz: f8b45a9f5ea2544ee0e862a0fda2951823782acf
4
+ data.tar.gz: 0f0d0a4e37d370970168da6ea3713648345f8129
5
5
  SHA512:
6
- metadata.gz: 7d052ab6fa7224f82e04bcad380a1e7298669c91a968f2598112bb04758cb9e4c359bc85f72cb8a89dba74219128bf611533233582cc9a12d75287c844296727
7
- data.tar.gz: 71089fae4c210927397d969e9ccc88192d84b17b62610ac25727b8c2829cf1d392e493e093bc3e60369b26b2ef9911006c41dbe1961c3818debb3134fc62a999
6
+ metadata.gz: 401af2ff83fcc21a8cbb43bdbb60582f392b311ef2509dd7cfe4c61c3f1cf6c5411c37bdf68f47fda4ef3092308b202bdb1286e9df14e1095ce4cf4ac70b10f1
7
+ data.tar.gz: a724d766fa57de46db680b9397c96779ca24de274eeb9d36738fca24bfff297273fe19cbbbaa354658afcf2de4ee1611ac1ebd34a4ac4286b9898e70825e1768
@@ -1,5 +1,5 @@
1
1
  module TaoOnRails
2
2
  module Rails
3
- VERSION = "0.1.1"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -1,55 +1,54 @@
1
1
  namespace :tao do
2
- namespace :svg_icons do
3
- desc 'generate svg icons.'
4
- task :generate => :environment do
5
- Dir.mkdir "#{Rails.root}/vendor/assets/javascripts/tao"
6
-
7
- File.open "#{Rails.root}/vendor/assets/javascripts/tao/icons.coffee", 'w' do |f|
8
- f.puts %{tao.iconsHtml = '''#{svg_html}'''}
9
- end
10
- end
11
2
 
12
- private
3
+ desc 'generate svg icons.'
4
+ task :generate_icons => :environment do
5
+ Dir.mkdir "#{Rails.root}/vendor/assets/javascripts/tao"
13
6
 
14
- def svg_html
15
- %{<svg id="tao-icons" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none">\n#{symbols}</svg>}
7
+ File.open "#{Rails.root}/vendor/assets/javascripts/tao/icons.coffee", 'w' do |f|
8
+ f.puts %{tao.iconsHtml = '''#{svg_html}'''}
16
9
  end
10
+ end
17
11
 
18
- def svg_files
19
- @svg_files ||= Dir.glob(File.expand_path("#{::Rails.root}/app/assets/icons/*.svg")).uniq
20
- end
12
+ private
21
13
 
22
- def symbols
23
- svg_files.map {|file| " #{symbol(file)}\n"}.join
24
- end
14
+ def svg_html
15
+ %{<svg id="tao-icons" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none">\n#{symbols}</svg>}
16
+ end
25
17
 
26
- def symbol(path)
27
- name = File.basename(path, ".*").underscore().dasherize()
28
- content = File.read(path)
29
- content.gsub(/<?.+\?>/,'')
30
- .gsub(/<!.+?>/,'')
31
- .gsub(/<title>.*<\/title>/, '')
32
- .gsub(/<desc>.*<\/desc>/, '')
33
- .gsub(/id=/,'class=')
34
- .gsub(/<svg.+?>/, %Q{<svg id="icon-#{name}" #{dimensions(content)}>})
35
- .gsub(/svg/,'symbol')
36
- .gsub(/\n/, '') # Remove endlines
37
- .gsub(/\s{2,}/, ' ') # Remove whitespace
38
- .gsub(/>\s+</, '><') # Remove whitespace between tags
39
- end
18
+ def svg_files
19
+ @svg_files ||= Dir.glob(File.expand_path("#{::Rails.root}/app/assets/icons/*.svg")).uniq
20
+ end
40
21
 
41
- def dimensions(content)
42
- dimension = content.scan(/<svg.+(viewBox=["'](.+?)["'])/).flatten
43
- viewbox = dimension.first
44
- #coords = dimension.last.split(' ')
45
-
46
- #width = coords[2].to_i - coords[0].to_i
47
- #height = coords[3].to_i - coords[1].to_i
48
- #hack android svg
49
- width = '100%'
50
- height = '100%'
51
- %Q{#{viewbox} width="#{width}" height="#{height}"}
52
- end
22
+ def symbols
23
+ svg_files.map {|file| " #{symbol(file)}\n"}.join
24
+ end
25
+
26
+ def symbol(path)
27
+ name = File.basename(path, ".*").underscore().dasherize()
28
+ content = File.read(path)
29
+ content.gsub(/<?.+\?>/,'')
30
+ .gsub(/<!.+?>/,'')
31
+ .gsub(/<title>.*<\/title>/, '')
32
+ .gsub(/<desc>.*<\/desc>/, '')
33
+ .gsub(/id=/,'class=')
34
+ .gsub(/<svg.+?>/, %Q{<svg id="icon-#{name}" #{dimensions(content)}>})
35
+ .gsub(/svg/,'symbol')
36
+ .gsub(/\n/, '') # Remove endlines
37
+ .gsub(/\s{2,}/, ' ') # Remove whitespace
38
+ .gsub(/>\s+</, '><') # Remove whitespace between tags
39
+ end
40
+
41
+ def dimensions(content)
42
+ dimension = content.scan(/<svg.+(viewBox=["'](.+?)["'])/).flatten
43
+ viewbox = dimension.first
44
+ #coords = dimension.last.split(' ')
45
+
46
+ #width = coords[2].to_i - coords[0].to_i
47
+ #height = coords[3].to_i - coords[1].to_i
48
+ #hack android svg
49
+ width = '100%'
50
+ height = '100%'
51
+ %Q{#{viewbox} width="#{width}" height="#{height}"}
53
52
  end
54
53
 
55
54
  end
@@ -0,0 +1,861 @@
1
+ //= require native-shim
2
+
3
+ 'use strict';
4
+
5
+ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
6
+
7
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8
+
9
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
10
+
11
+ //= require native-shim
12
+
13
+ /**
14
+ * @license
15
+ * Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
16
+ * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
17
+ * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
18
+ * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
19
+ * Code distributed by Google as part of the polymer project is also
20
+ * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
21
+ */
22
+
23
+ /**
24
+ * 2.3
25
+ * http://w3c.github.io/webcomponents/spec/custom/#dfn-element-definition
26
+ * @typedef {{
27
+ * name: string,
28
+ * localName: string,
29
+ * constructor: function(new:HTMLElement),
30
+ * connectedCallback: (Function|undefined),
31
+ * disconnectedCallback: (Function|undefined),
32
+ * attributeChangedCallback: (Function|undefined),
33
+ * observedAttributes: Array<string>,
34
+ * }}
35
+ */
36
+ var CustomElementDefinition = void 0;
37
+
38
+ /**
39
+ * @typedef {{
40
+ * resolve: !function(undefined),
41
+ * promise: !Promise<undefined>,
42
+ * }}
43
+ */
44
+ var Deferred = void 0;
45
+
46
+ (function () {
47
+ 'use strict';
48
+
49
+ var doc = document;
50
+ var win = window;
51
+
52
+ /**
53
+ * Gets 'customElement' from window so that it could be modified after
54
+ * the polyfill loads.
55
+ * @function
56
+ * @return {CustomElementRegistry}
57
+ */
58
+ var _customElements = function _customElements() {
59
+ return win['customElements'];
60
+ };
61
+
62
+ var _observerProp = '__$CE_observer';
63
+ var _attachedProp = '__$CE_attached';
64
+ var _upgradedProp = '__$CE_upgraded';
65
+
66
+ if (_customElements()) {
67
+ _customElements().flush = function () {};
68
+ if (!_customElements().forcePolyfill) {
69
+ nativeShim();
70
+ return;
71
+ }
72
+ }
73
+
74
+ // name validation
75
+ // https://html.spec.whatwg.org/multipage/scripting.html#valid-custom-element-name
76
+
77
+ /**
78
+ * @const
79
+ * @type {Array<string>}
80
+ */
81
+ var reservedTagList = ['annotation-xml', 'color-profile', 'font-face', 'font-face-src', 'font-face-uri', 'font-face-format', 'font-face-name', 'missing-glyph'];
82
+
83
+ /**
84
+ * @param {!string} name
85
+ * @return {!Error|undefined}
86
+ */
87
+ function checkValidCustomElementName(name) {
88
+ if (!(/^[a-z][.0-9_a-z]*-[\-.0-9_a-z]*$/.test(name) && reservedTagList.indexOf(name) === -1)) {
89
+ return new Error('The element name \'' + name + '\' is not valid.');
90
+ }
91
+ }
92
+
93
+ /**
94
+ * @param {!Node} root
95
+ * @return {TreeWalker}
96
+ */
97
+ function createTreeWalker(root) {
98
+ // IE 11 requires the third and fourth arguments be present. If the third
99
+ // arg is null, it applies the default behaviour. However IE also requires
100
+ // the fourth argument be present even though the other browsers ignore it.
101
+ return doc.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null, false);
102
+ }
103
+
104
+ /**
105
+ * @param {!Node} node
106
+ * @return {boolean}
107
+ */
108
+ function isElement(node) {
109
+ return node.nodeType === Node.ELEMENT_NODE;
110
+ }
111
+
112
+ /**
113
+ * @param {!Element} element
114
+ * @return {boolean}
115
+ */
116
+ function isHtmlImport(element) {
117
+ return element.tagName === 'LINK' && element.rel && element.rel.toLowerCase().split(' ').indexOf('import') !== -1;
118
+ }
119
+
120
+ /**
121
+ * @param {!Element} element
122
+ * @return {boolean}
123
+ */
124
+ function isConnected(element) {
125
+ var n = element;
126
+ do {
127
+ if (n[_attachedProp] || n.nodeType === Node.DOCUMENT_NODE) return true;
128
+ n = n.parentNode || n.nodeType === Node.DOCUMENT_FRAGMENT_NODE && n.host;
129
+ } while (n);
130
+ return false;
131
+ }
132
+
133
+ /**
134
+ * A registry of custom element definitions.
135
+ *
136
+ * See https://html.spec.whatwg.org/multipage/scripting.html#customelementsregistry
137
+ *
138
+ * @property {boolean} enableFlush Set to true to enable the flush() method
139
+ * to work. This should only be done for tests, as it causes a memory leak.
140
+ */
141
+
142
+ var CustomElementRegistry = function () {
143
+ function CustomElementRegistry() {
144
+ _classCallCheck(this, CustomElementRegistry);
145
+
146
+ /** @private {!Map<string, !CustomElementDefinition>} **/
147
+ this._definitions = new Map();
148
+
149
+ /** @private {!Map<Function, string>} **/
150
+ this._constructors = new Map();
151
+
152
+ /** @private {!Map<string, !Deferred>} **/
153
+ this._whenDefinedMap = new Map();
154
+
155
+ /** @private {!Set<!MutationObserver>} **/
156
+ this._observers = new Set();
157
+
158
+ /** @private {!MutationObserver} **/
159
+ this._attributeObserver = new MutationObserver(
160
+ /** @type {function(Array<MutationRecord>, MutationObserver)} */
161
+ this._handleAttributeChange.bind(this));
162
+
163
+ /** @private {?HTMLElement} **/
164
+ this._newInstance = null;
165
+
166
+ /** @private {!Set<string>} **/
167
+ this._pendingHtmlImportUrls = new Set();
168
+
169
+ /** @type {boolean} **/
170
+ this.enableFlush = true;
171
+
172
+ /** @private {boolean} **/
173
+ this._upgradeScheduled = false;
174
+
175
+ /** @type {MutationObserver} **/
176
+ this._mainDocumentObserver = null;
177
+ }
178
+
179
+ // HTML spec part 4.13.4
180
+ // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregistry-define
181
+ /**
182
+ * @param {string} name
183
+ * @param {function(new:HTMLElement)} constructor
184
+ * @param {{extends: string}} options
185
+ * @return {undefined}
186
+ */
187
+
188
+
189
+ _createClass(CustomElementRegistry, [{
190
+ key: 'define',
191
+ value: function define(name, constructor, options) {
192
+ // 1:
193
+ if (typeof constructor !== 'function') {
194
+ throw new TypeError('constructor must be a Constructor');
195
+ }
196
+
197
+ // 2. If constructor is an interface object whose corresponding interface
198
+ // either is HTMLElement or has HTMLElement in its set of inherited
199
+ // interfaces, throw a TypeError and abort these steps.
200
+ //
201
+ // It doesn't appear possible to check this condition from script
202
+
203
+ // 3:
204
+ var nameError = checkValidCustomElementName(name);
205
+ if (nameError) throw nameError;
206
+
207
+ // 4, 5:
208
+ // Note: we don't track being-defined names and constructors because
209
+ // define() isn't normally reentrant. The only time user code can run
210
+ // during define() is when getting callbacks off the prototype, which
211
+ // would be highly-unusual. We can make define() reentrant-safe if needed.
212
+ if (this._definitions.has(name)) {
213
+ throw new Error('An element with name \'' + name + '\' is already defined');
214
+ }
215
+
216
+ // 6, 7:
217
+ if (this._constructors.has(constructor)) {
218
+ throw new Error('Definition failed for \'' + name + '\': ' + 'The constructor is already used.');
219
+ }
220
+
221
+ // 8:
222
+ /** @type {string} */
223
+ var localName = name;
224
+
225
+ // 9, 10: We do not support extends currently.
226
+
227
+ // 11, 12, 13: Our define() isn't rentrant-safe
228
+
229
+ // 14.1:
230
+ /** @type {Object} */
231
+ var prototype = constructor.prototype;
232
+
233
+ // 14.2:
234
+ if ((typeof prototype === 'undefined' ? 'undefined' : _typeof(prototype)) !== 'object') {
235
+ throw new TypeError('Definition failed for \'' + name + '\': ' + 'constructor.prototype must be an object');
236
+ }
237
+
238
+ /**
239
+ * @param {string} callbackName
240
+ * @return {Function|undefined}
241
+ */
242
+ function getCallback(callbackName) {
243
+ var callback = prototype[callbackName];
244
+ if (callback !== undefined && typeof callback !== 'function') {
245
+ throw new Error(localName + ' \'' + callbackName + '\' is not a Function');
246
+ }
247
+ return callback;
248
+ }
249
+
250
+ // 3, 4:
251
+ var connectedCallback = getCallback('connectedCallback');
252
+
253
+ // 5, 6:
254
+ var disconnectedCallback = getCallback('disconnectedCallback');
255
+
256
+ // Divergence from spec: we always throw if attributeChangedCallback is
257
+ // not a function.
258
+
259
+ // 7, 9.1:
260
+ var attributeChangedCallback = getCallback('attributeChangedCallback');
261
+
262
+ // 8, 9.2, 9.3:
263
+ var observedAttributes = attributeChangedCallback && constructor['observedAttributes'] || [];
264
+
265
+ // 15:
266
+ /** @type {CustomElementDefinition} */
267
+ var definition = {
268
+ name: name,
269
+ localName: localName,
270
+ constructor: constructor,
271
+ connectedCallback: connectedCallback,
272
+ disconnectedCallback: disconnectedCallback,
273
+ attributeChangedCallback: attributeChangedCallback,
274
+ observedAttributes: observedAttributes
275
+ };
276
+
277
+ // 16:
278
+ this._definitions.set(localName, definition);
279
+ this._constructors.set(constructor, localName);
280
+
281
+ // 17, 18, 19:
282
+ this._upgradeDoc();
283
+
284
+ // 20:
285
+ /** @type {Deferred} **/
286
+ var deferred = this._whenDefinedMap.get(localName);
287
+ if (deferred) {
288
+ deferred.resolve(undefined);
289
+ this._whenDefinedMap.delete(localName);
290
+ }
291
+ }
292
+
293
+ /**
294
+ * Returns the constructor defined for `name`, or `null`.
295
+ *
296
+ * @param {string} name
297
+ * @return {Function|undefined}
298
+ */
299
+
300
+ }, {
301
+ key: 'get',
302
+ value: function get(name) {
303
+ // https://html.spec.whatwg.org/multipage/scripting.html#custom-elements-api
304
+ var def = this._definitions.get(name);
305
+ return def ? def.constructor : undefined;
306
+ }
307
+
308
+ /**
309
+ * Returns a `Promise` that resolves when a custom element for `name` has
310
+ * been defined.
311
+ *
312
+ * @param {string} name
313
+ * @return {!Promise}
314
+ */
315
+
316
+ }, {
317
+ key: 'whenDefined',
318
+ value: function whenDefined(name) {
319
+ // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregistry-whendefined
320
+ var nameError = checkValidCustomElementName(name);
321
+ if (nameError) return Promise.reject(nameError);
322
+ if (this._definitions.has(name)) return Promise.resolve();
323
+
324
+ /** @type {Deferred} **/
325
+ var deferred = this._whenDefinedMap.get(name);
326
+ if (deferred) return deferred.promise;
327
+
328
+ var resolve = void 0;
329
+ var promise = new Promise(function (_resolve, _) {
330
+ resolve = _resolve;
331
+ });
332
+ deferred = { promise: promise, resolve: resolve };
333
+ this._whenDefinedMap.set(name, deferred);
334
+ return promise;
335
+ }
336
+
337
+ /**
338
+ * Causes all pending mutation records to be processed, and thus all
339
+ * customization, upgrades and custom element reactions to be called.
340
+ * `enableFlush` must be true for this to work. Only use during tests!
341
+ */
342
+
343
+ }, {
344
+ key: 'flush',
345
+ value: function flush() {
346
+ if (this.enableFlush) {
347
+ // console.warn("flush!!!");
348
+ this._handleMutations(this._mainDocumentObserver.takeRecords());
349
+ this._handleAttributeChange(this._attributeObserver.takeRecords());
350
+ this._observers.forEach(
351
+ /**
352
+ * @param {!MutationObserver} observer
353
+ * @this {CustomElementRegistry}
354
+ */
355
+ function (observer) {
356
+ this._handleMutations(observer.takeRecords());
357
+ }, this);
358
+ }
359
+ }
360
+
361
+ /**
362
+ * Upgrade all existing in document elements. This process is expensive so
363
+ * is optionally batched based on the state of HTMLImports. (Note,
364
+ * this batching might not be necessary if instead of walking the dom,
365
+ * a map of upgrade candidates was maintained.)
366
+ * @private
367
+ */
368
+
369
+ }, {
370
+ key: '_upgradeDoc',
371
+ value: function _upgradeDoc() {
372
+ var _this2 = this;
373
+
374
+ if (!this._upgradeScheduled) {
375
+ this._upgradeScheduled = true;
376
+ var onReady = function onReady() {
377
+ _this2._upgradeScheduled = false;
378
+ if (!_this2._mainDocumentObserver) {
379
+ _this2._mainDocumentObserver = _this2._observeRoot(doc);
380
+ }
381
+ _this2._addNodes(doc.childNodes);
382
+ };
383
+ if (window['HTMLImports']) {
384
+ window['HTMLImports']['whenReady'](onReady);
385
+ } else {
386
+ onReady();
387
+ }
388
+ }
389
+ }
390
+
391
+ /**
392
+ * @param {?HTMLElement} instance
393
+ * @private
394
+ */
395
+
396
+ }, {
397
+ key: '_setNewInstance',
398
+ value: function _setNewInstance(instance) {
399
+ this._newInstance = instance;
400
+ }
401
+
402
+ /**
403
+ * Observes a DOM root for mutations that trigger upgrades and reactions.
404
+ * @param {Node} root
405
+ * @private
406
+ */
407
+
408
+ }, {
409
+ key: '_observeRoot',
410
+ value: function _observeRoot(root) {
411
+ // console.log('_observeRoot', root, root.baseURI);
412
+ // console.assert(!root[_observerProp]);
413
+ if (root[_observerProp] != null) {
414
+ //console.warn(`Root ${root} is already observed`);
415
+ return root[_observerProp];
416
+ }
417
+ root[_observerProp] = new MutationObserver(
418
+ /** @type {function(Array<MutationRecord>, MutationObserver)} */
419
+ this._handleMutations.bind(this));
420
+ root[_observerProp].observe(root, { childList: true, subtree: true });
421
+ if (this.enableFlush) {
422
+ // this is memory leak, only use in tests
423
+ this._observers.add(root[_observerProp]);
424
+ }
425
+ return root[_observerProp];
426
+ }
427
+
428
+ /**
429
+ * @param {Node} root
430
+ * @private
431
+ */
432
+
433
+ }, {
434
+ key: '_unobserveRoot',
435
+ value: function _unobserveRoot(root) {
436
+ if (root[_observerProp] != null) {
437
+ root[_observerProp].disconnect();
438
+ if (this.enableFlush) {
439
+ this._observers.delete(root[_observerProp]);
440
+ }
441
+ root[_observerProp] = null;
442
+ }
443
+ }
444
+
445
+ /**
446
+ * @param {!Array<!MutationRecord>} mutations
447
+ * @private
448
+ */
449
+
450
+ }, {
451
+ key: '_handleMutations',
452
+ value: function _handleMutations(mutations) {
453
+ for (var i = 0; i < mutations.length; i++) {
454
+ /** @type {!MutationRecord} */
455
+ var mutation = mutations[i];
456
+ if (mutation.type === 'childList') {
457
+ // Note: we can't get an ordering between additions and removals, and
458
+ // so might diverge from spec reaction ordering
459
+ var addedNodes = /** @type {!NodeList<!Node>} */mutation.addedNodes;
460
+ var removedNodes = /** @type {!NodeList<!Node>} */mutation.removedNodes;
461
+ this._removeNodes(removedNodes);
462
+ this._addNodes(addedNodes);
463
+ }
464
+ }
465
+ }
466
+
467
+ /**
468
+ * @param {!(NodeList<!Node>|Array<!Node>)} nodeList
469
+ * @param {?Set<Node>=} visitedNodes
470
+ * @private
471
+ */
472
+
473
+ }, {
474
+ key: '_addNodes',
475
+ value: function _addNodes(nodeList, visitedNodes) {
476
+ visitedNodes = visitedNodes || new Set();
477
+
478
+ for (var i = 0; i < nodeList.length; i++) {
479
+ var root = nodeList[i];
480
+
481
+ if (!isElement(root)) {
482
+ continue;
483
+ }
484
+
485
+ // Since we're adding this node to an observed tree, we can unobserve
486
+ this._unobserveRoot(root);
487
+
488
+ var walker = createTreeWalker(root);
489
+ do {
490
+ var node = /** @type {!HTMLElement} */walker.currentNode;
491
+ this._addElement(node, visitedNodes);
492
+ } while (walker.nextNode());
493
+ }
494
+ }
495
+
496
+ /**
497
+ * @param {!HTMLElement} element
498
+ * @param {!Set<Node>=} visitedNodes
499
+ */
500
+
501
+ }, {
502
+ key: '_addElement',
503
+ value: function _addElement(element, visitedNodes) {
504
+ if (visitedNodes.has(element)) return;
505
+ visitedNodes.add(element);
506
+
507
+ /** @type {?CustomElementDefinition} */
508
+ var definition = this._definitions.get(element.localName);
509
+ if (definition) {
510
+ if (!element[_upgradedProp]) {
511
+ this._upgradeElement(element, definition, true);
512
+ }
513
+ if (element[_upgradedProp] && !element[_attachedProp] && isConnected(element)) {
514
+ element[_attachedProp] = true;
515
+ if (definition.connectedCallback) {
516
+ definition.connectedCallback.call(element);
517
+ }
518
+ }
519
+ }
520
+ if (element.shadowRoot) {
521
+ // TODO(justinfagnani): do we need to check that the shadowRoot
522
+ // is observed?
523
+ this._addNodes(element.shadowRoot.childNodes, visitedNodes);
524
+ }
525
+ if (isHtmlImport(element)) {
526
+ this._addImport( /** @type {!HTMLLinkElement} */element, visitedNodes);
527
+ }
528
+ }
529
+
530
+ /**
531
+ * @param {!HTMLLinkElement} link
532
+ * @param {!Set<Node>=} visitedNodes
533
+ */
534
+
535
+ }, {
536
+ key: '_addImport',
537
+ value: function _addImport(link, visitedNodes) {
538
+ var _this3 = this;
539
+
540
+ // During a tree walk to add or upgrade nodes, we may encounter multiple
541
+ // HTML imports that reference the same document, and may encounter
542
+ // imports in various states of loading.
543
+
544
+ // First, we only want to process the first import for a document in a
545
+ // walk, so we check visitedNodes for the document, not the link.
546
+ //
547
+ // Second, for documents that haven't loaded yet, we only want to add one
548
+ // listener, regardless of the number of links or walks, so we track
549
+ // pending loads in _pendingHtmlImportUrls.
550
+
551
+ // Check to see if the import is loaded
552
+ /** @type {?Document} */
553
+ var _import = link.import;
554
+ if (_import) {
555
+ // The import is loaded, but only process the first link element
556
+ if (visitedNodes.has(_import)) return;
557
+ visitedNodes.add(_import);
558
+
559
+ // The import is loaded observe it
560
+ if (!_import[_observerProp]) this._observeRoot(_import);
561
+
562
+ // walk the document
563
+ this._addNodes(_import.childNodes, visitedNodes);
564
+ } else {
565
+ var _ret = function () {
566
+ // The import is not loaded, so wait for it
567
+ /** @type {string} */
568
+ var importUrl = link.href;
569
+ if (_this3._pendingHtmlImportUrls.has(importUrl)) return {
570
+ v: void 0
571
+ };
572
+ _this3._pendingHtmlImportUrls.add(importUrl);
573
+
574
+ /**
575
+ * @const
576
+ * @type {CustomElementRegistry}
577
+ */
578
+ var _this = _this3;
579
+ var onLoad = function onLoad() {
580
+ link.removeEventListener('load', /** @type {function(Event)} */onLoad);
581
+ if (!link.import[_observerProp]) _this._observeRoot(link.import);
582
+ // We don't pass visitedNodes because this is async and not part of
583
+ // the current tree walk.
584
+ _this._addNodes(link.import.childNodes);
585
+ };
586
+ link.addEventListener('load', onLoad);
587
+ }();
588
+
589
+ if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
590
+ }
591
+ }
592
+
593
+ /**
594
+ * @param {NodeList} nodeList
595
+ * @private
596
+ */
597
+
598
+ }, {
599
+ key: '_removeNodes',
600
+ value: function _removeNodes(nodeList) {
601
+ for (var i = 0; i < nodeList.length; i++) {
602
+ var root = nodeList[i];
603
+
604
+ if (!isElement(root)) {
605
+ continue;
606
+ }
607
+
608
+ // Since we're detatching this element from an observed root, we need to
609
+ // reobserve it.
610
+ // TODO(justinfagnani): can we do this in a microtask so we don't thrash
611
+ // on creating and destroying MutationObservers on batch DOM mutations?
612
+ this._observeRoot(root);
613
+
614
+ var walker = createTreeWalker(root);
615
+ do {
616
+ var node = walker.currentNode;
617
+ if (node[_upgradedProp] && node[_attachedProp]) {
618
+ node[_attachedProp] = false;
619
+ var definition = this._definitions.get(node.localName);
620
+ if (definition && definition.disconnectedCallback) {
621
+ definition.disconnectedCallback.call(node);
622
+ }
623
+ }
624
+ } while (walker.nextNode());
625
+ }
626
+ }
627
+
628
+ /**
629
+ * Upgrades or customizes a custom element.
630
+ *
631
+ * @param {HTMLElement} element
632
+ * @param {CustomElementDefinition} definition
633
+ * @param {boolean} callConstructor
634
+ * @private
635
+ */
636
+
637
+ }, {
638
+ key: '_upgradeElement',
639
+ value: function _upgradeElement(element, definition, callConstructor) {
640
+ var prototype = definition.constructor.prototype;
641
+ element.__proto__ = prototype;
642
+ if (callConstructor) {
643
+ this._setNewInstance(element);
644
+ new definition.constructor();
645
+ element[_upgradedProp] = true;
646
+ console.assert(this._newInstance == null);
647
+ }
648
+
649
+ var observedAttributes = definition.observedAttributes;
650
+ var attributeChangedCallback = definition.attributeChangedCallback;
651
+ if (attributeChangedCallback && observedAttributes.length > 0) {
652
+ this._attributeObserver.observe(element, {
653
+ attributes: true,
654
+ attributeOldValue: true,
655
+ attributeFilter: observedAttributes
656
+ });
657
+
658
+ // Trigger attributeChangedCallback for existing attributes.
659
+ // https://html.spec.whatwg.org/multipage/scripting.html#upgrades
660
+ for (var i = 0; i < observedAttributes.length; i++) {
661
+ var name = observedAttributes[i];
662
+ if (element.hasAttribute(name)) {
663
+ var value = element.getAttribute(name);
664
+ attributeChangedCallback.call(element, name, null, value, null);
665
+ }
666
+ }
667
+ }
668
+ }
669
+
670
+ /**
671
+ * @param {!Array<!MutationRecord>} mutations
672
+ * @private
673
+ */
674
+
675
+ }, {
676
+ key: '_handleAttributeChange',
677
+ value: function _handleAttributeChange(mutations) {
678
+ for (var i = 0; i < mutations.length; i++) {
679
+ var mutation = mutations[i];
680
+ if (mutation.type === 'attributes') {
681
+ var target = /** @type {HTMLElement} */mutation.target;
682
+ // We should be gaurenteed to have a definition because this mutation
683
+ // observer is only observing custom elements observedAttributes
684
+ var definition = this._definitions.get(target.localName);
685
+ var name = /** @type {!string} */mutation.attributeName;
686
+ var oldValue = mutation.oldValue;
687
+ var newValue = target.getAttribute(name);
688
+ // Skip changes that were handled synchronously by setAttribute
689
+ if (newValue !== oldValue) {
690
+ var namespace = mutation.attributeNamespace;
691
+ definition.attributeChangedCallback.call(target, name, oldValue, newValue, namespace);
692
+ }
693
+ }
694
+ }
695
+ }
696
+ }]);
697
+
698
+ return CustomElementRegistry;
699
+ }();
700
+
701
+ // Closure Compiler Exports
702
+
703
+
704
+ window['CustomElementRegistry'] = CustomElementRegistry;
705
+ CustomElementRegistry.prototype['define'] = CustomElementRegistry.prototype.define;
706
+ CustomElementRegistry.prototype['get'] = CustomElementRegistry.prototype.get;
707
+ CustomElementRegistry.prototype['whenDefined'] = CustomElementRegistry.prototype.whenDefined;
708
+ CustomElementRegistry.prototype['flush'] = CustomElementRegistry.prototype.flush;
709
+ CustomElementRegistry.prototype['polyfilled'] = true;
710
+ // TODO(justinfagnani): remove these in production code
711
+ CustomElementRegistry.prototype['_observeRoot'] = CustomElementRegistry.prototype._observeRoot;
712
+ CustomElementRegistry.prototype['_addImport'] = CustomElementRegistry.prototype._addImport;
713
+
714
+ // patch window.HTMLElement
715
+
716
+ /** @const */
717
+ var origHTMLElement = win.HTMLElement;
718
+ /**
719
+ * @type {function(new: HTMLElement)}
720
+ */
721
+ var newHTMLElement = function HTMLElement() {
722
+ var customElements = _customElements();
723
+
724
+ // If there's an being upgraded, return that
725
+ if (customElements._newInstance) {
726
+ var i = customElements._newInstance;
727
+ customElements._newInstance = null;
728
+ return i;
729
+ }
730
+ if (this.constructor) {
731
+ // Find the tagname of the constructor and create a new element with it
732
+ var tagName = customElements._constructors.get(this.constructor);
733
+ return _createElement(doc, tagName, undefined, false);
734
+ }
735
+ throw new Error('Unknown constructor. Did you call customElements.define()?');
736
+ };
737
+ win.HTMLElement = newHTMLElement;
738
+ win.HTMLElement.prototype = Object.create(origHTMLElement.prototype, {
739
+ constructor: { value: win.HTMLElement, configurable: true, writable: true }
740
+ });
741
+
742
+ // patch doc.createElement
743
+ // TODO(justinfagnani): why is the cast neccessary?
744
+ // Can we fix the Closure DOM externs?
745
+ var _origCreateElement =
746
+ /** @type {function(this:Document, string, (Object|undefined)=): !HTMLElement}}*/
747
+ doc.createElement;
748
+
749
+ /**
750
+ * Creates a new element and upgrades it if it's a custom element.
751
+ * @param {!Document} doc
752
+ * @param {!string} tagName
753
+ * @param {Object|undefined} options
754
+ * @param {boolean} callConstructor whether or not to call the elements
755
+ * constructor after upgrading. If an element is created by calling its
756
+ * constructor, then `callConstructor` should be false to prevent double
757
+ * initialization.
758
+ */
759
+ function _createElement(doc, tagName, options, callConstructor) {
760
+ var customElements = _customElements();
761
+ var element = options ? _origCreateElement.call(doc, tagName, options) : _origCreateElement.call(doc, tagName);
762
+ var definition = customElements._definitions.get(tagName.toLowerCase());
763
+ if (definition) {
764
+ customElements._upgradeElement(element, definition, callConstructor);
765
+ }
766
+ if (tagName.toLowerCase() !== 'html') {
767
+ customElements._observeRoot(element);
768
+ }
769
+ return element;
770
+ };
771
+ doc.createElement = function (tagName, options) {
772
+ return _createElement(doc, tagName, options, true);
773
+ };
774
+
775
+ // patch doc.createElementNS
776
+
777
+ var HTMLNS = 'http://www.w3.org/1999/xhtml';
778
+
779
+ /** @type {function(this:Document,string,string):Element} */
780
+ var _origCreateElementNS = doc.createElementNS;
781
+ doc.createElementNS =
782
+ /** @type {function(this:Document,(string|null),string):!Element} */
783
+ function (namespaceURI, qualifiedName) {
784
+ if (namespaceURI === 'http://www.w3.org/1999/xhtml') {
785
+ return doc.createElement(qualifiedName);
786
+ } else {
787
+ return _origCreateElementNS.call(doc, namespaceURI, qualifiedName);
788
+ }
789
+ };
790
+
791
+ // patch Element.attachShadow
792
+
793
+ /** @type {function({closed: boolean})} */
794
+ var _origAttachShadow = Element.prototype['attachShadow'];
795
+ if (_origAttachShadow) {
796
+ Object.defineProperty(Element.prototype, 'attachShadow', {
797
+ value: function value(options) {
798
+ /** @type {!Node} */
799
+ var root = _origAttachShadow.call(this, options);
800
+ /** @type {CustomElementRegistry} */
801
+ var customElements = _customElements();
802
+ customElements._observeRoot(root);
803
+ return root;
804
+ }
805
+ });
806
+ }
807
+
808
+ // patch doc.importNode
809
+
810
+ var rawImportNode = doc.importNode;
811
+ doc.importNode = function (node, deep) {
812
+ var clone = /** @type{!Node} */rawImportNode.call(doc, node, deep);
813
+ var customElements = _customElements();
814
+ var nodes = isElement(clone) ? [clone] : clone.childNodes;
815
+ /** @type {CustomElementRegistry} */_customElements()._addNodes(nodes);
816
+ return clone;
817
+ };
818
+
819
+ // patch Element.setAttribute & removeAttribute
820
+
821
+ var _origSetAttribute = Element.prototype.setAttribute;
822
+ Element.prototype['setAttribute'] = function (name, value) {
823
+ changeAttribute(this, name, value, _origSetAttribute);
824
+ };
825
+ var _origRemoveAttribute = Element.prototype.removeAttribute;
826
+ Element.prototype['removeAttribute'] = function (name) {
827
+ changeAttribute(this, name, null, _origRemoveAttribute);
828
+ };
829
+
830
+ function changeAttribute(element, name, value, operation) {
831
+ name = name.toLowerCase();
832
+ var oldValue = element.getAttribute(name);
833
+ operation.call(element, name, value);
834
+
835
+ // Bail if this wasn't a fully upgraded custom element
836
+ if (element[_upgradedProp] == true) {
837
+ var definition = _customElements()._definitions.get(element.localName);
838
+ var observedAttributes = definition.observedAttributes;
839
+ var attributeChangedCallback = definition.attributeChangedCallback;
840
+ if (attributeChangedCallback && observedAttributes.indexOf(name) >= 0) {
841
+ var newValue = element.getAttribute(name);
842
+ if (newValue !== oldValue) {
843
+ attributeChangedCallback.call(element, name, oldValue, newValue, null);
844
+ }
845
+ }
846
+ }
847
+ }
848
+
849
+ Object.defineProperty(window, 'customElements', {
850
+ value: new CustomElementRegistry(),
851
+ configurable: true,
852
+ enumerable: true
853
+ });
854
+
855
+ // TODO(justinfagnani): Remove. Temporary for backward-compatibility
856
+ window['CustomElements'] = {
857
+ takeRecords: function takeRecords() {
858
+ if (_customElements().flush) _customElements().flush();
859
+ }
860
+ };
861
+ })();
@@ -0,0 +1,90 @@
1
+
2
+ window.nativeShim = ->
3
+ eval '''
4
+ 'use strict';
5
+
6
+ const NativeHTMLElement = window.HTMLElement;
7
+ const nativeDefine = window.customElements.define;
8
+ const nativeGet = window.customElements.get;
9
+
10
+ /**
11
+ * Map of user-provided constructors to tag names.
12
+ *
13
+ * @type {Map<Function, string>}
14
+ */
15
+ const tagnameByConstructor = new Map();
16
+
17
+ /**
18
+ * Map of tag anmes to user-provided constructors.
19
+ *
20
+ * @type {Map<string, Function>}
21
+ */
22
+ const constructorByTagname = new Map();
23
+
24
+
25
+ /**
26
+ * Whether the constructors are being called by a browser process, ie parsing
27
+ * or createElement.
28
+ */
29
+ let browserConstruction = false;
30
+
31
+ /**
32
+ * Whether the constructors are being called by a user-space process, ie
33
+ * calling an element constructor.
34
+ */
35
+ let userConstruction = false;
36
+
37
+ window.HTMLElement = function() {
38
+ if (!browserConstruction) {
39
+ const tagname = tagnameByConstructor.get(this.constructor);
40
+ const fakeClass = nativeGet.call(window.customElements, tagname);
41
+
42
+ // Make sure that the fake constructor doesn't call back to this constructor
43
+ userConstruction = true;
44
+ const instance = new (fakeClass)();
45
+ return instance;
46
+ }
47
+ // Else do nothing. This will be reached by ES5-style classes doing
48
+ // HTMLElement.call() during initialization
49
+ browserConstruction = false;
50
+ };
51
+
52
+ window.HTMLElement.prototype = Object.create(NativeHTMLElement.prototype);
53
+ window.HTMLElement.prototype.constructor = window.HTMLElement;
54
+
55
+ window.customElements.define = (tagname, elementClass) => {
56
+ const elementProto = elementClass.prototype;
57
+ const StandInElement = class extends NativeHTMLElement {
58
+ constructor() {
59
+ // Call the native HTMLElement constructor, this gives us the
60
+ // under-construction instance as `this`:
61
+ super();
62
+
63
+ // The prototype will be wrong up because the browser used our fake
64
+ // class, so fix it:
65
+ Object.setPrototypeOf(this, elementProto);
66
+
67
+ if (!userConstruction) {
68
+ // Make sure that user-defined constructor bottom's out to a do-nothing
69
+ // HTMLElement() call
70
+ browserConstruction = true;
71
+ // Call the user-defined constructor on our instance:
72
+ elementClass.call(this);
73
+ }
74
+ userConstruction = false;
75
+ }
76
+ };
77
+ const standInProto = StandInElement.prototype;
78
+ StandInElement.observedAttributes = elementClass.observedAttributes;
79
+ standInProto.connectedCallback = elementProto.connectedCallback;
80
+ standInProto.disconnectedCallback = elementProto.disconnectedCallback;
81
+ standInProto.attributeChangedCallback = elementProto.attributeChangedCallback;
82
+ standInProto.adoptedCallback = elementProto.adoptedCallback;
83
+
84
+ tagnameByConstructor.set(elementClass, tagname);
85
+ constructorByTagname.set(tagname, elementClass);
86
+ nativeDefine.call(window.customElements, tagname, StandInElement);
87
+ };
88
+
89
+ window.customElements.get = (tagname) => constructorByTagname.get(tagname);
90
+ '''
@@ -5,6 +5,9 @@
5
5
  #= require i18n
6
6
 
7
7
  #= require_self
8
- #= require_tree ./tao
8
+ #= require_tree tao/application
9
+ #= require_tree tao/page
10
+ #= require_tree tao/helpers
11
+ #= require_tree tao/icons
9
12
 
10
13
  window.tao = {}
@@ -1,4 +1,6 @@
1
1
  #= require lodash
2
+ #= require custom-elements
3
+ #= require native-shim
2
4
 
3
5
  components = {}
4
6
 
@@ -60,6 +62,18 @@ TaoComponentBasedOn = (superClass = 'HTMLElement') ->
60
62
  attributeChangedCallback: (attrName, oldValue, newValue) ->
61
63
  @["#{_.camelCase attrName}Changed"]?(newValue, oldValue)
62
64
 
65
+ on: (args...) ->
66
+ $(@).on args...
67
+
68
+ off: (args...) ->
69
+ $(@).off args...
70
+
71
+ trigger: (args...) ->
72
+ $(@).triggerHandler(args...)
73
+
74
+ one: (args...) ->
75
+ $(@).one args...
76
+
63
77
  _init: ->
64
78
  # to be implemented
65
79
 
@@ -0,0 +1,2 @@
1
+
2
+ # generate this file by exec: rake tao:generate_icons
@@ -1,3 +1,42 @@
1
- #= require qing-module
1
+ class TaoModule
2
2
 
3
- window.TaoModule = QingModule
3
+ @extend: (obj) ->
4
+ unless obj and typeof obj == 'object'
5
+ throw new Error('TaoModule.extend: param should be an object')
6
+
7
+ for key, val of obj when key not in ['included', 'extended']
8
+ @[key] = val
9
+
10
+ obj.extended?.call(@)
11
+ @
12
+
13
+ @include: (obj) ->
14
+ unless obj and typeof obj == 'object'
15
+ throw new Error('TaoModule.include: param should be an object')
16
+
17
+ for key, val of obj when key not in ['included', 'extended']
18
+ @::[key] = val
19
+
20
+ obj.included?.call(@)
21
+ @
22
+
23
+ constructor: (opts) ->
24
+ @_setOptions opts
25
+ @_init()
26
+
27
+ _setOptions: (opts) ->
28
+ @opts = $.extend {}, TaoModule.opts, opts
29
+
30
+ _init: ->
31
+
32
+ on: (args...) ->
33
+ $(@).on args...
34
+
35
+ off: (args...) ->
36
+ $(@).off args...
37
+
38
+ trigger: (args...) ->
39
+ $(@).triggerHandler(args...)
40
+
41
+ one: (args...) ->
42
+ $(@).one args...
@@ -1,5 +1,2 @@
1
- /*
2
- *= require normalize-rails
3
- *= require_tree ./tao
4
- *
5
- */
1
+ //= require normalize-rails
2
+ //= require_tree tao/icons
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tao_on_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Siyuan Liu
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2016-12-01 00:00:00.000000000 Z
12
+ date: 2016-12-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -176,10 +176,13 @@ files:
176
176
  - lib/tao_on_rails/rails/version.rb
177
177
  - lib/tasks/tao_icons.rake
178
178
  - tao_on_rails.gemspec
179
+ - vendor/assets/javascripts/custom-elements.js
180
+ - vendor/assets/javascripts/native-shim.coffee
179
181
  - vendor/assets/javascripts/tao.coffee
180
182
  - vendor/assets/javascripts/tao/application.coffee
181
183
  - vendor/assets/javascripts/tao/component.coffee
182
184
  - vendor/assets/javascripts/tao/helpers.coffee
185
+ - vendor/assets/javascripts/tao/icons.coffee
183
186
  - vendor/assets/javascripts/tao/module.coffee
184
187
  - vendor/assets/javascripts/tao/page.coffee
185
188
  - vendor/assets/stylesheets/tao.scss