OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The Polymer Authors. All rights reserved. | 2 * Copyright 2012 The Polymer Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style | 3 * Use of this source code is governed by a BSD-style |
4 * license that can be found in the LICENSE file. | 4 * license that can be found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 if (typeof WeakMap === 'undefined') { | 7 if (typeof WeakMap === 'undefined') { |
8 (function() { | 8 (function() { |
9 var defineProperty = Object.defineProperty; | 9 var defineProperty = Object.defineProperty; |
10 var counter = Date.now() % 1e9; | 10 var counter = Date.now() % 1e9; |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 objects.push(obj); | 487 objects.push(obj); |
488 } else if (objects.indexOf(obj) < 0) { | 488 } else if (objects.indexOf(obj) < 0) { |
489 objects.push(obj); | 489 objects.push(obj); |
490 Object.observe(obj, callback); | 490 Object.observe(obj, callback); |
491 } | 491 } |
492 | 492 |
493 observe(Object.getPrototypeOf(obj)); | 493 observe(Object.getPrototypeOf(obj)); |
494 } | 494 } |
495 | 495 |
496 function reset() { | 496 function reset() { |
497 resetScheduled = false; | |
498 if (!resetNeeded) | |
499 return; | |
500 | |
501 var objs = toRemove === emptyArray ? [] : toRemove; | 497 var objs = toRemove === emptyArray ? [] : toRemove; |
502 toRemove = objects; | 498 toRemove = objects; |
503 objects = objs; | 499 objects = objs; |
504 | 500 |
505 var observer; | 501 var observer; |
506 for (var id in observers) { | 502 for (var id in observers) { |
507 observer = observers[id]; | 503 observer = observers[id]; |
508 if (!observer || observer.state_ != OPENED) | 504 if (!observer || observer.state_ != OPENED) |
509 continue; | 505 continue; |
510 | 506 |
511 observer.iterateObjects_(observe); | 507 observer.iterateObjects_(observe); |
512 } | 508 } |
513 | 509 |
514 for (var i = 0; i < toRemove.length; i++) { | 510 for (var i = 0; i < toRemove.length; i++) { |
515 var obj = toRemove[i]; | 511 var obj = toRemove[i]; |
516 if (obj) | 512 if (obj) |
517 Object.unobserve(obj, callback); | 513 Object.unobserve(obj, callback); |
518 } | 514 } |
519 | 515 |
520 toRemove.length = 0; | 516 toRemove.length = 0; |
521 } | 517 } |
522 | 518 |
| 519 function scheduledReset() { |
| 520 resetScheduled = false; |
| 521 if (!resetNeeded) |
| 522 return; |
| 523 |
| 524 reset(); |
| 525 } |
| 526 |
523 function scheduleReset() { | 527 function scheduleReset() { |
524 if (resetScheduled) | 528 if (resetScheduled) |
525 return; | 529 return; |
526 | 530 |
527 resetNeeded = true; | 531 resetNeeded = true; |
528 resetScheduled = true; | 532 resetScheduled = true; |
529 runEOM(reset); | 533 runEOM(scheduledReset); |
530 } | 534 } |
531 | 535 |
532 function callback() { | 536 function callback() { |
| 537 reset(); |
| 538 |
533 var observer; | 539 var observer; |
534 | 540 |
535 for (var id in observers) { | 541 for (var id in observers) { |
536 observer = observers[id]; | 542 observer = observers[id]; |
537 if (!observer || observer.state_ != OPENED) | 543 if (!observer || observer.state_ != OPENED) |
538 continue; | 544 continue; |
539 | 545 |
540 observer.check_(); | 546 observer.check_(); |
541 } | 547 } |
542 | |
543 scheduleReset(); | |
544 } | 548 } |
545 | 549 |
546 var record = { | 550 var record = { |
547 object: undefined, | 551 object: undefined, |
548 objects: objects, | 552 objects: objects, |
549 open: function(obs) { | 553 open: function(obs) { |
550 observers[obs.id_] = obs; | 554 observers[obs.id_] = obs; |
551 observerCount++; | 555 observerCount++; |
552 obs.iterateObjects_(observe); | 556 obs.iterateObjects_(observe); |
553 }, | 557 }, |
(...skipping 1360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1914 | 1918 |
1915 addForwardingProperties(nativePrototype, wrapperPrototype); | 1919 addForwardingProperties(nativePrototype, wrapperPrototype); |
1916 if (opt_instance) | 1920 if (opt_instance) |
1917 registerInstanceProperties(wrapperPrototype, opt_instance); | 1921 registerInstanceProperties(wrapperPrototype, opt_instance); |
1918 defineProperty(wrapperPrototype, 'constructor', { | 1922 defineProperty(wrapperPrototype, 'constructor', { |
1919 value: wrapperConstructor, | 1923 value: wrapperConstructor, |
1920 configurable: true, | 1924 configurable: true, |
1921 enumerable: false, | 1925 enumerable: false, |
1922 writable: true | 1926 writable: true |
1923 }); | 1927 }); |
| 1928 // Set it again. Some VMs optimizes objects that are used as prototypes. |
| 1929 wrapperConstructor.prototype = wrapperPrototype; |
1924 } | 1930 } |
1925 | 1931 |
1926 function isWrapperFor(wrapperConstructor, nativeConstructor) { | 1932 function isWrapperFor(wrapperConstructor, nativeConstructor) { |
1927 return constructorTable.get(nativeConstructor.prototype) === | 1933 return constructorTable.get(nativeConstructor.prototype) === |
1928 wrapperConstructor; | 1934 wrapperConstructor; |
1929 } | 1935 } |
1930 | 1936 |
1931 /** | 1937 /** |
1932 * Creates a generic wrapper constructor based on |object| and its | 1938 * Creates a generic wrapper constructor based on |object| and its |
1933 * constructor. | 1939 * constructor. |
1934 * @param {Node} object | 1940 * @param {Node} object |
1935 * @return {Function} The generated constructor. | 1941 * @return {Function} The generated constructor. |
1936 */ | 1942 */ |
1937 function registerObject(object) { | 1943 function registerObject(object) { |
1938 var nativePrototype = Object.getPrototypeOf(object); | 1944 var nativePrototype = Object.getPrototypeOf(object); |
1939 | 1945 |
1940 var superWrapperConstructor = getWrapperConstructor(nativePrototype); | 1946 var superWrapperConstructor = getWrapperConstructor(nativePrototype); |
1941 var GeneratedWrapper = createWrapperConstructor(superWrapperConstructor); | 1947 var GeneratedWrapper = createWrapperConstructor(superWrapperConstructor); |
1942 registerInternal(nativePrototype, GeneratedWrapper, object); | 1948 registerInternal(nativePrototype, GeneratedWrapper, object); |
1943 | 1949 |
1944 return GeneratedWrapper; | 1950 return GeneratedWrapper; |
1945 } | 1951 } |
1946 | 1952 |
1947 function createWrapperConstructor(superWrapperConstructor) { | 1953 function createWrapperConstructor(superWrapperConstructor) { |
1948 function GeneratedWrapper(node) { | 1954 function GeneratedWrapper(node) { |
1949 superWrapperConstructor.call(this, node); | 1955 superWrapperConstructor.call(this, node); |
1950 } | 1956 } |
1951 GeneratedWrapper.prototype = | 1957 var p = Object.create(superWrapperConstructor.prototype); |
1952 Object.create(superWrapperConstructor.prototype); | 1958 p.constructor = GeneratedWrapper; |
1953 GeneratedWrapper.prototype.constructor = GeneratedWrapper; | 1959 GeneratedWrapper.prototype = p; |
1954 | 1960 |
1955 return GeneratedWrapper; | 1961 return GeneratedWrapper; |
1956 } | 1962 } |
1957 | 1963 |
1958 var OriginalDOMImplementation = window.DOMImplementation; | 1964 var OriginalDOMImplementation = window.DOMImplementation; |
1959 var OriginalEventTarget = window.EventTarget; | 1965 var OriginalEventTarget = window.EventTarget; |
1960 var OriginalEvent = window.Event; | 1966 var OriginalEvent = window.Event; |
1961 var OriginalNode = window.Node; | 1967 var OriginalNode = window.Node; |
1962 var OriginalWindow = window.Window; | 1968 var OriginalWindow = window.Window; |
1963 var OriginalRange = window.Range; | 1969 var OriginalRange = window.Range; |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2517 } | 2523 } |
2518 }; | 2524 }; |
2519 | 2525 |
2520 scope.enqueueMutation = enqueueMutation; | 2526 scope.enqueueMutation = enqueueMutation; |
2521 scope.registerTransientObservers = registerTransientObservers; | 2527 scope.registerTransientObservers = registerTransientObservers; |
2522 scope.wrappers.MutationObserver = MutationObserver; | 2528 scope.wrappers.MutationObserver = MutationObserver; |
2523 scope.wrappers.MutationRecord = MutationRecord; | 2529 scope.wrappers.MutationRecord = MutationRecord; |
2524 | 2530 |
2525 })(window.ShadowDOMPolyfill); | 2531 })(window.ShadowDOMPolyfill); |
2526 | 2532 |
| 2533 /** |
| 2534 * Copyright 2014 The Polymer Authors. All rights reserved. |
| 2535 * Use of this source code is goverened by a BSD-style |
| 2536 * license that can be found in the LICENSE file. |
| 2537 */ |
| 2538 |
| 2539 (function(scope) { |
| 2540 'use strict'; |
| 2541 |
| 2542 /** |
| 2543 * A tree scope represents the root of a tree. All nodes in a tree point to |
| 2544 * the same TreeScope object. The tree scope of a node get set the first time |
| 2545 * it is accessed or when a node is added or remove to a tree. |
| 2546 * @constructor |
| 2547 */ |
| 2548 function TreeScope(root, parent) { |
| 2549 this.root = root; |
| 2550 this.parent = parent; |
| 2551 } |
| 2552 |
| 2553 TreeScope.prototype = { |
| 2554 get renderer() { |
| 2555 if (this.root instanceof scope.wrappers.ShadowRoot) { |
| 2556 return scope.getRendererForHost(this.root.host); |
| 2557 } |
| 2558 return null; |
| 2559 }, |
| 2560 |
| 2561 contains: function(treeScope) { |
| 2562 for (; treeScope; treeScope = treeScope.parent) { |
| 2563 if (treeScope === this) |
| 2564 return true; |
| 2565 } |
| 2566 return false; |
| 2567 } |
| 2568 }; |
| 2569 |
| 2570 function setTreeScope(node, treeScope) { |
| 2571 if (node.treeScope_ !== treeScope) { |
| 2572 node.treeScope_ = treeScope; |
| 2573 for (var child = node.firstChild; child; child = child.nextSibling) { |
| 2574 setTreeScope(child, treeScope); |
| 2575 } |
| 2576 } |
| 2577 } |
| 2578 |
| 2579 function getTreeScope(node) { |
| 2580 if (node.treeScope_) |
| 2581 return node.treeScope_; |
| 2582 var parent = node.parentNode; |
| 2583 var treeScope; |
| 2584 if (parent) |
| 2585 treeScope = getTreeScope(parent); |
| 2586 else |
| 2587 treeScope = new TreeScope(node, null); |
| 2588 return node.treeScope_ = treeScope; |
| 2589 } |
| 2590 |
| 2591 scope.TreeScope = TreeScope; |
| 2592 scope.getTreeScope = getTreeScope; |
| 2593 scope.setTreeScope = setTreeScope; |
| 2594 |
| 2595 })(window.ShadowDOMPolyfill); |
| 2596 |
2527 // Copyright 2013 The Polymer Authors. All rights reserved. | 2597 // Copyright 2013 The Polymer Authors. All rights reserved. |
2528 // Use of this source code is goverened by a BSD-style | 2598 // Use of this source code is goverened by a BSD-style |
2529 // license that can be found in the LICENSE file. | 2599 // license that can be found in the LICENSE file. |
2530 | 2600 |
2531 (function(scope) { | 2601 (function(scope) { |
2532 'use strict'; | 2602 'use strict'; |
2533 | 2603 |
2534 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; | 2604 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; |
| 2605 var getTreeScope = scope.getTreeScope; |
2535 var mixin = scope.mixin; | 2606 var mixin = scope.mixin; |
2536 var registerWrapper = scope.registerWrapper; | 2607 var registerWrapper = scope.registerWrapper; |
2537 var unwrap = scope.unwrap; | 2608 var unwrap = scope.unwrap; |
2538 var wrap = scope.wrap; | 2609 var wrap = scope.wrap; |
2539 var wrappers = scope.wrappers; | 2610 var wrappers = scope.wrappers; |
2540 | 2611 |
2541 var wrappedFuns = new WeakMap(); | 2612 var wrappedFuns = new WeakMap(); |
2542 var listenersTable = new WeakMap(); | 2613 var listenersTable = new WeakMap(); |
2543 var handledEventsTable = new WeakMap(); | 2614 var handledEventsTable = new WeakMap(); |
2544 var currentlyDispatchingEvents = new WeakMap(); | 2615 var currentlyDispatchingEvents = new WeakMap(); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2679 } | 2750 } |
2680 | 2751 |
2681 function getInsertionParent(node) { | 2752 function getInsertionParent(node) { |
2682 return scope.insertionParentTable.get(node); | 2753 return scope.insertionParentTable.get(node); |
2683 } | 2754 } |
2684 | 2755 |
2685 function isDistributed(node) { | 2756 function isDistributed(node) { |
2686 return getInsertionParent(node); | 2757 return getInsertionParent(node); |
2687 } | 2758 } |
2688 | 2759 |
2689 function rootOfNode(node) { | 2760 function inSameTree(a, b) { |
2690 var p; | 2761 return getTreeScope(a) === getTreeScope(b); |
2691 while (p = node.parentNode) { | |
2692 node = p; | |
2693 } | |
2694 return node; | |
2695 } | 2762 } |
2696 | 2763 |
2697 function inSameTree(a, b) { | |
2698 return rootOfNode(a) === rootOfNode(b); | |
2699 } | |
2700 | |
2701 function enclosedBy(a, b) { | |
2702 if (a === b) | |
2703 return true; | |
2704 if (a instanceof wrappers.ShadowRoot) | |
2705 return enclosedBy(rootOfNode(a.host), b); | |
2706 return false; | |
2707 } | |
2708 | |
2709 | |
2710 function dispatchOriginalEvent(originalEvent) { | 2764 function dispatchOriginalEvent(originalEvent) { |
2711 // Make sure this event is only dispatched once. | 2765 // Make sure this event is only dispatched once. |
2712 if (handledEventsTable.get(originalEvent)) | 2766 if (handledEventsTable.get(originalEvent)) |
2713 return; | 2767 return; |
2714 handledEventsTable.set(originalEvent, true); | 2768 handledEventsTable.set(originalEvent, true); |
2715 | 2769 |
2716 return dispatchEvent(wrap(originalEvent), wrap(originalEvent.target)); | 2770 return dispatchEvent(wrap(originalEvent), wrap(originalEvent.target)); |
2717 } | 2771 } |
2718 | 2772 |
2719 function dispatchEvent(event, originalWrapperTarget) { | 2773 function dispatchEvent(event, originalWrapperTarget) { |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2914 }, | 2968 }, |
2915 get eventPhase() { | 2969 get eventPhase() { |
2916 return eventPhaseTable.get(this); | 2970 return eventPhaseTable.get(this); |
2917 }, | 2971 }, |
2918 get path() { | 2972 get path() { |
2919 var nodeList = new wrappers.NodeList(); | 2973 var nodeList = new wrappers.NodeList(); |
2920 var eventPath = eventPathTable.get(this); | 2974 var eventPath = eventPathTable.get(this); |
2921 if (eventPath) { | 2975 if (eventPath) { |
2922 var index = 0; | 2976 var index = 0; |
2923 var lastIndex = eventPath.length - 1; | 2977 var lastIndex = eventPath.length - 1; |
2924 var baseRoot = rootOfNode(currentTargetTable.get(this)); | 2978 var baseRoot = getTreeScope(currentTargetTable.get(this)); |
2925 | 2979 |
2926 for (var i = 0; i <= lastIndex; i++) { | 2980 for (var i = 0; i <= lastIndex; i++) { |
2927 var currentTarget = eventPath[i].currentTarget; | 2981 var currentTarget = eventPath[i].currentTarget; |
2928 var currentRoot = rootOfNode(currentTarget); | 2982 var currentRoot = getTreeScope(currentTarget); |
2929 if (enclosedBy(baseRoot, currentRoot) && | 2983 if (currentRoot.contains(baseRoot) && |
2930 // Make sure we do not add Window to the path. | 2984 // Make sure we do not add Window to the path. |
2931 (i !== lastIndex || currentTarget instanceof wrappers.Node)) { | 2985 (i !== lastIndex || currentTarget instanceof wrappers.Node)) { |
2932 nodeList[index++] = currentTarget; | 2986 nodeList[index++] = currentTarget; |
2933 } | 2987 } |
2934 } | 2988 } |
2935 nodeList.length = index; | 2989 nodeList.length = index; |
2936 } | 2990 } |
2937 return nodeList; | 2991 return nodeList; |
2938 }, | 2992 }, |
2939 stopPropagation: function() { | 2993 stopPropagation: function() { |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3387 (function(scope) { | 3441 (function(scope) { |
3388 'use strict'; | 3442 'use strict'; |
3389 | 3443 |
3390 // TODO(arv): Implement. | 3444 // TODO(arv): Implement. |
3391 | 3445 |
3392 scope.wrapHTMLCollection = scope.wrapNodeList; | 3446 scope.wrapHTMLCollection = scope.wrapNodeList; |
3393 scope.wrappers.HTMLCollection = scope.wrappers.NodeList; | 3447 scope.wrappers.HTMLCollection = scope.wrappers.NodeList; |
3394 | 3448 |
3395 })(window.ShadowDOMPolyfill); | 3449 })(window.ShadowDOMPolyfill); |
3396 | 3450 |
3397 // Copyright 2012 The Polymer Authors. All rights reserved. | 3451 /** |
3398 // Use of this source code is goverened by a BSD-style | 3452 * Copyright 2012 The Polymer Authors. All rights reserved. |
3399 // license that can be found in the LICENSE file. | 3453 * Use of this source code is goverened by a BSD-style |
| 3454 * license that can be found in the LICENSE file. |
| 3455 */ |
3400 | 3456 |
3401 (function(scope) { | 3457 (function(scope) { |
3402 'use strict'; | 3458 'use strict'; |
3403 | 3459 |
3404 var EventTarget = scope.wrappers.EventTarget; | 3460 var EventTarget = scope.wrappers.EventTarget; |
3405 var NodeList = scope.wrappers.NodeList; | 3461 var NodeList = scope.wrappers.NodeList; |
| 3462 var TreeScope = scope.TreeScope; |
3406 var assert = scope.assert; | 3463 var assert = scope.assert; |
3407 var defineWrapGetter = scope.defineWrapGetter; | 3464 var defineWrapGetter = scope.defineWrapGetter; |
3408 var enqueueMutation = scope.enqueueMutation; | 3465 var enqueueMutation = scope.enqueueMutation; |
| 3466 var getTreeScope = scope.getTreeScope; |
3409 var isWrapper = scope.isWrapper; | 3467 var isWrapper = scope.isWrapper; |
3410 var mixin = scope.mixin; | 3468 var mixin = scope.mixin; |
3411 var registerTransientObservers = scope.registerTransientObservers; | 3469 var registerTransientObservers = scope.registerTransientObservers; |
3412 var registerWrapper = scope.registerWrapper; | 3470 var registerWrapper = scope.registerWrapper; |
| 3471 var setTreeScope = scope.setTreeScope; |
3413 var unwrap = scope.unwrap; | 3472 var unwrap = scope.unwrap; |
3414 var wrap = scope.wrap; | 3473 var wrap = scope.wrap; |
3415 var wrapIfNeeded = scope.wrapIfNeeded; | 3474 var wrapIfNeeded = scope.wrapIfNeeded; |
3416 var wrappers = scope.wrappers; | 3475 var wrappers = scope.wrappers; |
3417 | 3476 |
3418 function assertIsNodeWrapper(node) { | 3477 function assertIsNodeWrapper(node) { |
3419 assert(node instanceof Node); | 3478 assert(node instanceof Node); |
3420 } | 3479 } |
3421 | 3480 |
3422 function createOneElementNodeList(node) { | 3481 function createOneElementNodeList(node) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3519 enqueueRemovalForInsertedDocumentFragment(node, nodes); | 3578 enqueueRemovalForInsertedDocumentFragment(node, nodes); |
3520 return nodes; | 3579 return nodes; |
3521 } | 3580 } |
3522 | 3581 |
3523 function snapshotNodeList(nodeList) { | 3582 function snapshotNodeList(nodeList) { |
3524 // NodeLists are not live at the moment so just return the same object. | 3583 // NodeLists are not live at the moment so just return the same object. |
3525 return nodeList; | 3584 return nodeList; |
3526 } | 3585 } |
3527 | 3586 |
3528 // http://dom.spec.whatwg.org/#node-is-inserted | 3587 // http://dom.spec.whatwg.org/#node-is-inserted |
3529 function nodeWasAdded(node) { | 3588 function nodeWasAdded(node, treeScope) { |
| 3589 setTreeScope(node, treeScope); |
3530 node.nodeIsInserted_(); | 3590 node.nodeIsInserted_(); |
3531 } | 3591 } |
3532 | 3592 |
3533 function nodesWereAdded(nodes) { | 3593 function nodesWereAdded(nodes, parent) { |
| 3594 var treeScope = getTreeScope(parent); |
3534 for (var i = 0; i < nodes.length; i++) { | 3595 for (var i = 0; i < nodes.length; i++) { |
3535 nodeWasAdded(nodes[i]); | 3596 nodeWasAdded(nodes[i], treeScope); |
3536 } | 3597 } |
3537 } | 3598 } |
3538 | 3599 |
3539 // http://dom.spec.whatwg.org/#node-is-removed | 3600 // http://dom.spec.whatwg.org/#node-is-removed |
3540 function nodeWasRemoved(node) { | 3601 function nodeWasRemoved(node) { |
3541 // Nothing at this point in time. | 3602 setTreeScope(node, new TreeScope(node, null)); |
3542 } | 3603 } |
3543 | 3604 |
3544 function nodesWereRemoved(nodes) { | 3605 function nodesWereRemoved(nodes) { |
3545 // Nothing at this point in time. | 3606 for (var i = 0; i < nodes.length; i++) { |
| 3607 nodeWasRemoved(nodes[i]); |
| 3608 } |
3546 } | 3609 } |
3547 | 3610 |
3548 function ensureSameOwnerDocument(parent, child) { | 3611 function ensureSameOwnerDocument(parent, child) { |
3549 var ownerDoc = parent.nodeType === Node.DOCUMENT_NODE ? | 3612 var ownerDoc = parent.nodeType === Node.DOCUMENT_NODE ? |
3550 parent : parent.ownerDocument; | 3613 parent : parent.ownerDocument; |
3551 if (ownerDoc !== child.ownerDocument) | 3614 if (ownerDoc !== child.ownerDocument) |
3552 ownerDoc.adoptNode(child); | 3615 ownerDoc.adoptNode(child); |
3553 } | 3616 } |
3554 | 3617 |
3555 function adoptNodesIfNeeded(owner, nodes) { | 3618 function adoptNodesIfNeeded(owner, nodes) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3653 child; | 3716 child; |
3654 child = child.nextSibling) { | 3717 child = child.nextSibling) { |
3655 cloneContent.appendChild(cloneNode(child, true, opt_doc)); | 3718 cloneContent.appendChild(cloneNode(child, true, opt_doc)); |
3656 } | 3719 } |
3657 } | 3720 } |
3658 } | 3721 } |
3659 // TODO(arv): Some HTML elements also clone other data like value. | 3722 // TODO(arv): Some HTML elements also clone other data like value. |
3660 return clone; | 3723 return clone; |
3661 } | 3724 } |
3662 | 3725 |
| 3726 function contains(self, child) { |
| 3727 if (!child || getTreeScope(self) !== getTreeScope(child)) |
| 3728 return false; |
| 3729 |
| 3730 for (var node = child; node; node = node.parentNode) { |
| 3731 if (node === self) |
| 3732 return true; |
| 3733 } |
| 3734 return false; |
| 3735 } |
| 3736 |
3663 var OriginalNode = window.Node; | 3737 var OriginalNode = window.Node; |
3664 | 3738 |
3665 /** | 3739 /** |
3666 * This represents a wrapper of a native DOM node. | 3740 * This represents a wrapper of a native DOM node. |
3667 * @param {!Node} original The original DOM node, aka, the visual DOM node. | 3741 * @param {!Node} original The original DOM node, aka, the visual DOM node. |
3668 * @constructor | 3742 * @constructor |
3669 * @extends {EventTarget} | 3743 * @extends {EventTarget} |
3670 */ | 3744 */ |
3671 function Node(original) { | 3745 function Node(original) { |
3672 assert(original instanceof OriginalNode); | 3746 assert(original instanceof OriginalNode); |
(...skipping 26 matching lines...) Expand all Loading... |
3699 * @type {Node|undefined} | 3773 * @type {Node|undefined} |
3700 * @private | 3774 * @private |
3701 */ | 3775 */ |
3702 this.nextSibling_ = undefined; | 3776 this.nextSibling_ = undefined; |
3703 | 3777 |
3704 /** | 3778 /** |
3705 * @type {Node|undefined} | 3779 * @type {Node|undefined} |
3706 * @private | 3780 * @private |
3707 */ | 3781 */ |
3708 this.previousSibling_ = undefined; | 3782 this.previousSibling_ = undefined; |
| 3783 |
| 3784 this.treeScope_ = undefined; |
3709 } | 3785 } |
3710 | 3786 |
3711 var OriginalDocumentFragment = window.DocumentFragment; | 3787 var OriginalDocumentFragment = window.DocumentFragment; |
3712 var originalAppendChild = OriginalNode.prototype.appendChild; | 3788 var originalAppendChild = OriginalNode.prototype.appendChild; |
3713 var originalCompareDocumentPosition = | 3789 var originalCompareDocumentPosition = |
3714 OriginalNode.prototype.compareDocumentPosition; | 3790 OriginalNode.prototype.compareDocumentPosition; |
3715 var originalInsertBefore = OriginalNode.prototype.insertBefore; | 3791 var originalInsertBefore = OriginalNode.prototype.insertBefore; |
3716 var originalRemoveChild = OriginalNode.prototype.removeChild; | 3792 var originalRemoveChild = OriginalNode.prototype.removeChild; |
3717 var originalReplaceChild = OriginalNode.prototype.replaceChild; | 3793 var originalReplaceChild = OriginalNode.prototype.replaceChild; |
3718 | 3794 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3787 adoptNodesIfNeeded(this, nodes); | 3863 adoptNodesIfNeeded(this, nodes); |
3788 } | 3864 } |
3789 } | 3865 } |
3790 | 3866 |
3791 enqueueMutation(this, 'childList', { | 3867 enqueueMutation(this, 'childList', { |
3792 addedNodes: nodes, | 3868 addedNodes: nodes, |
3793 nextSibling: refWrapper, | 3869 nextSibling: refWrapper, |
3794 previousSibling: previousNode | 3870 previousSibling: previousNode |
3795 }); | 3871 }); |
3796 | 3872 |
3797 nodesWereAdded(nodes); | 3873 nodesWereAdded(nodes, this); |
3798 | 3874 |
3799 return childWrapper; | 3875 return childWrapper; |
3800 }, | 3876 }, |
3801 | 3877 |
3802 removeChild: function(childWrapper) { | 3878 removeChild: function(childWrapper) { |
3803 assertIsNodeWrapper(childWrapper); | 3879 assertIsNodeWrapper(childWrapper); |
3804 if (childWrapper.parentNode !== this) { | 3880 if (childWrapper.parentNode !== this) { |
3805 // IE has invalid DOM trees at times. | 3881 // IE has invalid DOM trees at times. |
3806 var found = false; | 3882 var found = false; |
3807 var childNodes = this.childNodes; | 3883 var childNodes = this.childNodes; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3919 } | 3995 } |
3920 | 3996 |
3921 enqueueMutation(this, 'childList', { | 3997 enqueueMutation(this, 'childList', { |
3922 addedNodes: nodes, | 3998 addedNodes: nodes, |
3923 removedNodes: createOneElementNodeList(oldChildWrapper), | 3999 removedNodes: createOneElementNodeList(oldChildWrapper), |
3924 nextSibling: nextNode, | 4000 nextSibling: nextNode, |
3925 previousSibling: previousNode | 4001 previousSibling: previousNode |
3926 }); | 4002 }); |
3927 | 4003 |
3928 nodeWasRemoved(oldChildWrapper); | 4004 nodeWasRemoved(oldChildWrapper); |
3929 nodesWereAdded(nodes); | 4005 nodesWereAdded(nodes, this); |
3930 | 4006 |
3931 return oldChildWrapper; | 4007 return oldChildWrapper; |
3932 }, | 4008 }, |
3933 | 4009 |
3934 /** | 4010 /** |
3935 * Called after a node was inserted. Subclasses override this to invalidate | 4011 * Called after a node was inserted. Subclasses override this to invalidate |
3936 * the renderer as needed. | 4012 * the renderer as needed. |
3937 * @private | 4013 * @private |
3938 */ | 4014 */ |
3939 nodeIsInserted_: function() { | 4015 nodeIsInserted_: function() { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4011 } | 4087 } |
4012 | 4088 |
4013 var addedNodes = snapshotNodeList(this.childNodes); | 4089 var addedNodes = snapshotNodeList(this.childNodes); |
4014 | 4090 |
4015 enqueueMutation(this, 'childList', { | 4091 enqueueMutation(this, 'childList', { |
4016 addedNodes: addedNodes, | 4092 addedNodes: addedNodes, |
4017 removedNodes: removedNodes | 4093 removedNodes: removedNodes |
4018 }); | 4094 }); |
4019 | 4095 |
4020 nodesWereRemoved(removedNodes); | 4096 nodesWereRemoved(removedNodes); |
4021 nodesWereAdded(addedNodes); | 4097 nodesWereAdded(addedNodes, this); |
4022 }, | 4098 }, |
4023 | 4099 |
4024 get childNodes() { | 4100 get childNodes() { |
4025 var wrapperList = new NodeList(); | 4101 var wrapperList = new NodeList(); |
4026 var i = 0; | 4102 var i = 0; |
4027 for (var child = this.firstChild; child; child = child.nextSibling) { | 4103 for (var child = this.firstChild; child; child = child.nextSibling) { |
4028 wrapperList[i++] = child; | 4104 wrapperList[i++] = child; |
4029 } | 4105 } |
4030 wrapperList.length = i; | 4106 wrapperList.length = i; |
4031 return wrapperList; | 4107 return wrapperList; |
4032 }, | 4108 }, |
4033 | 4109 |
4034 cloneNode: function(deep) { | 4110 cloneNode: function(deep) { |
4035 return cloneNode(this, deep); | 4111 return cloneNode(this, deep); |
4036 }, | 4112 }, |
4037 | 4113 |
4038 contains: function(child) { | 4114 contains: function(child) { |
4039 if (!child) | 4115 return contains(this, wrapIfNeeded(child)); |
4040 return false; | |
4041 | |
4042 child = wrapIfNeeded(child); | |
4043 | |
4044 // TODO(arv): Optimize using ownerDocument etc. | |
4045 if (child === this) | |
4046 return true; | |
4047 var parentNode = child.parentNode; | |
4048 if (!parentNode) | |
4049 return false; | |
4050 return this.contains(parentNode); | |
4051 }, | 4116 }, |
4052 | 4117 |
4053 compareDocumentPosition: function(otherNode) { | 4118 compareDocumentPosition: function(otherNode) { |
4054 // This only wraps, it therefore only operates on the composed DOM and not | 4119 // This only wraps, it therefore only operates on the composed DOM and not |
4055 // the logical DOM. | 4120 // the logical DOM. |
4056 return originalCompareDocumentPosition.call(this.impl, unwrap(otherNode)); | 4121 return originalCompareDocumentPosition.call(this.impl, unwrap(otherNode)); |
4057 }, | 4122 }, |
4058 | 4123 |
4059 normalize: function() { | 4124 normalize: function() { |
4060 var nodes = snapshotNodeList(this.childNodes); | 4125 var nodes = snapshotNodeList(this.childNodes); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4097 defineWrapGetter(Node, 'ownerDocument'); | 4162 defineWrapGetter(Node, 'ownerDocument'); |
4098 | 4163 |
4099 // We use a DocumentFragment as a base and then delete the properties of | 4164 // We use a DocumentFragment as a base and then delete the properties of |
4100 // DocumentFragment.prototype from the wrapper Node. Since delete makes | 4165 // DocumentFragment.prototype from the wrapper Node. Since delete makes |
4101 // objects slow in some JS engines we recreate the prototype object. | 4166 // objects slow in some JS engines we recreate the prototype object. |
4102 registerWrapper(OriginalNode, Node, document.createDocumentFragment()); | 4167 registerWrapper(OriginalNode, Node, document.createDocumentFragment()); |
4103 delete Node.prototype.querySelector; | 4168 delete Node.prototype.querySelector; |
4104 delete Node.prototype.querySelectorAll; | 4169 delete Node.prototype.querySelectorAll; |
4105 Node.prototype = mixin(Object.create(EventTarget.prototype), Node.prototype); | 4170 Node.prototype = mixin(Object.create(EventTarget.prototype), Node.prototype); |
4106 | 4171 |
| 4172 scope.cloneNode = cloneNode; |
4107 scope.nodeWasAdded = nodeWasAdded; | 4173 scope.nodeWasAdded = nodeWasAdded; |
4108 scope.nodeWasRemoved = nodeWasRemoved; | 4174 scope.nodeWasRemoved = nodeWasRemoved; |
4109 scope.nodesWereAdded = nodesWereAdded; | 4175 scope.nodesWereAdded = nodesWereAdded; |
4110 scope.nodesWereRemoved = nodesWereRemoved; | 4176 scope.nodesWereRemoved = nodesWereRemoved; |
4111 scope.snapshotNodeList = snapshotNodeList; | 4177 scope.snapshotNodeList = snapshotNodeList; |
4112 scope.wrappers.Node = Node; | 4178 scope.wrappers.Node = Node; |
4113 scope.cloneNode = cloneNode; | |
4114 | 4179 |
4115 })(window.ShadowDOMPolyfill); | 4180 })(window.ShadowDOMPolyfill); |
4116 | 4181 |
4117 // Copyright 2013 The Polymer Authors. All rights reserved. | 4182 // Copyright 2013 The Polymer Authors. All rights reserved. |
4118 // Use of this source code is governed by a BSD-style | 4183 // Use of this source code is governed by a BSD-style |
4119 // license that can be found in the LICENSE file. | 4184 // license that can be found in the LICENSE file. |
4120 | 4185 |
4121 (function(scope) { | 4186 (function(scope) { |
4122 'use strict'; | 4187 'use strict'; |
4123 | 4188 |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4675 } | 4740 } |
4676 | 4741 |
4677 var addedNodes = snapshotNodeList(this.childNodes); | 4742 var addedNodes = snapshotNodeList(this.childNodes); |
4678 | 4743 |
4679 enqueueMutation(this, 'childList', { | 4744 enqueueMutation(this, 'childList', { |
4680 addedNodes: addedNodes, | 4745 addedNodes: addedNodes, |
4681 removedNodes: removedNodes | 4746 removedNodes: removedNodes |
4682 }); | 4747 }); |
4683 | 4748 |
4684 nodesWereRemoved(removedNodes); | 4749 nodesWereRemoved(removedNodes); |
4685 nodesWereAdded(addedNodes); | 4750 nodesWereAdded(addedNodes, this); |
4686 }, | 4751 }, |
4687 | 4752 |
4688 get outerHTML() { | 4753 get outerHTML() { |
4689 return getOuterHTML(this, this.parentNode); | 4754 return getOuterHTML(this, this.parentNode); |
4690 }, | 4755 }, |
4691 set outerHTML(value) { | 4756 set outerHTML(value) { |
4692 var p = this.parentNode; | 4757 var p = this.parentNode; |
4693 if (p) { | 4758 if (p) { |
4694 p.invalidateShadowRenderer(); | 4759 p.invalidateShadowRenderer(); |
4695 var df = frag(p, value); | 4760 var df = frag(p, value); |
(...skipping 1020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5716 })(window.ShadowDOMPolyfill); | 5781 })(window.ShadowDOMPolyfill); |
5717 | 5782 |
5718 // Copyright 2013 The Polymer Authors. All rights reserved. | 5783 // Copyright 2013 The Polymer Authors. All rights reserved. |
5719 // Use of this source code is goverened by a BSD-style | 5784 // Use of this source code is goverened by a BSD-style |
5720 // license that can be found in the LICENSE file. | 5785 // license that can be found in the LICENSE file. |
5721 | 5786 |
5722 (function(scope) { | 5787 (function(scope) { |
5723 'use strict'; | 5788 'use strict'; |
5724 | 5789 |
5725 var DocumentFragment = scope.wrappers.DocumentFragment; | 5790 var DocumentFragment = scope.wrappers.DocumentFragment; |
| 5791 var TreeScope = scope.TreeScope; |
5726 var elementFromPoint = scope.elementFromPoint; | 5792 var elementFromPoint = scope.elementFromPoint; |
5727 var getInnerHTML = scope.getInnerHTML; | 5793 var getInnerHTML = scope.getInnerHTML; |
| 5794 var getTreeScope = scope.getTreeScope; |
5728 var mixin = scope.mixin; | 5795 var mixin = scope.mixin; |
5729 var rewrap = scope.rewrap; | 5796 var rewrap = scope.rewrap; |
5730 var setInnerHTML = scope.setInnerHTML; | 5797 var setInnerHTML = scope.setInnerHTML; |
5731 var unwrap = scope.unwrap; | 5798 var unwrap = scope.unwrap; |
5732 | 5799 |
5733 var shadowHostTable = new WeakMap(); | 5800 var shadowHostTable = new WeakMap(); |
5734 var nextOlderShadowTreeTable = new WeakMap(); | 5801 var nextOlderShadowTreeTable = new WeakMap(); |
5735 | 5802 |
5736 var spaceCharRe = /[ \t\n\r\f]/; | 5803 var spaceCharRe = /[ \t\n\r\f]/; |
5737 | 5804 |
5738 function ShadowRoot(hostWrapper) { | 5805 function ShadowRoot(hostWrapper) { |
5739 var node = unwrap(hostWrapper.impl.ownerDocument.createDocumentFragment()); | 5806 var node = unwrap(hostWrapper.impl.ownerDocument.createDocumentFragment()); |
5740 DocumentFragment.call(this, node); | 5807 DocumentFragment.call(this, node); |
5741 | 5808 |
5742 // createDocumentFragment associates the node with a wrapper | 5809 // createDocumentFragment associates the node with a wrapper |
5743 // DocumentFragment instance. Override that. | 5810 // DocumentFragment instance. Override that. |
5744 rewrap(node, this); | 5811 rewrap(node, this); |
5745 | 5812 |
| 5813 this.treeScope_ = new TreeScope(this, getTreeScope(hostWrapper)); |
| 5814 |
5746 var oldShadowRoot = hostWrapper.shadowRoot; | 5815 var oldShadowRoot = hostWrapper.shadowRoot; |
5747 nextOlderShadowTreeTable.set(this, oldShadowRoot); | 5816 nextOlderShadowTreeTable.set(this, oldShadowRoot); |
5748 | 5817 |
5749 shadowHostTable.set(this, hostWrapper); | 5818 shadowHostTable.set(this, hostWrapper); |
5750 } | 5819 } |
5751 ShadowRoot.prototype = Object.create(DocumentFragment.prototype); | 5820 ShadowRoot.prototype = Object.create(DocumentFragment.prototype); |
5752 mixin(ShadowRoot.prototype, { | 5821 mixin(ShadowRoot.prototype, { |
5753 get innerHTML() { | 5822 get innerHTML() { |
5754 return getInnerHTML(this); | 5823 return getInnerHTML(this); |
5755 }, | 5824 }, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5791 | 5860 |
5792 (function(scope) { | 5861 (function(scope) { |
5793 'use strict'; | 5862 'use strict'; |
5794 | 5863 |
5795 var Element = scope.wrappers.Element; | 5864 var Element = scope.wrappers.Element; |
5796 var HTMLContentElement = scope.wrappers.HTMLContentElement; | 5865 var HTMLContentElement = scope.wrappers.HTMLContentElement; |
5797 var HTMLShadowElement = scope.wrappers.HTMLShadowElement; | 5866 var HTMLShadowElement = scope.wrappers.HTMLShadowElement; |
5798 var Node = scope.wrappers.Node; | 5867 var Node = scope.wrappers.Node; |
5799 var ShadowRoot = scope.wrappers.ShadowRoot; | 5868 var ShadowRoot = scope.wrappers.ShadowRoot; |
5800 var assert = scope.assert; | 5869 var assert = scope.assert; |
| 5870 var getTreeScope = scope.getTreeScope; |
5801 var mixin = scope.mixin; | 5871 var mixin = scope.mixin; |
5802 var oneOf = scope.oneOf; | 5872 var oneOf = scope.oneOf; |
5803 var unwrap = scope.unwrap; | 5873 var unwrap = scope.unwrap; |
5804 var wrap = scope.wrap; | 5874 var wrap = scope.wrap; |
5805 | 5875 |
5806 /** | 5876 /** |
5807 * Updates the fields of a wrapper to a snapshot of the logical DOM as needed. | 5877 * Updates the fields of a wrapper to a snapshot of the logical DOM as needed. |
5808 * Up means parentNode | 5878 * Up means parentNode |
5809 * Sideways means previous and next sibling. | 5879 * Sideways means previous and next sibling. |
5810 * @param {!Node} wrapper | 5880 * @param {!Node} wrapper |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6010 'setTimeout' | 6080 'setTimeout' |
6011 ]); | 6081 ]); |
6012 | 6082 |
6013 var pendingDirtyRenderers = []; | 6083 var pendingDirtyRenderers = []; |
6014 var renderTimer; | 6084 var renderTimer; |
6015 | 6085 |
6016 function renderAllPending() { | 6086 function renderAllPending() { |
6017 // TODO(arv): Order these in document order. That way we do not have to | 6087 // TODO(arv): Order these in document order. That way we do not have to |
6018 // render something twice. | 6088 // render something twice. |
6019 for (var i = 0; i < pendingDirtyRenderers.length; i++) { | 6089 for (var i = 0; i < pendingDirtyRenderers.length; i++) { |
6020 pendingDirtyRenderers[i].render(); | 6090 var renderer = pendingDirtyRenderers[i]; |
| 6091 var parentRenderer = renderer.parentRenderer; |
| 6092 if (parentRenderer && parentRenderer.dirty) |
| 6093 continue; |
| 6094 renderer.render(); |
6021 } | 6095 } |
6022 | 6096 |
6023 pendingDirtyRenderers = []; | 6097 pendingDirtyRenderers = []; |
6024 } | 6098 } |
6025 | 6099 |
6026 function handleRequestAnimationFrame() { | 6100 function handleRequestAnimationFrame() { |
6027 renderTimer = null; | 6101 renderTimer = null; |
6028 renderAllPending(); | 6102 renderAllPending(); |
6029 } | 6103 } |
6030 | 6104 |
6031 /** | 6105 /** |
6032 * Returns existing shadow renderer for a host or creates it if it is needed. | 6106 * Returns existing shadow renderer for a host or creates it if it is needed. |
6033 * @params {!Element} host | 6107 * @params {!Element} host |
6034 * @return {!ShadowRenderer} | 6108 * @return {!ShadowRenderer} |
6035 */ | 6109 */ |
6036 function getRendererForHost(host) { | 6110 function getRendererForHost(host) { |
6037 var renderer = rendererForHostTable.get(host); | 6111 var renderer = rendererForHostTable.get(host); |
6038 if (!renderer) { | 6112 if (!renderer) { |
6039 renderer = new ShadowRenderer(host); | 6113 renderer = new ShadowRenderer(host); |
6040 rendererForHostTable.set(host, renderer); | 6114 rendererForHostTable.set(host, renderer); |
6041 } | 6115 } |
6042 return renderer; | 6116 return renderer; |
6043 } | 6117 } |
6044 | 6118 |
6045 function getShadowRootAncestor(node) { | 6119 function getShadowRootAncestor(node) { |
6046 for (; node; node = node.parentNode) { | 6120 var root = getTreeScope(node).root; |
6047 if (node instanceof ShadowRoot) | 6121 if (root instanceof ShadowRoot) |
6048 return node; | 6122 return root; |
6049 } | |
6050 return null; | 6123 return null; |
6051 } | 6124 } |
6052 | 6125 |
6053 function getRendererForShadowRoot(shadowRoot) { | 6126 function getRendererForShadowRoot(shadowRoot) { |
6054 return getRendererForHost(shadowRoot.host); | 6127 return getRendererForHost(shadowRoot.host); |
6055 } | 6128 } |
6056 | 6129 |
6057 var spliceDiff = new ArraySplice(); | 6130 var spliceDiff = new ArraySplice(); |
6058 spliceDiff.equals = function(renderNode, rawNode) { | 6131 spliceDiff.equals = function(renderNode, rawNode) { |
6059 return unwrap(renderNode.node) === rawNode; | 6132 return unwrap(renderNode.node) === rawNode; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6156 for (var node = shadowRoot.firstChild; node; node = node.nextSibling) { | 6229 for (var node = shadowRoot.firstChild; node; node = node.nextSibling) { |
6157 this.renderNode(shadowRoot, renderNode, node, false); | 6230 this.renderNode(shadowRoot, renderNode, node, false); |
6158 } | 6231 } |
6159 | 6232 |
6160 if (topMostRenderer) | 6233 if (topMostRenderer) |
6161 renderNode.sync(); | 6234 renderNode.sync(); |
6162 | 6235 |
6163 this.dirty = false; | 6236 this.dirty = false; |
6164 }, | 6237 }, |
6165 | 6238 |
| 6239 get parentRenderer() { |
| 6240 return getTreeScope(this.host).renderer; |
| 6241 }, |
| 6242 |
6166 invalidate: function() { | 6243 invalidate: function() { |
6167 if (!this.dirty) { | 6244 if (!this.dirty) { |
6168 this.dirty = true; | 6245 this.dirty = true; |
6169 pendingDirtyRenderers.push(this); | 6246 pendingDirtyRenderers.push(this); |
6170 if (renderTimer) | 6247 if (renderTimer) |
6171 return; | 6248 return; |
6172 renderTimer = window[request](handleRequestAnimationFrame, 0); | 6249 renderTimer = window[request](handleRequestAnimationFrame, 0); |
6173 } | 6250 } |
6174 }, | 6251 }, |
6175 | 6252 |
(...skipping 10 matching lines...) Expand all Loading... |
6186 } else { | 6263 } else { |
6187 this.renderAsAnyDomTree(shadowRoot, renderNode, node, isNested); | 6264 this.renderAsAnyDomTree(shadowRoot, renderNode, node, isNested); |
6188 } | 6265 } |
6189 }, | 6266 }, |
6190 | 6267 |
6191 renderAsAnyDomTree: function(shadowRoot, renderNode, node, isNested) { | 6268 renderAsAnyDomTree: function(shadowRoot, renderNode, node, isNested) { |
6192 renderNode = renderNode.append(node); | 6269 renderNode = renderNode.append(node); |
6193 | 6270 |
6194 if (isShadowHost(node)) { | 6271 if (isShadowHost(node)) { |
6195 var renderer = getRendererForHost(node); | 6272 var renderer = getRendererForHost(node); |
6196 // renderNode.skip = !renderer.dirty; | 6273 renderNode.skip = !renderer.dirty; |
6197 renderer.invalidate(); | |
6198 renderer.render(renderNode); | 6274 renderer.render(renderNode); |
6199 } else { | 6275 } else { |
6200 for (var child = node.firstChild; child; child = child.nextSibling) { | 6276 for (var child = node.firstChild; child; child = child.nextSibling) { |
6201 this.renderNode(shadowRoot, renderNode, child, isNested); | 6277 this.renderNode(shadowRoot, renderNode, child, isNested); |
6202 } | 6278 } |
6203 } | 6279 } |
6204 }, | 6280 }, |
6205 | 6281 |
6206 renderInsertionPoint: function(shadowRoot, renderNode, insertionPoint, | 6282 renderInsertionPoint: function(shadowRoot, renderNode, insertionPoint, |
6207 isNested) { | 6283 isNested) { |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6586 | 6662 |
6587 (function(scope) { | 6663 (function(scope) { |
6588 'use strict'; | 6664 'use strict'; |
6589 | 6665 |
6590 var GetElementsByInterface = scope.GetElementsByInterface; | 6666 var GetElementsByInterface = scope.GetElementsByInterface; |
6591 var Node = scope.wrappers.Node; | 6667 var Node = scope.wrappers.Node; |
6592 var ParentNodeInterface = scope.ParentNodeInterface; | 6668 var ParentNodeInterface = scope.ParentNodeInterface; |
6593 var Selection = scope.wrappers.Selection; | 6669 var Selection = scope.wrappers.Selection; |
6594 var SelectorsInterface = scope.SelectorsInterface; | 6670 var SelectorsInterface = scope.SelectorsInterface; |
6595 var ShadowRoot = scope.wrappers.ShadowRoot; | 6671 var ShadowRoot = scope.wrappers.ShadowRoot; |
| 6672 var TreeScope = scope.TreeScope; |
6596 var cloneNode = scope.cloneNode; | 6673 var cloneNode = scope.cloneNode; |
6597 var defineWrapGetter = scope.defineWrapGetter; | 6674 var defineWrapGetter = scope.defineWrapGetter; |
6598 var elementFromPoint = scope.elementFromPoint; | 6675 var elementFromPoint = scope.elementFromPoint; |
6599 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; | 6676 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; |
6600 var matchesNames = scope.matchesNames; | 6677 var matchesNames = scope.matchesNames; |
6601 var mixin = scope.mixin; | 6678 var mixin = scope.mixin; |
6602 var registerWrapper = scope.registerWrapper; | 6679 var registerWrapper = scope.registerWrapper; |
6603 var renderAllPending = scope.renderAllPending; | 6680 var renderAllPending = scope.renderAllPending; |
6604 var rewrap = scope.rewrap; | 6681 var rewrap = scope.rewrap; |
6605 var unwrap = scope.unwrap; | 6682 var unwrap = scope.unwrap; |
6606 var wrap = scope.wrap; | 6683 var wrap = scope.wrap; |
6607 var wrapEventTargetMethods = scope.wrapEventTargetMethods; | 6684 var wrapEventTargetMethods = scope.wrapEventTargetMethods; |
6608 var wrapNodeList = scope.wrapNodeList; | 6685 var wrapNodeList = scope.wrapNodeList; |
6609 | 6686 |
6610 var implementationTable = new WeakMap(); | 6687 var implementationTable = new WeakMap(); |
6611 | 6688 |
6612 function Document(node) { | 6689 function Document(node) { |
6613 Node.call(this, node); | 6690 Node.call(this, node); |
| 6691 this.treeScope_ = new TreeScope(this, null); |
6614 } | 6692 } |
6615 Document.prototype = Object.create(Node.prototype); | 6693 Document.prototype = Object.create(Node.prototype); |
6616 | 6694 |
6617 defineWrapGetter(Document, 'documentElement'); | 6695 defineWrapGetter(Document, 'documentElement'); |
6618 | 6696 |
6619 // Conceptually both body and head can be in a shadow but suporting that seems | 6697 // Conceptually both body and head can be in a shadow but suporting that seems |
6620 // overkill at this point. | 6698 // overkill at this point. |
6621 defineWrapGetter(Document, 'body'); | 6699 defineWrapGetter(Document, 'body'); |
6622 defineWrapGetter(Document, 'head'); | 6700 defineWrapGetter(Document, 'head'); |
6623 | 6701 |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7231 (function(scope) { | 7309 (function(scope) { |
7232 | 7310 |
7233 var ShadowCSS = { | 7311 var ShadowCSS = { |
7234 strictStyling: false, | 7312 strictStyling: false, |
7235 registry: {}, | 7313 registry: {}, |
7236 // Shim styles for a given root associated with a name and extendsName | 7314 // Shim styles for a given root associated with a name and extendsName |
7237 // 1. cache root styles by name | 7315 // 1. cache root styles by name |
7238 // 2. optionally tag root nodes with scope name | 7316 // 2. optionally tag root nodes with scope name |
7239 // 3. shim polyfill directives /* @polyfill */ and /* @polyfill-rule */ | 7317 // 3. shim polyfill directives /* @polyfill */ and /* @polyfill-rule */ |
7240 // 4. shim :host and scoping | 7318 // 4. shim :host and scoping |
7241 shimStyling: function(root, name, extendsName, ownSheet) { | 7319 shimStyling: function(root, name, extendsName) { |
| 7320 var scopeStyles = this.prepareRoot(root, name, extendsName); |
7242 var typeExtension = this.isTypeExtension(extendsName); | 7321 var typeExtension = this.isTypeExtension(extendsName); |
| 7322 var scopeSelector = this.makeScopeSelector(name, typeExtension); |
7243 // use caching to make working with styles nodes easier and to facilitate | 7323 // use caching to make working with styles nodes easier and to facilitate |
7244 // lookup of extendee | 7324 // lookup of extendee |
7245 var def = this.registerDefinition(root, name, extendsName); | 7325 var cssText = stylesToCssText(scopeStyles, true); |
7246 // find styles and apply shimming... | 7326 cssText = this.scopeCssText(cssText, scopeSelector); |
| 7327 // cache shimmed css on root for user extensibility |
| 7328 if (root) { |
| 7329 root.shimmedStyle = cssText; |
| 7330 } |
| 7331 // add style to document |
| 7332 this.addCssToDocument(cssText, name); |
| 7333 }, |
| 7334 /* |
| 7335 * Shim a style element with the given selector. Returns cssText that can |
| 7336 * be included in the document via Platform.ShadowCSS.addCssToDocument(css). |
| 7337 */ |
| 7338 shimStyle: function(style, selector) { |
| 7339 return this.shimCssText(style.textContent, selector); |
| 7340 }, |
| 7341 /* |
| 7342 * Shim some cssText with the given selector. Returns cssText that can |
| 7343 * be included in the document via Platform.ShadowCSS.addCssToDocument(css). |
| 7344 */ |
| 7345 shimCssText: function(cssText, selector) { |
| 7346 cssText = this.insertDirectives(cssText); |
| 7347 return this.scopeCssText(cssText, selector); |
| 7348 }, |
| 7349 makeScopeSelector: function(name, typeExtension) { |
| 7350 if (name) { |
| 7351 return typeExtension ? '[is=' + name + ']' : name; |
| 7352 } |
| 7353 return ''; |
| 7354 }, |
| 7355 isTypeExtension: function(extendsName) { |
| 7356 return extendsName && extendsName.indexOf('-') < 0; |
| 7357 }, |
| 7358 prepareRoot: function(root, name, extendsName) { |
| 7359 var def = this.registerRoot(root, name, extendsName); |
| 7360 this.replaceTextInStyles(def.rootStyles, this.insertDirectives); |
| 7361 // remove existing style elements |
| 7362 this.removeStyles(root, def.rootStyles); |
| 7363 // apply strict attr |
7247 if (this.strictStyling) { | 7364 if (this.strictStyling) { |
7248 this.applyScopeToContent(root, name); | 7365 this.applyScopeToContent(root, name); |
7249 } | 7366 } |
7250 var cssText = this.stylesToShimmedCssText(def.rootStyles, def.scopeStyles, | 7367 return def.scopeStyles; |
7251 name, typeExtension); | 7368 }, |
7252 // provide shimmedStyle for user extensibility | 7369 removeStyles: function(root, styles) { |
7253 def.shimmedStyle = cssTextToStyle(cssText); | 7370 for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) { |
7254 if (root) { | |
7255 root.shimmedStyle = def.shimmedStyle; | |
7256 } | |
7257 // remove existing style elements | |
7258 for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]); | |
7259 i++) { | |
7260 s.parentNode.removeChild(s); | 7371 s.parentNode.removeChild(s); |
7261 } | 7372 } |
7262 // add style to document | |
7263 if (ownSheet) { | |
7264 addOwnSheet(cssText, name); | |
7265 } else { | |
7266 addCssToDocument(cssText); | |
7267 } | |
7268 }, | 7373 }, |
7269 // apply @polyfill rules + :host and scope shimming | 7374 registerRoot: function(root, name, extendsName) { |
7270 stylesToShimmedCssText: function(rootStyles, scopeStyles, name, | |
7271 typeExtension) { | |
7272 name = name || ''; | |
7273 // insert @polyfill and @polyfill-rule rules into style elements | |
7274 // scoping process takes care of shimming these | |
7275 this.insertPolyfillDirectives(rootStyles); | |
7276 this.insertPolyfillRules(rootStyles); | |
7277 var cssText = this.shimScoping(scopeStyles, name, typeExtension); | |
7278 // note: we only need to do rootStyles since these are unscoped. | |
7279 cssText += this.extractPolyfillUnscopedRules(rootStyles); | |
7280 return cssText.trim(); | |
7281 }, | |
7282 registerDefinition: function(root, name, extendsName) { | |
7283 var def = this.registry[name] = { | 7375 var def = this.registry[name] = { |
7284 root: root, | 7376 root: root, |
7285 name: name, | 7377 name: name, |
7286 extendsName: extendsName | 7378 extendsName: extendsName |
7287 } | 7379 } |
7288 var styles = root ? root.querySelectorAll('style') : []; | 7380 var styles = this.findStyles(root); |
7289 styles = styles ? Array.prototype.slice.call(styles, 0) : []; | |
7290 def.rootStyles = styles; | 7381 def.rootStyles = styles; |
7291 def.scopeStyles = def.rootStyles; | 7382 def.scopeStyles = def.rootStyles; |
7292 var extendee = this.registry[def.extendsName]; | 7383 var extendee = this.registry[def.extendsName]; |
7293 if (extendee && (!root || root.querySelector('shadow'))) { | 7384 if (extendee && (!root || root.querySelector('shadow'))) { |
7294 def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles); | 7385 def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles); |
7295 } | 7386 } |
7296 return def; | 7387 return def; |
7297 }, | 7388 }, |
7298 isTypeExtension: function(extendsName) { | 7389 findStyles: function(root) { |
7299 return extendsName && extendsName.indexOf('-') < 0; | 7390 if (!root) { |
| 7391 return []; |
| 7392 } |
| 7393 var styles = root.querySelectorAll('style'); |
| 7394 return Array.prototype.filter.call(styles, function(s) { |
| 7395 return !s.hasAttribute(NO_SHIM_ATTRIBUTE); |
| 7396 }); |
7300 }, | 7397 }, |
7301 applyScopeToContent: function(root, name) { | 7398 applyScopeToContent: function(root, name) { |
7302 if (root) { | 7399 if (root) { |
7303 // add the name attribute to each node in root. | 7400 // add the name attribute to each node in root. |
7304 Array.prototype.forEach.call(root.querySelectorAll('*'), | 7401 Array.prototype.forEach.call(root.querySelectorAll('*'), |
7305 function(node) { | 7402 function(node) { |
7306 node.setAttribute(name, ''); | 7403 node.setAttribute(name, ''); |
7307 }); | 7404 }); |
7308 // and template contents too | 7405 // and template contents too |
7309 Array.prototype.forEach.call(root.querySelectorAll('template'), | 7406 Array.prototype.forEach.call(root.querySelectorAll('template'), |
7310 function(template) { | 7407 function(template) { |
7311 this.applyScopeToContent(template.content, name); | 7408 this.applyScopeToContent(template.content, name); |
7312 }, | 7409 }, |
7313 this); | 7410 this); |
7314 } | 7411 } |
7315 }, | 7412 }, |
| 7413 insertDirectives: function(cssText) { |
| 7414 cssText = this.insertPolyfillDirectivesInCssText(cssText); |
| 7415 return this.insertPolyfillRulesInCssText(cssText); |
| 7416 }, |
7316 /* | 7417 /* |
7317 * Process styles to convert native ShadowDOM rules that will trip | 7418 * Process styles to convert native ShadowDOM rules that will trip |
7318 * up the css parser; we rely on decorating the stylesheet with comments. | 7419 * up the css parser; we rely on decorating the stylesheet with inert rules. |
7319 * | 7420 * |
7320 * For example, we convert this rule: | 7421 * For example, we convert this rule: |
7321 * | 7422 * |
7322 * (comment start) @polyfill :host menu-item (comment end) | 7423 * polyfill-next-selector { content: ':host menu-item'; } |
7323 * shadow::-webkit-distributed(menu-item) { | 7424 * ::content menu-item { |
7324 * | 7425 * |
7325 * to this: | 7426 * to this: |
7326 * | 7427 * |
7327 * scopeName menu-item { | 7428 * scopeName menu-item { |
7328 * | 7429 * |
7329 **/ | 7430 **/ |
7330 insertPolyfillDirectives: function(styles) { | |
7331 if (styles) { | |
7332 Array.prototype.forEach.call(styles, function(s) { | |
7333 s.textContent = this.insertPolyfillDirectivesInCssText(s.textContent); | |
7334 }, this); | |
7335 } | |
7336 }, | |
7337 insertPolyfillDirectivesInCssText: function(cssText) { | 7431 insertPolyfillDirectivesInCssText: function(cssText) { |
7338 return cssText.replace(cssPolyfillCommentRe, function(match, p1) { | 7432 // TODO(sorvell): remove either content or comment |
| 7433 cssText = cssText.replace(cssCommentNextSelectorRe, function(match, p1) { |
7339 // remove end comment delimiter and add block start | 7434 // remove end comment delimiter and add block start |
7340 return p1.slice(0, -2) + '{'; | 7435 return p1.slice(0, -2) + '{'; |
7341 }); | 7436 }); |
| 7437 return cssText.replace(cssContentNextSelectorRe, function(match, p1) { |
| 7438 return p1 + ' {'; |
| 7439 }); |
7342 }, | 7440 }, |
7343 /* | 7441 /* |
7344 * Process styles to add rules which will only apply under the polyfill | 7442 * Process styles to add rules which will only apply under the polyfill |
7345 * | 7443 * |
7346 * For example, we convert this rule: | 7444 * For example, we convert this rule: |
7347 * | 7445 * |
7348 * (comment start) @polyfill-rule :host menu-item { | 7446 * polyfill-rule { |
7349 * ... } (comment end) | 7447 * content: ':host menu-item'; |
| 7448 * ... |
| 7449 * } |
7350 * | 7450 * |
7351 * to this: | 7451 * to this: |
7352 * | 7452 * |
7353 * scopeName menu-item {...} | 7453 * scopeName menu-item {...} |
7354 * | 7454 * |
7355 **/ | 7455 **/ |
7356 insertPolyfillRules: function(styles) { | |
7357 if (styles) { | |
7358 Array.prototype.forEach.call(styles, function(s) { | |
7359 s.textContent = this.insertPolyfillRulesInCssText(s.textContent); | |
7360 }, this); | |
7361 } | |
7362 }, | |
7363 insertPolyfillRulesInCssText: function(cssText) { | 7456 insertPolyfillRulesInCssText: function(cssText) { |
7364 return cssText.replace(cssPolyfillRuleCommentRe, function(match, p1) { | 7457 // TODO(sorvell): remove either content or comment |
| 7458 cssText = cssText.replace(cssCommentRuleRe, function(match, p1) { |
7365 // remove end comment delimiter | 7459 // remove end comment delimiter |
7366 return p1.slice(0, -1); | 7460 return p1.slice(0, -1); |
7367 }); | 7461 }); |
7368 }, | 7462 return cssText.replace(cssContentRuleRe, function(match, p1, p2, p3) { |
7369 /* | 7463 var rule = match.replace(p1, '').replace(p2, ''); |
7370 * Process styles to add rules which will only apply under the polyfill | 7464 return p3 + rule; |
7371 * and do not process via CSSOM. (CSSOM is destructive to rules on rare | 7465 }); |
7372 * occasions, e.g. -webkit-calc on Safari.) | |
7373 * For example, we convert this rule: | |
7374 * | |
7375 * (comment start) @polyfill-unscoped-rule menu-item { | |
7376 * ... } (comment end) | |
7377 * | |
7378 * to this: | |
7379 * | |
7380 * menu-item {...} | |
7381 * | |
7382 **/ | |
7383 extractPolyfillUnscopedRules: function(styles) { | |
7384 var cssText = ''; | |
7385 if (styles) { | |
7386 Array.prototype.forEach.call(styles, function(s) { | |
7387 cssText += this.extractPolyfillUnscopedRulesFromCssText( | |
7388 s.textContent) + '\n\n'; | |
7389 }, this); | |
7390 } | |
7391 return cssText; | |
7392 }, | |
7393 extractPolyfillUnscopedRulesFromCssText: function(cssText) { | |
7394 var r = '', matches; | |
7395 while (matches = cssPolyfillUnscopedRuleCommentRe.exec(cssText)) { | |
7396 r += matches[1].slice(0, -1) + '\n\n'; | |
7397 } | |
7398 return r; | |
7399 }, | 7466 }, |
7400 /* Ensure styles are scoped. Pseudo-scoping takes a rule like: | 7467 /* Ensure styles are scoped. Pseudo-scoping takes a rule like: |
7401 * | 7468 * |
7402 * .foo {... } | 7469 * .foo {... } |
7403 * | 7470 * |
7404 * and converts this to | 7471 * and converts this to |
7405 * | 7472 * |
7406 * scopeName .foo { ... } | 7473 * scopeName .foo { ... } |
7407 */ | 7474 */ |
7408 shimScoping: function(styles, name, typeExtension) { | 7475 scopeCssText: function(cssText, scopeSelector) { |
7409 if (styles) { | 7476 var unscoped = this.extractUnscopedRulesFromCssText(cssText); |
7410 return this.convertScopedStyles(styles, name, typeExtension); | |
7411 } | |
7412 }, | |
7413 convertScopedStyles: function(styles, name, typeExtension) { | |
7414 var cssText = stylesToCssText(styles); | |
7415 cssText = this.insertPolyfillHostInCssText(cssText); | 7477 cssText = this.insertPolyfillHostInCssText(cssText); |
7416 cssText = this.convertColonHost(cssText); | 7478 cssText = this.convertColonHost(cssText); |
7417 cssText = this.convertColonAncestor(cssText); | 7479 cssText = this.convertColonAncestor(cssText); |
7418 cssText = this.convertCombinators(cssText); | 7480 cssText = this.convertCombinators(cssText); |
7419 if (name) { | 7481 if (scopeSelector) { |
7420 var self = this, cssText; | 7482 var self = this, cssText; |
7421 | |
7422 withCssRules(cssText, function(rules) { | 7483 withCssRules(cssText, function(rules) { |
7423 cssText = self.scopeRules(rules, name, typeExtension); | 7484 cssText = self.scopeRules(rules, scopeSelector); |
7424 }); | 7485 }); |
7425 | 7486 |
7426 } | 7487 } |
7427 return cssText; | 7488 cssText = cssText + '\n' + unscoped; |
| 7489 return cssText.trim(); |
| 7490 }, |
| 7491 /* |
| 7492 * Process styles to add rules which will only apply under the polyfill |
| 7493 * and do not process via CSSOM. (CSSOM is destructive to rules on rare |
| 7494 * occasions, e.g. -webkit-calc on Safari.) |
| 7495 * For example, we convert this rule: |
| 7496 * |
| 7497 * (comment start) @polyfill-unscoped-rule menu-item { |
| 7498 * ... } (comment end) |
| 7499 * |
| 7500 * to this: |
| 7501 * |
| 7502 * menu-item {...} |
| 7503 * |
| 7504 **/ |
| 7505 extractUnscopedRulesFromCssText: function(cssText) { |
| 7506 // TODO(sorvell): remove either content or comment |
| 7507 var r = '', m; |
| 7508 while (m = cssCommentUnscopedRuleRe.exec(cssText)) { |
| 7509 r += m[1].slice(0, -1) + '\n\n'; |
| 7510 } |
| 7511 while (m = cssContentUnscopedRuleRe.exec(cssText)) { |
| 7512 r += m[0].replace(m[2], '').replace(m[1], m[3]) + '\n\n'; |
| 7513 } |
| 7514 return r; |
7428 }, | 7515 }, |
7429 /* | 7516 /* |
7430 * convert a rule like :host(.foo) > .bar { } | 7517 * convert a rule like :host(.foo) > .bar { } |
7431 * | 7518 * |
7432 * to | 7519 * to |
7433 * | 7520 * |
7434 * scopeName.foo > .bar | 7521 * scopeName.foo > .bar |
7435 */ | 7522 */ |
7436 convertColonHost: function(cssText) { | 7523 convertColonHost: function(cssText) { |
7437 return this.convertColonRule(cssText, cssColonHostRe, | 7524 return this.convertColonRule(cssText, cssColonHostRe, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7482 colonHostPartReplacer: function(host, part, suffix) { | 7569 colonHostPartReplacer: function(host, part, suffix) { |
7483 return host + part.replace(polyfillHost, '') + suffix; | 7570 return host + part.replace(polyfillHost, '') + suffix; |
7484 }, | 7571 }, |
7485 /* | 7572 /* |
7486 * Convert ^ and ^^ combinators by replacing with space. | 7573 * Convert ^ and ^^ combinators by replacing with space. |
7487 */ | 7574 */ |
7488 convertCombinators: function(cssText) { | 7575 convertCombinators: function(cssText) { |
7489 return cssText.replace(/\^\^/g, ' ').replace(/\^/g, ' '); | 7576 return cssText.replace(/\^\^/g, ' ').replace(/\^/g, ' '); |
7490 }, | 7577 }, |
7491 // change a selector like 'div' to 'name div' | 7578 // change a selector like 'div' to 'name div' |
7492 scopeRules: function(cssRules, name, typeExtension) { | 7579 scopeRules: function(cssRules, scopeSelector) { |
7493 var cssText = ''; | 7580 var cssText = ''; |
7494 if (cssRules) { | 7581 if (cssRules) { |
7495 Array.prototype.forEach.call(cssRules, function(rule) { | 7582 Array.prototype.forEach.call(cssRules, function(rule) { |
7496 if (rule.selectorText && (rule.style && rule.style.cssText)) { | 7583 if (rule.selectorText && (rule.style && rule.style.cssText)) { |
7497 cssText += this.scopeSelector(rule.selectorText, name, typeExtension, | 7584 cssText += this.scopeSelector(rule.selectorText, scopeSelector, |
7498 this.strictStyling) + ' {\n\t'; | 7585 this.strictStyling) + ' {\n\t'; |
7499 cssText += this.propertiesFromRule(rule) + '\n}\n\n'; | 7586 cssText += this.propertiesFromRule(rule) + '\n}\n\n'; |
7500 } else if (rule.type === CSSRule.MEDIA_RULE) { | 7587 } else if (rule.type === CSSRule.MEDIA_RULE) { |
7501 cssText += '@media ' + rule.media.mediaText + ' {\n'; | 7588 cssText += '@media ' + rule.media.mediaText + ' {\n'; |
7502 cssText += this.scopeRules(rule.cssRules, name, typeExtension); | 7589 cssText += this.scopeRules(rule.cssRules, scopeSelector); |
7503 cssText += '\n}\n\n'; | 7590 cssText += '\n}\n\n'; |
7504 } else if (rule.cssText) { | 7591 } else if (rule.cssText) { |
7505 cssText += rule.cssText + '\n\n'; | 7592 cssText += rule.cssText + '\n\n'; |
7506 } | 7593 } |
7507 }, this); | 7594 }, this); |
7508 } | 7595 } |
7509 return cssText; | 7596 return cssText; |
7510 }, | 7597 }, |
7511 scopeSelector: function(selector, name, typeExtension, strict) { | 7598 scopeSelector: function(selector, scopeSelector, strict) { |
7512 var r = [], parts = selector.split(','); | 7599 var r = [], parts = selector.split(','); |
7513 parts.forEach(function(p) { | 7600 parts.forEach(function(p) { |
7514 p = p.trim(); | 7601 p = p.trim(); |
7515 if (this.selectorNeedsScoping(p, name, typeExtension)) { | 7602 if (this.selectorNeedsScoping(p, scopeSelector)) { |
7516 p = (strict && !p.match(polyfillHostNoCombinator)) ? | 7603 p = (strict && !p.match(polyfillHostNoCombinator)) ? |
7517 this.applyStrictSelectorScope(p, name) : | 7604 this.applyStrictSelectorScope(p, scopeSelector) : |
7518 this.applySimpleSelectorScope(p, name, typeExtension); | 7605 this.applySimpleSelectorScope(p, scopeSelector); |
7519 } | 7606 } |
7520 r.push(p); | 7607 r.push(p); |
7521 }, this); | 7608 }, this); |
7522 return r.join(', '); | 7609 return r.join(', '); |
7523 }, | 7610 }, |
7524 selectorNeedsScoping: function(selector, name, typeExtension) { | 7611 selectorNeedsScoping: function(selector, scopeSelector) { |
7525 var re = this.makeScopeMatcher(name, typeExtension); | 7612 var re = this.makeScopeMatcher(scopeSelector); |
7526 return !selector.match(re); | 7613 return !selector.match(re); |
7527 }, | 7614 }, |
7528 makeScopeMatcher: function(name, typeExtension) { | 7615 makeScopeMatcher: function(scopeSelector) { |
7529 var matchScope = typeExtension ? '\\[is=[\'"]?' + name + '[\'"]?\\]' : name; | 7616 scopeSelector = scopeSelector.replace(/\[/g, '\\[').replace(/\[/g, '\\]'); |
7530 return new RegExp('^(' + matchScope + ')' + selectorReSuffix, 'm'); | 7617 return new RegExp('^(' + scopeSelector + ')' + selectorReSuffix, 'm'); |
7531 }, | 7618 }, |
7532 // scope via name and [is=name] | 7619 // scope via name and [is=name] |
7533 applySimpleSelectorScope: function(selector, name, typeExtension) { | 7620 applySimpleSelectorScope: function(selector, scopeSelector) { |
7534 var scoper = typeExtension ? '[is=' + name + ']' : name; | |
7535 if (selector.match(polyfillHostRe)) { | 7621 if (selector.match(polyfillHostRe)) { |
7536 selector = selector.replace(polyfillHostNoCombinator, scoper); | 7622 selector = selector.replace(polyfillHostNoCombinator, scopeSelector); |
7537 return selector.replace(polyfillHostRe, scoper + ' '); | 7623 return selector.replace(polyfillHostRe, scopeSelector + ' '); |
7538 } else { | 7624 } else { |
7539 return scoper + ' ' + selector; | 7625 return scopeSelector + ' ' + selector; |
7540 } | 7626 } |
7541 }, | 7627 }, |
7542 // return a selector with [name] suffix on each simple selector | 7628 // return a selector with [name] suffix on each simple selector |
7543 // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name] | 7629 // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name] |
7544 applyStrictSelectorScope: function(selector, name) { | 7630 applyStrictSelectorScope: function(selector, scopeSelector) { |
| 7631 scopeSelector = scopeSelector.replace(/\[is=([^\]]*)\]/g, '$1'); |
7545 var splits = [' ', '>', '+', '~'], | 7632 var splits = [' ', '>', '+', '~'], |
7546 scoped = selector, | 7633 scoped = selector, |
7547 attrName = '[' + name + ']'; | 7634 attrName = '[' + scopeSelector + ']'; |
7548 splits.forEach(function(sep) { | 7635 splits.forEach(function(sep) { |
7549 var parts = scoped.split(sep); | 7636 var parts = scoped.split(sep); |
7550 scoped = parts.map(function(p) { | 7637 scoped = parts.map(function(p) { |
7551 // remove :host since it should be unnecessary | 7638 // remove :host since it should be unnecessary |
7552 var t = p.trim().replace(polyfillHostRe, ''); | 7639 var t = p.trim().replace(polyfillHostRe, ''); |
7553 if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) { | 7640 if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) { |
7554 p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3') | 7641 p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3') |
7555 } | 7642 } |
7556 return p; | 7643 return p; |
7557 }).join(sep); | 7644 }).join(sep); |
7558 }); | 7645 }); |
7559 return scoped; | 7646 return scoped; |
7560 }, | 7647 }, |
7561 insertPolyfillHostInCssText: function(selector) { | 7648 insertPolyfillHostInCssText: function(selector) { |
7562 return selector.replace(hostRe, polyfillHost).replace(colonHostRe, | 7649 return selector.replace(hostRe, polyfillHost).replace(colonHostRe, |
7563 polyfillHost).replace(colonAncestorRe, polyfillAncestor); | 7650 polyfillHost).replace(colonAncestorRe, polyfillAncestor); |
7564 }, | 7651 }, |
7565 propertiesFromRule: function(rule) { | 7652 propertiesFromRule: function(rule) { |
7566 // TODO(sorvell): Safari cssom incorrectly removes quotes from the content | 7653 // TODO(sorvell): Safari cssom incorrectly removes quotes from the content |
7567 // property. (https://bugs.webkit.org/show_bug.cgi?id=118045) | 7654 // property. (https://bugs.webkit.org/show_bug.cgi?id=118045) |
7568 if (rule.style.content && !rule.style.content.match(/['"]+/)) { | 7655 if (rule.style.content && !rule.style.content.match(/['"]+/)) { |
7569 return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \'' + | 7656 return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \'' + |
7570 rule.style.content + '\';'); | 7657 rule.style.content + '\';'); |
7571 } | 7658 } |
7572 return rule.style.cssText; | 7659 return rule.style.cssText; |
| 7660 }, |
| 7661 replaceTextInStyles: function(styles, action) { |
| 7662 if (styles && action) { |
| 7663 if (!(styles instanceof Array)) { |
| 7664 styles = [styles]; |
| 7665 } |
| 7666 Array.prototype.forEach.call(styles, function(s) { |
| 7667 s.textContent = action.call(this, s.textContent); |
| 7668 }, this); |
| 7669 } |
| 7670 }, |
| 7671 addCssToDocument: function(cssText, name) { |
| 7672 if (cssText.match('@import')) { |
| 7673 addOwnSheet(cssText, name); |
| 7674 } else { |
| 7675 addCssToDocument(cssText); |
| 7676 } |
7573 } | 7677 } |
7574 }; | 7678 }; |
7575 | 7679 |
7576 var selectorRe = /([^{]*)({[\s\S]*?})/gim, | 7680 var selectorRe = /([^{]*)({[\s\S]*?})/gim, |
7577 cssCommentRe = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, | 7681 cssCommentRe = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, |
7578 cssPolyfillCommentRe = /\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?
){/gim, | 7682 // TODO(sorvell): remove either content or comment |
7579 cssPolyfillRuleCommentRe = /\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\/
/gim, | 7683 cssCommentNextSelectorRe = /\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^
{]*?){/gim, |
7580 cssPolyfillUnscopedRuleCommentRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([
^/*][^*]*\*+)*)\//gim, | 7684 cssContentNextSelectorRe = /polyfill-next-selector[^}]*content\:[\s]*'([^']*
)'[^}]*}([^{]*?){/gim, |
| 7685 // TODO(sorvell): remove either content or comment |
| 7686 cssCommentRuleRe = /\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim, |
| 7687 cssContentRuleRe = /(polyfill-rule)[^}]*(content\:[\s]*'([^']*)'[^;]*;)[^}]*
}/gim, |
| 7688 // TODO(sorvell): remove either content or comment |
| 7689 cssCommentUnscopedRuleRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]
*\*+)*)\//gim, |
| 7690 cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content\:[\s]*'([^
']*)'[^;]*;)[^}]*}/gim, |
7581 cssPseudoRe = /::(x-[^\s{,(]*)/gim, | 7691 cssPseudoRe = /::(x-[^\s{,(]*)/gim, |
7582 cssPartRe = /::part\(([^)]*)\)/gim, | 7692 cssPartRe = /::part\(([^)]*)\)/gim, |
7583 // note: :host pre-processed to -shadowcsshost. | 7693 // note: :host pre-processed to -shadowcsshost. |
7584 polyfillHost = '-shadowcsshost', | 7694 polyfillHost = '-shadowcsshost', |
7585 // note: :ancestor pre-processed to -shadowcssancestor. | 7695 // note: :ancestor pre-processed to -shadowcssancestor. |
7586 polyfillAncestor = '-shadowcssancestor', | 7696 polyfillAncestor = '-shadowcssancestor', |
7587 parenSuffix = ')(?:\\((' + | 7697 parenSuffix = ')(?:\\((' + |
7588 '(?:\\([^)(]*\\)|[^)(]*)+?' + | 7698 '(?:\\([^)(]*\\)|[^)(]*)+?' + |
7589 ')\\))?([^,{]*)'; | 7699 ')\\))?([^,{]*)'; |
7590 cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'), | 7700 cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'), |
7591 cssColonAncestorRe = new RegExp('(' + polyfillAncestor + parenSuffix, 'gim')
, | 7701 cssColonAncestorRe = new RegExp('(' + polyfillAncestor + parenSuffix, 'gim')
, |
7592 selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$', | 7702 selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$', |
7593 hostRe = /@host/gim, | 7703 hostRe = /@host/gim, |
7594 colonHostRe = /\:host/gim, | 7704 colonHostRe = /\:host/gim, |
7595 colonAncestorRe = /\:ancestor/gim, | 7705 colonAncestorRe = /\:ancestor/gim, |
7596 /* host name without combinator */ | 7706 /* host name without combinator */ |
7597 polyfillHostNoCombinator = polyfillHost + '-no-combinator', | 7707 polyfillHostNoCombinator = polyfillHost + '-no-combinator', |
7598 polyfillHostRe = new RegExp(polyfillHost, 'gim'); | 7708 polyfillHostRe = new RegExp(polyfillHost, 'gim'), |
7599 polyfillAncestorRe = new RegExp(polyfillAncestor, 'gim'); | 7709 polyfillAncestorRe = new RegExp(polyfillAncestor, 'gim'); |
7600 | 7710 |
7601 function stylesToCssText(styles, preserveComments) { | 7711 function stylesToCssText(styles, preserveComments) { |
7602 var cssText = ''; | 7712 var cssText = ''; |
7603 Array.prototype.forEach.call(styles, function(s) { | 7713 Array.prototype.forEach.call(styles, function(s) { |
7604 cssText += s.textContent + '\n\n'; | 7714 cssText += s.textContent + '\n\n'; |
7605 }); | 7715 }); |
7606 // strip comments for easier processing | 7716 // strip comments for easier processing |
7607 if (!preserveComments) { | 7717 if (!preserveComments) { |
7608 cssText = cssText.replace(cssCommentRe, ''); | 7718 cssText = cssText.replace(cssCommentRe, ''); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7693 | 7803 |
7694 function addOwnSheet(cssText, name) { | 7804 function addOwnSheet(cssText, name) { |
7695 var style = cssTextToStyle(cssText); | 7805 var style = cssTextToStyle(cssText); |
7696 style.setAttribute(name, ''); | 7806 style.setAttribute(name, ''); |
7697 style.setAttribute(SHIMMED_ATTRIBUTE, ''); | 7807 style.setAttribute(SHIMMED_ATTRIBUTE, ''); |
7698 document.head.appendChild(style); | 7808 document.head.appendChild(style); |
7699 } | 7809 } |
7700 | 7810 |
7701 var SHIM_ATTRIBUTE = 'shim-shadowdom'; | 7811 var SHIM_ATTRIBUTE = 'shim-shadowdom'; |
7702 var SHIMMED_ATTRIBUTE = 'shim-shadowdom-css'; | 7812 var SHIMMED_ATTRIBUTE = 'shim-shadowdom-css'; |
| 7813 var NO_SHIM_ATTRIBUTE = 'no-shim'; |
7703 | 7814 |
7704 var sheet; | 7815 var sheet; |
7705 function getSheet() { | 7816 function getSheet() { |
7706 if (!sheet) { | 7817 if (!sheet) { |
7707 sheet = document.createElement("style"); | 7818 sheet = document.createElement("style"); |
7708 sheet.setAttribute(SHIMMED_ATTRIBUTE, ''); | 7819 sheet.setAttribute(SHIMMED_ATTRIBUTE, ''); |
7709 sheet[SHIMMED_ATTRIBUTE] = true; | 7820 sheet[SHIMMED_ATTRIBUTE] = true; |
7710 } | 7821 } |
7711 return sheet; | 7822 return sheet; |
7712 } | 7823 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7747 originalParseGeneric.call(this, elt); | 7858 originalParseGeneric.call(this, elt); |
7748 return; | 7859 return; |
7749 } | 7860 } |
7750 if (elt.__resource) { | 7861 if (elt.__resource) { |
7751 style = elt.ownerDocument.createElement('style'); | 7862 style = elt.ownerDocument.createElement('style'); |
7752 style.textContent = urlResolver.resolveCssText( | 7863 style.textContent = urlResolver.resolveCssText( |
7753 elt.__resource, elt.href); | 7864 elt.__resource, elt.href); |
7754 } else { | 7865 } else { |
7755 urlResolver.resolveStyle(style); | 7866 urlResolver.resolveStyle(style); |
7756 } | 7867 } |
7757 var styles = [style]; | 7868 style.textContent = ShadowCSS.shimStyle(style); |
7758 style.textContent = ShadowCSS.stylesToShimmedCssText(styles, styles); | |
7759 style.removeAttribute(SHIM_ATTRIBUTE, ''); | 7869 style.removeAttribute(SHIM_ATTRIBUTE, ''); |
7760 style.setAttribute(SHIMMED_ATTRIBUTE, ''); | 7870 style.setAttribute(SHIMMED_ATTRIBUTE, ''); |
7761 style[SHIMMED_ATTRIBUTE] = true; | 7871 style[SHIMMED_ATTRIBUTE] = true; |
7762 // place in document | 7872 // place in document |
7763 if (style.parentNode !== head) { | 7873 if (style.parentNode !== head) { |
7764 // replace links in head | 7874 // replace links in head |
7765 if (elt.parentNode === head) { | 7875 if (elt.parentNode === head) { |
7766 head.replaceChild(style, elt); | 7876 head.replaceChild(style, elt); |
7767 } else { | 7877 } else { |
7768 head.appendChild(style); | 7878 head.appendChild(style); |
(...skipping 3936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11705 * @return {Event} A new PointerEvent of type `inType` and initialized with prop
erties from `inDict`. | 11815 * @return {Event} A new PointerEvent of type `inType` and initialized with prop
erties from `inDict`. |
11706 */ | 11816 */ |
11707 (function(scope) { | 11817 (function(scope) { |
11708 // test for DOM Level 4 Events | 11818 // test for DOM Level 4 Events |
11709 var NEW_MOUSE_EVENT = false; | 11819 var NEW_MOUSE_EVENT = false; |
11710 var HAS_BUTTONS = false; | 11820 var HAS_BUTTONS = false; |
11711 try { | 11821 try { |
11712 var ev = new MouseEvent('click', {buttons: 1}); | 11822 var ev = new MouseEvent('click', {buttons: 1}); |
11713 NEW_MOUSE_EVENT = true; | 11823 NEW_MOUSE_EVENT = true; |
11714 HAS_BUTTONS = ev.buttons === 1; | 11824 HAS_BUTTONS = ev.buttons === 1; |
| 11825 ev = null; |
11715 } catch(e) { | 11826 } catch(e) { |
11716 } | 11827 } |
11717 | 11828 |
11718 var MOUSE_PROPS = [ | 11829 var MOUSE_PROPS = [ |
11719 'bubbles', | 11830 'bubbles', |
11720 'cancelable', | 11831 'cancelable', |
11721 'view', | 11832 'view', |
11722 'detail', | 11833 'detail', |
11723 'screenX', | 11834 'screenX', |
11724 'screenY', | 11835 'screenY', |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11765 // but initMouseEvent does not expose an argument with which to set | 11876 // but initMouseEvent does not expose an argument with which to set |
11766 // MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set | 11877 // MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set |
11767 // MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectatio
ns | 11878 // MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectatio
ns |
11768 // of app developers. | 11879 // of app developers. |
11769 // | 11880 // |
11770 // The only way to propagate the correct state of MouseEvent.which and | 11881 // The only way to propagate the correct state of MouseEvent.which and |
11771 // MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which ==
0 | 11882 // MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which ==
0 |
11772 // is to call initMouseEvent with a buttonArg value of -1. | 11883 // is to call initMouseEvent with a buttonArg value of -1. |
11773 // | 11884 // |
11774 // This is fixed with DOM Level 4's use of buttons | 11885 // This is fixed with DOM Level 4's use of buttons |
11775 var buttons; | 11886 var buttons = inDict.buttons; |
11776 if (inDict.buttons || HAS_BUTTONS) { | 11887 // touch has two possible buttons state: 0 and 1, rely on being told the rig
ht one |
11777 buttons = inDict.buttons; | 11888 if (!HAS_BUTTONS && !buttons && inType !== 'touch') { |
11778 } else { | |
11779 switch (inDict.which) { | 11889 switch (inDict.which) { |
11780 case 1: buttons = 1; break; | 11890 case 1: buttons = 1; break; |
11781 case 2: buttons = 4; break; | 11891 case 2: buttons = 4; break; |
11782 case 3: buttons = 2; break; | 11892 case 3: buttons = 2; break; |
11783 default: buttons = 0; | 11893 default: buttons = 0; |
11784 } | 11894 } |
11785 } | 11895 } |
11786 | 11896 |
11787 var e; | 11897 var e; |
11788 if (NEW_MOUSE_EVENT) { | 11898 if (NEW_MOUSE_EVENT) { |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12313 this.addCallback(el); | 12423 this.addCallback(el); |
12314 }, | 12424 }, |
12315 elementChanged: function(el, oldValue) { | 12425 elementChanged: function(el, oldValue) { |
12316 this.changedCallback(el, oldValue); | 12426 this.changedCallback(el, oldValue); |
12317 }, | 12427 }, |
12318 concatLists: function(accum, list) { | 12428 concatLists: function(accum, list) { |
12319 return accum.concat(toArray(list)); | 12429 return accum.concat(toArray(list)); |
12320 }, | 12430 }, |
12321 // register all touch-action = none nodes on document load | 12431 // register all touch-action = none nodes on document load |
12322 installOnLoad: function() { | 12432 installOnLoad: function() { |
12323 document.addEventListener('DOMContentLoaded', this.installNewSubtree.bind(
this, document)); | 12433 document.addEventListener('readystatechange', function() { |
| 12434 if (document.readyState === 'complete') { |
| 12435 this.installNewSubtree(document); |
| 12436 } |
| 12437 }.bind(this)); |
12324 }, | 12438 }, |
12325 isElement: function(n) { | 12439 isElement: function(n) { |
12326 return n.nodeType === Node.ELEMENT_NODE; | 12440 return n.nodeType === Node.ELEMENT_NODE; |
12327 }, | 12441 }, |
12328 flattenMutationTree: function(inNodes) { | 12442 flattenMutationTree: function(inNodes) { |
12329 // find children with touch-action | 12443 // find children with touch-action |
12330 var tree = map(inNodes, this.findElements, this); | 12444 var tree = map(inNodes, this.findElements, this); |
12331 // make sure the added nodes are accounted for | 12445 // make sure the added nodes are accounted for |
12332 tree.push(filter(inNodes, this.isElement)); | 12446 tree.push(filter(inNodes, this.isElement)); |
12333 // flatten the list | 12447 // flatten the list |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12598 this.clickCount = 0; | 12712 this.clickCount = 0; |
12599 this.resetId = null; | 12713 this.resetId = null; |
12600 }.bind(this); | 12714 }.bind(this); |
12601 this.resetId = setTimeout(fn, CLICK_COUNT_TIMEOUT); | 12715 this.resetId = setTimeout(fn, CLICK_COUNT_TIMEOUT); |
12602 }, | 12716 }, |
12603 cancelResetClickCount: function() { | 12717 cancelResetClickCount: function() { |
12604 if (this.resetId) { | 12718 if (this.resetId) { |
12605 clearTimeout(this.resetId); | 12719 clearTimeout(this.resetId); |
12606 } | 12720 } |
12607 }, | 12721 }, |
| 12722 typeToButtons: function(type) { |
| 12723 var ret = 0; |
| 12724 if (type === 'touchstart' || type === 'touchmove') { |
| 12725 ret = 1; |
| 12726 } |
| 12727 return ret; |
| 12728 }, |
12608 touchToPointer: function(inTouch) { | 12729 touchToPointer: function(inTouch) { |
12609 var e = dispatcher.cloneEvent(inTouch); | 12730 var e = dispatcher.cloneEvent(inTouch); |
12610 // Spec specifies that pointerId 1 is reserved for Mouse. | 12731 // Spec specifies that pointerId 1 is reserved for Mouse. |
12611 // Touch identifiers can start at 0. | 12732 // Touch identifiers can start at 0. |
12612 // Add 2 to the touch identifier for compatibility. | 12733 // Add 2 to the touch identifier for compatibility. |
12613 e.pointerId = inTouch.identifier + 2; | 12734 e.pointerId = inTouch.identifier + 2; |
12614 e.target = findTarget(e); | 12735 e.target = findTarget(e); |
12615 e.bubbles = true; | 12736 e.bubbles = true; |
12616 e.cancelable = true; | 12737 e.cancelable = true; |
12617 e.detail = this.clickCount; | 12738 e.detail = this.clickCount; |
12618 e.button = 0; | 12739 e.button = 0; |
12619 e.buttons = 1; | 12740 e.buttons = this.typeToButtons(this.currentTouchEvent); |
12620 e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0; | 12741 e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0; |
12621 e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0; | 12742 e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0; |
12622 e.pressure = inTouch.webkitForce || inTouch.force || 0.5; | 12743 e.pressure = inTouch.webkitForce || inTouch.force || 0.5; |
12623 e.isPrimary = this.isPrimaryTouch(inTouch); | 12744 e.isPrimary = this.isPrimaryTouch(inTouch); |
12624 e.pointerType = this.POINTER_TYPE; | 12745 e.pointerType = this.POINTER_TYPE; |
12625 return e; | 12746 return e; |
12626 }, | 12747 }, |
12627 processTouches: function(inEvent, inFunction) { | 12748 processTouches: function(inEvent, inFunction) { |
12628 var tl = inEvent.changedTouches; | 12749 var tl = inEvent.changedTouches; |
| 12750 this.currentTouchEvent = inEvent.type; |
12629 var pointers = touchMap(tl, this.touchToPointer, this); | 12751 var pointers = touchMap(tl, this.touchToPointer, this); |
12630 // forward touch preventDefaults | 12752 // forward touch preventDefaults |
12631 pointers.forEach(function(p) { | 12753 pointers.forEach(function(p) { |
12632 p.preventDefault = function() { | 12754 p.preventDefault = function() { |
12633 this.scrolling = false; | 12755 this.scrolling = false; |
12634 this.firstXY = null; | 12756 this.firstXY = null; |
12635 inEvent.preventDefault(); | 12757 inEvent.preventDefault(); |
12636 }; | 12758 }; |
12637 }, this); | 12759 }, this); |
12638 pointers.forEach(inFunction, this); | 12760 pointers.forEach(inFunction, this); |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13353 setTimeout(fn, 0); | 13475 setTimeout(fn, 0); |
13354 }, | 13476 }, |
13355 preventTap: function(inPointerId) { | 13477 preventTap: function(inPointerId) { |
13356 var t = this.recognizers.tap; | 13478 var t = this.recognizers.tap; |
13357 if (t){ | 13479 if (t){ |
13358 t.preventTap(inPointerId); | 13480 t.preventTap(inPointerId); |
13359 } | 13481 } |
13360 } | 13482 } |
13361 }; | 13483 }; |
13362 dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher); | 13484 dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher); |
| 13485 // recognizers call into the dispatcher and load later |
| 13486 // solve the chicken and egg problem by having registerScopes module run last |
| 13487 dispatcher.registerQueue = []; |
| 13488 dispatcher.immediateRegister = false; |
13363 scope.dispatcher = dispatcher; | 13489 scope.dispatcher = dispatcher; |
13364 var registerQueue = []; | |
13365 var immediateRegister = false; | |
13366 /** | 13490 /** |
13367 * Enable gesture events for a given scope, typically | 13491 * Enable gesture events for a given scope, typically |
13368 * [ShadowRoots](https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow
/index.html#shadow-root-object). | 13492 * [ShadowRoots](https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow
/index.html#shadow-root-object). |
13369 * | 13493 * |
13370 * @for PointerGestures | 13494 * @for PointerGestures |
13371 * @method register | 13495 * @method register |
13372 * @param {ShadowRoot} scope A top level scope to enable gesture | 13496 * @param {ShadowRoot} scope A top level scope to enable gesture |
13373 * support on. | 13497 * support on. |
13374 */ | 13498 */ |
13375 scope.register = function(inScope) { | 13499 scope.register = function(inScope) { |
13376 if (immediateRegister) { | 13500 if (dispatcher.immediateRegister) { |
13377 var pe = window.PointerEventsPolyfill; | 13501 var pe = window.PointerEventsPolyfill; |
13378 if (pe) { | 13502 if (pe) { |
13379 pe.register(inScope); | 13503 pe.register(inScope); |
13380 } | 13504 } |
13381 scope.dispatcher.registerTarget(inScope); | 13505 scope.dispatcher.registerTarget(inScope); |
13382 } else { | 13506 } else { |
13383 registerQueue.push(inScope); | 13507 dispatcher.registerQueue.push(inScope); |
13384 } | 13508 } |
13385 }; | 13509 }; |
13386 // wait to register scopes until recognizers load | 13510 scope.register(document); |
13387 document.addEventListener('DOMContentLoaded', function() { | |
13388 immediateRegister = true; | |
13389 registerQueue.push(document); | |
13390 registerQueue.forEach(scope.register); | |
13391 }); | |
13392 })(window.PointerGestures); | 13511 })(window.PointerGestures); |
13393 | 13512 |
13394 /* | 13513 /* |
13395 * Copyright 2013 The Polymer Authors. All rights reserved. | 13514 * Copyright 2013 The Polymer Authors. All rights reserved. |
13396 * Use of this source code is governed by a BSD-style | 13515 * Use of this source code is governed by a BSD-style |
13397 * license that can be found in the LICENSE file. | 13516 * license that can be found in the LICENSE file. |
13398 */ | 13517 */ |
13399 | 13518 |
13400 /** | 13519 /** |
13401 * This event is fired when a pointer is held down for 200ms. | 13520 * This event is fired when a pointer is held down for 200ms. |
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14045 'pointerdown', | 14164 'pointerdown', |
14046 'pointermove', | 14165 'pointermove', |
14047 'pointerup', | 14166 'pointerup', |
14048 'pointercancel', | 14167 'pointercancel', |
14049 'keyup' | 14168 'keyup' |
14050 ], | 14169 ], |
14051 pointerdown: function(inEvent) { | 14170 pointerdown: function(inEvent) { |
14052 if (inEvent.isPrimary && !inEvent.tapPrevented) { | 14171 if (inEvent.isPrimary && !inEvent.tapPrevented) { |
14053 pointermap.set(inEvent.pointerId, { | 14172 pointermap.set(inEvent.pointerId, { |
14054 target: inEvent.target, | 14173 target: inEvent.target, |
| 14174 buttons: inEvent.buttons, |
14055 x: inEvent.clientX, | 14175 x: inEvent.clientX, |
14056 y: inEvent.clientY | 14176 y: inEvent.clientY |
14057 }); | 14177 }); |
14058 } | 14178 } |
14059 }, | 14179 }, |
14060 pointermove: function(inEvent) { | 14180 pointermove: function(inEvent) { |
14061 if (inEvent.isPrimary) { | 14181 if (inEvent.isPrimary) { |
14062 var start = pointermap.get(inEvent.pointerId); | 14182 var start = pointermap.get(inEvent.pointerId); |
14063 if (start) { | 14183 if (start) { |
14064 if (inEvent.tapPrevented) { | 14184 if (inEvent.tapPrevented) { |
14065 pointermap.delete(inEvent.pointerId); | 14185 pointermap.delete(inEvent.pointerId); |
14066 } | 14186 } |
14067 } | 14187 } |
14068 } | 14188 } |
14069 }, | 14189 }, |
14070 shouldTap: function(e) { | 14190 shouldTap: function(e, downState) { |
14071 if (!e.tapPrevented) { | 14191 if (!e.tapPrevented) { |
14072 // only allow left click to tap for mouse | 14192 if (e.pointerType === 'mouse') { |
14073 return e.pointerType === 'mouse' ? e.buttons === 1 : true; | 14193 // only allow left click to tap for mouse |
| 14194 return downState.buttons === 1; |
| 14195 } else { |
| 14196 return true; |
| 14197 } |
14074 } | 14198 } |
14075 }, | 14199 }, |
14076 pointerup: function(inEvent) { | 14200 pointerup: function(inEvent) { |
14077 var start = pointermap.get(inEvent.pointerId); | 14201 var start = pointermap.get(inEvent.pointerId); |
14078 if (start && this.shouldTap(inEvent)) { | 14202 if (start && this.shouldTap(inEvent, start)) { |
14079 var t = scope.findLCA(start.target, inEvent.target); | 14203 var t = scope.findLCA(start.target, inEvent.target); |
14080 if (t) { | 14204 if (t) { |
14081 var e = dispatcher.makeEvent('tap', { | 14205 var e = dispatcher.makeEvent('tap', { |
14082 x: inEvent.clientX, | 14206 x: inEvent.clientX, |
14083 y: inEvent.clientY, | 14207 y: inEvent.clientY, |
14084 detail: inEvent.detail, | 14208 detail: inEvent.detail, |
14085 pointerType: inEvent.pointerType | 14209 pointerType: inEvent.pointerType |
14086 }); | 14210 }); |
14087 dispatcher.dispatchEvent(e, t); | 14211 dispatcher.dispatchEvent(e, t); |
14088 } | 14212 } |
(...skipping 18 matching lines...) Expand all Loading... |
14107 } | 14231 } |
14108 } | 14232 } |
14109 }, | 14233 }, |
14110 preventTap: function(inPointerId) { | 14234 preventTap: function(inPointerId) { |
14111 pointermap.delete(inPointerId); | 14235 pointermap.delete(inPointerId); |
14112 } | 14236 } |
14113 }; | 14237 }; |
14114 dispatcher.registerRecognizer('tap', tap); | 14238 dispatcher.registerRecognizer('tap', tap); |
14115 })(window.PointerGestures); | 14239 })(window.PointerGestures); |
14116 | 14240 |
| 14241 /* |
| 14242 * Copyright 2014 The Polymer Authors. All rights reserved. |
| 14243 * Use of this source code is governed by a BSD-style |
| 14244 * license that can be found in the LICENSE file. |
| 14245 */ |
| 14246 |
| 14247 /** |
| 14248 * Because recognizers are loaded after dispatcher, we have to wait to register |
| 14249 * scopes until after all the recognizers. |
| 14250 */ |
| 14251 (function(scope) { |
| 14252 var dispatcher = scope.dispatcher; |
| 14253 function registerScopes() { |
| 14254 dispatcher.immediateRegister = true; |
| 14255 var rq = dispatcher.registerQueue; |
| 14256 rq.forEach(scope.register); |
| 14257 rq.length = 0; |
| 14258 } |
| 14259 if (document.readyState === 'complete') { |
| 14260 registerScopes(); |
| 14261 } else { |
| 14262 // register scopes after a steadystate is reached |
| 14263 // less MutationObserver churn |
| 14264 document.addEventListener('readystatechange', function() { |
| 14265 if (document.readyState === 'complete') { |
| 14266 registerScopes(); |
| 14267 } |
| 14268 }); |
| 14269 } |
| 14270 })(window.PointerGestures); |
| 14271 |
14117 // Copyright 2011 Google Inc. | 14272 // Copyright 2011 Google Inc. |
14118 // | 14273 // |
14119 // Licensed under the Apache License, Version 2.0 (the "License"); | 14274 // Licensed under the Apache License, Version 2.0 (the "License"); |
14120 // you may not use this file except in compliance with the License. | 14275 // you may not use this file except in compliance with the License. |
14121 // You may obtain a copy of the License at | 14276 // You may obtain a copy of the License at |
14122 // | 14277 // |
14123 // http://www.apache.org/licenses/LICENSE-2.0 | 14278 // http://www.apache.org/licenses/LICENSE-2.0 |
14124 // | 14279 // |
14125 // Unless required by applicable law or agreed to in writing, software | 14280 // Unless required by applicable law or agreed to in writing, software |
14126 // distributed under the License is distributed on an "AS IS" BASIS, | 14281 // distributed under the License is distributed on an "AS IS" BASIS, |
14127 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 14282 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14128 // See the License for the specific language governing permissions and | 14283 // See the License for the specific language governing permissions and |
14129 // limitations under the License. | 14284 // limitations under the License. |
14130 | 14285 |
14131 (function(global) { | 14286 (function(global) { |
14132 'use strict'; | 14287 'use strict'; |
14133 | 14288 |
14134 var filter = Array.prototype.filter.call.bind(Array.prototype.filter); | 14289 var filter = Array.prototype.filter.call.bind(Array.prototype.filter); |
14135 | 14290 |
14136 function getTreeScope(node) { | 14291 function getTreeScope(node) { |
14137 while (node.parentNode) { | 14292 while (node.parentNode) { |
14138 node = node.parentNode; | 14293 node = node.parentNode; |
14139 } | 14294 } |
14140 | 14295 |
14141 return typeof node.getElementById === 'function' ? node : null; | 14296 return typeof node.getElementById === 'function' ? node : null; |
14142 } | 14297 } |
14143 | 14298 |
14144 // JScript does not have __proto__. We wrap all object literals with | |
14145 // createObject which uses Object.create, Object.defineProperty and | |
14146 // Object.getOwnPropertyDescriptor to create a new object that does the exact | |
14147 // same thing. The main downside to this solution is that we have to extract | |
14148 // all those property descriptors for IE. | |
14149 var createObject = ('__proto__' in {}) ? | |
14150 function(obj) { return obj; } : | |
14151 function(obj) { | |
14152 var proto = obj.__proto__; | |
14153 if (!proto) | |
14154 return obj; | |
14155 var newObject = Object.create(proto); | |
14156 Object.getOwnPropertyNames(obj).forEach(function(name) { | |
14157 Object.defineProperty(newObject, name, | |
14158 Object.getOwnPropertyDescriptor(obj, name)); | |
14159 }); | |
14160 return newObject; | |
14161 }; | |
14162 | |
14163 // IE does not support have Document.prototype.contains. | |
14164 if (typeof document.contains != 'function') { | |
14165 Document.prototype.contains = function(node) { | |
14166 if (node === this || node.parentNode === this) | |
14167 return true; | |
14168 return this.documentElement.contains(node); | |
14169 } | |
14170 } | |
14171 | 14299 |
14172 Node.prototype.bind = function(name, observable) { | 14300 Node.prototype.bind = function(name, observable) { |
14173 console.error('Unhandled binding to Node: ', this, name, observable); | 14301 console.error('Unhandled binding to Node: ', this, name, observable); |
14174 }; | 14302 }; |
14175 | 14303 |
14176 function unbind(node, name) { | 14304 function unbind(node, name) { |
14177 var bindings = node.bindings; | 14305 var bindings = node.bindings; |
14178 if (!bindings) { | 14306 if (!bindings) { |
14179 node.bindings = {}; | 14307 node.bindings = {}; |
14180 return; | 14308 return; |
(...skipping 3295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17476 } | 17604 } |
17477 } | 17605 } |
17478 | 17606 |
17479 // exports | 17607 // exports |
17480 scope.flush = flush; | 17608 scope.flush = flush; |
17481 | 17609 |
17482 })(window.Platform); | 17610 })(window.Platform); |
17483 | 17611 |
17484 | 17612 |
17485 //# sourceMappingURL=platform.concat.js.map | 17613 //# sourceMappingURL=platform.concat.js.map |
OLD | NEW |