| 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 |