OLD | NEW |
1 if (!HTMLElement.prototype.createShadowRoot | 1 if (!HTMLElement.prototype.createShadowRoot |
2 || window.__forceShadowDomPolyfill) { | 2 || window.__forceShadowDomPolyfill) { |
3 | 3 |
4 /* | 4 /* |
5 * Copyright 2013 The Polymer Authors. All rights reserved. | 5 * Copyright 2013 The Polymer Authors. All rights reserved. |
6 * Use of this source code is governed by a BSD-style | 6 * Use of this source code is governed by a BSD-style |
7 * license that can be found in the LICENSE file. | 7 * license that can be found in the LICENSE file. |
8 */ | 8 */ |
9 (function() { | 9 (function() { |
10 // TODO(jmesserly): fix dart:html to use unprefixed name | 10 // TODO(jmesserly): fix dart:html to use unprefixed name |
(...skipping 1866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1877 return node.parentNode || (dv = node.defaultView) && wrap(dv) || null; | 1877 return node.parentNode || (dv = node.defaultView) && wrap(dv) || null; |
1878 } | 1878 } |
1879 | 1879 |
1880 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#df
n-adjusted-parent | 1880 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#df
n-adjusted-parent |
1881 function calculateParents(node, context, ancestors) { | 1881 function calculateParents(node, context, ancestors) { |
1882 if (ancestors.length) | 1882 if (ancestors.length) |
1883 return ancestors.shift(); | 1883 return ancestors.shift(); |
1884 | 1884 |
1885 // 1. | 1885 // 1. |
1886 if (isShadowRoot(node)) | 1886 if (isShadowRoot(node)) |
1887 return getInsertionParent(node) || scope.getHostForShadowRoot(node); | 1887 return getInsertionParent(node) || node.host; |
1888 | 1888 |
1889 // 2. | 1889 // 2. |
1890 var eventParents = scope.eventParentsTable.get(node); | 1890 var eventParents = scope.eventParentsTable.get(node); |
1891 if (eventParents) { | 1891 if (eventParents) { |
1892 // Copy over the remaining event parents for next iteration. | 1892 // Copy over the remaining event parents for next iteration. |
1893 for (var i = 1; i < eventParents.length; i++) { | 1893 for (var i = 1; i < eventParents.length; i++) { |
1894 ancestors[i - 1] = eventParents[i]; | 1894 ancestors[i - 1] = eventParents[i]; |
1895 } | 1895 } |
1896 return eventParents[0]; | 1896 return eventParents[0]; |
1897 } | 1897 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1973 if (inSameTree(ancestor, target)) // 3.4.4. | 1973 if (inSameTree(ancestor, target)) // 3.4.4. |
1974 return stack[stack.length - 1]; | 1974 return stack[stack.length - 1]; |
1975 | 1975 |
1976 if (isShadowRoot(ancestor)) // 3.4.5. | 1976 if (isShadowRoot(ancestor)) // 3.4.5. |
1977 stack.pop(); | 1977 stack.pop(); |
1978 | 1978 |
1979 last = ancestor; // 3.4.6. | 1979 last = ancestor; // 3.4.6. |
1980 ancestor = calculateParents(ancestor, context, ancestors); // 3.4.7. | 1980 ancestor = calculateParents(ancestor, context, ancestors); // 3.4.7. |
1981 } | 1981 } |
1982 if (isShadowRoot(target)) // 3.5. | 1982 if (isShadowRoot(target)) // 3.5. |
1983 target = scope.getHostForShadowRoot(target); | 1983 target = target.host; |
1984 else | 1984 else |
1985 target = target.parentNode; // 3.6. | 1985 target = target.parentNode; // 3.6. |
1986 } | 1986 } |
1987 } | 1987 } |
1988 | 1988 |
1989 function getInsertionParent(node) { | 1989 function getInsertionParent(node) { |
1990 return scope.insertionParentTable.get(node); | 1990 return scope.insertionParentTable.get(node); |
1991 } | 1991 } |
1992 | 1992 |
1993 function isDistributed(node) { | 1993 function isDistributed(node) { |
1994 return getInsertionParent(node); | 1994 return getInsertionParent(node); |
1995 } | 1995 } |
1996 | 1996 |
1997 function rootOfNode(node) { | 1997 function rootOfNode(node) { |
1998 var p; | 1998 var p; |
1999 while (p = node.parentNode) { | 1999 while (p = node.parentNode) { |
2000 node = p; | 2000 node = p; |
2001 } | 2001 } |
2002 return node; | 2002 return node; |
2003 } | 2003 } |
2004 | 2004 |
2005 function inSameTree(a, b) { | 2005 function inSameTree(a, b) { |
2006 return rootOfNode(a) === rootOfNode(b); | 2006 return rootOfNode(a) === rootOfNode(b); |
2007 } | 2007 } |
2008 | 2008 |
2009 function enclosedBy(a, b) { | 2009 function enclosedBy(a, b) { |
2010 if (a === b) | 2010 if (a === b) |
2011 return true; | 2011 return true; |
2012 if (a instanceof wrappers.ShadowRoot) { | 2012 if (a instanceof wrappers.ShadowRoot) |
2013 var host = scope.getHostForShadowRoot(a); | 2013 return enclosedBy(rootOfNode(a.host), b); |
2014 return enclosedBy(rootOfNode(host), b); | |
2015 } | |
2016 return false; | 2014 return false; |
2017 } | 2015 } |
2018 | 2016 |
2019 var mutationEventsAreSilenced = 0; | 2017 var mutationEventsAreSilenced = 0; |
2020 | 2018 |
2021 function muteMutationEvents() { | 2019 function muteMutationEvents() { |
2022 mutationEventsAreSilenced++; | 2020 mutationEventsAreSilenced++; |
2023 } | 2021 } |
2024 | 2022 |
2025 function unmuteMutationEvents() { | 2023 function unmuteMutationEvents() { |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2427 | 2425 |
2428 [Node, Window].forEach(function(constructor) { | 2426 [Node, Window].forEach(function(constructor) { |
2429 var p = constructor.prototype; | 2427 var p = constructor.prototype; |
2430 methodNames.forEach(function(name) { | 2428 methodNames.forEach(function(name) { |
2431 Object.defineProperty(p, name + '_', {value: p[name]}); | 2429 Object.defineProperty(p, name + '_', {value: p[name]}); |
2432 }); | 2430 }); |
2433 }); | 2431 }); |
2434 | 2432 |
2435 function getTargetToListenAt(wrapper) { | 2433 function getTargetToListenAt(wrapper) { |
2436 if (wrapper instanceof wrappers.ShadowRoot) | 2434 if (wrapper instanceof wrappers.ShadowRoot) |
2437 wrapper = scope.getHostForShadowRoot(wrapper); | 2435 wrapper = wrapper.host; |
2438 return unwrap(wrapper); | 2436 return unwrap(wrapper); |
2439 } | 2437 } |
2440 | 2438 |
2441 EventTarget.prototype = { | 2439 EventTarget.prototype = { |
2442 addEventListener: function(type, fun, capture) { | 2440 addEventListener: function(type, fun, capture) { |
2443 if (!isValidListener(fun)) | 2441 if (!isValidListener(fun)) |
2444 return; | 2442 return; |
2445 | 2443 |
2446 var listener = new Listener(type, fun, capture); | 2444 var listener = new Listener(type, fun, capture); |
2447 var listeners = listenersTable.get(this); | 2445 var listeners = listenersTable.get(this); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2664 node.previousSibling_ = previousNode; | 2662 node.previousSibling_ = previousNode; |
2665 node.nextSibling_ = nextNode; | 2663 node.nextSibling_ = nextNode; |
2666 if (previousNode) | 2664 if (previousNode) |
2667 previousNode.nextSibling_ = node; | 2665 previousNode.nextSibling_ = node; |
2668 if (nextNode) | 2666 if (nextNode) |
2669 nextNode.previousSibling_ = node; | 2667 nextNode.previousSibling_ = node; |
2670 return [node]; | 2668 return [node]; |
2671 } | 2669 } |
2672 | 2670 |
2673 var nodes = []; | 2671 var nodes = []; |
2674 var firstChild; | 2672 for (var child = node.firstChild; child; child = child.nextSibling) { |
2675 while (firstChild = node.firstChild) { | 2673 nodes.push(child); |
2676 node.removeChild(firstChild); | 2674 } |
2677 nodes.push(firstChild); | 2675 |
2678 firstChild.parentNode_ = parentNode; | 2676 for (var i = nodes.length - 1; i >= 0; i--) { |
| 2677 node.removeChild(nodes[i]); |
| 2678 nodes[i].parentNode_ = parentNode; |
2679 } | 2679 } |
2680 | 2680 |
2681 for (var i = 0; i < nodes.length; i++) { | 2681 for (var i = 0; i < nodes.length; i++) { |
2682 nodes[i].previousSibling_ = nodes[i - 1] || previousNode; | 2682 nodes[i].previousSibling_ = nodes[i - 1] || previousNode; |
2683 nodes[i].nextSibling_ = nodes[i + 1] || nextNode; | 2683 nodes[i].nextSibling_ = nodes[i + 1] || nextNode; |
2684 } | 2684 } |
2685 | 2685 |
2686 if (previousNode) | 2686 if (previousNode) |
2687 previousNode.nextSibling_ = nodes[0]; | 2687 previousNode.nextSibling_ = nodes[0]; |
2688 if (nextNode) | 2688 if (nextNode) |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2818 */ | 2818 */ |
2819 this.nextSibling_ = undefined; | 2819 this.nextSibling_ = undefined; |
2820 | 2820 |
2821 /** | 2821 /** |
2822 * @type {Node|undefined} | 2822 * @type {Node|undefined} |
2823 * @private | 2823 * @private |
2824 */ | 2824 */ |
2825 this.previousSibling_ = undefined; | 2825 this.previousSibling_ = undefined; |
2826 }; | 2826 }; |
2827 | 2827 |
| 2828 var OriginalDocumentFragment = window.DocumentFragment; |
2828 var originalAppendChild = OriginalNode.prototype.appendChild; | 2829 var originalAppendChild = OriginalNode.prototype.appendChild; |
2829 var originalInsertBefore = OriginalNode.prototype.insertBefore; | |
2830 var originalReplaceChild = OriginalNode.prototype.replaceChild; | |
2831 var originalRemoveChild = OriginalNode.prototype.removeChild; | |
2832 var originalCompareDocumentPosition = | 2830 var originalCompareDocumentPosition = |
2833 OriginalNode.prototype.compareDocumentPosition; | 2831 OriginalNode.prototype.compareDocumentPosition; |
| 2832 var originalInsertBefore = OriginalNode.prototype.insertBefore; |
| 2833 var originalRemoveChild = OriginalNode.prototype.removeChild; |
| 2834 var originalReplaceChild = OriginalNode.prototype.replaceChild; |
| 2835 |
| 2836 var isIe = /Trident/.test(navigator.userAgent); |
| 2837 |
| 2838 var removeChildOriginalHelper = isIe ? |
| 2839 function(parent, child) { |
| 2840 try { |
| 2841 originalRemoveChild.call(parent, child); |
| 2842 } catch (ex) { |
| 2843 if (!(parent instanceof OriginalDocumentFragment)) |
| 2844 throw ex; |
| 2845 } |
| 2846 } : |
| 2847 function(parent, child) { |
| 2848 originalRemoveChild.call(parent, child); |
| 2849 }; |
2834 | 2850 |
2835 Node.prototype = Object.create(EventTarget.prototype); | 2851 Node.prototype = Object.create(EventTarget.prototype); |
2836 mixin(Node.prototype, { | 2852 mixin(Node.prototype, { |
2837 appendChild: function(childWrapper) { | 2853 appendChild: function(childWrapper) { |
2838 assertIsNodeWrapper(childWrapper); | 2854 assertIsNodeWrapper(childWrapper); |
2839 | 2855 |
2840 var nodes; | 2856 var nodes; |
2841 | 2857 |
2842 if (this.invalidateShadowRenderer() || invalidateParent(childWrapper)) { | 2858 if (this.invalidateShadowRenderer() || invalidateParent(childWrapper)) { |
2843 var previousNode = this.lastChild; | 2859 var previousNode = this.lastChild; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2899 } | 2915 } |
2900 | 2916 |
2901 nodesWereAdded(nodes); | 2917 nodesWereAdded(nodes); |
2902 | 2918 |
2903 return childWrapper; | 2919 return childWrapper; |
2904 }, | 2920 }, |
2905 | 2921 |
2906 removeChild: function(childWrapper) { | 2922 removeChild: function(childWrapper) { |
2907 assertIsNodeWrapper(childWrapper); | 2923 assertIsNodeWrapper(childWrapper); |
2908 if (childWrapper.parentNode !== this) { | 2924 if (childWrapper.parentNode !== this) { |
2909 // TODO(arv): DOMException | 2925 // IE has invalid DOM trees at times. |
2910 throw new Error('NotFoundError'); | 2926 var found = false; |
| 2927 var childNodes = this.childNodes; |
| 2928 for (var ieChild = this.firstChild; ieChild; |
| 2929 ieChild = ieChild.nextSibling) { |
| 2930 if (ieChild === childWrapper) { |
| 2931 found = true; |
| 2932 break; |
| 2933 } |
| 2934 } |
| 2935 if (!found) { |
| 2936 // TODO(arv): DOMException |
| 2937 throw new Error('NotFoundError'); |
| 2938 } |
2911 } | 2939 } |
2912 | 2940 |
2913 var childNode = unwrap(childWrapper); | 2941 var childNode = unwrap(childWrapper); |
2914 if (this.invalidateShadowRenderer()) { | 2942 if (this.invalidateShadowRenderer()) { |
2915 | 2943 |
2916 // We need to remove the real node from the DOM before updating the | 2944 // We need to remove the real node from the DOM before updating the |
2917 // pointers. This is so that that mutation event is dispatched before | 2945 // pointers. This is so that that mutation event is dispatched before |
2918 // the pointers have changed. | 2946 // the pointers have changed. |
2919 var thisFirstChild = this.firstChild; | 2947 var thisFirstChild = this.firstChild; |
2920 var thisLastChild = this.lastChild; | 2948 var thisLastChild = this.lastChild; |
2921 var childWrapperNextSibling = childWrapper.nextSibling; | 2949 var childWrapperNextSibling = childWrapper.nextSibling; |
2922 var childWrapperPreviousSibling = childWrapper.previousSibling; | 2950 var childWrapperPreviousSibling = childWrapper.previousSibling; |
2923 | 2951 |
2924 var parentNode = childNode.parentNode; | 2952 var parentNode = childNode.parentNode; |
2925 if (parentNode) | 2953 if (parentNode) |
2926 originalRemoveChild.call(parentNode, childNode); | 2954 removeChildOriginalHelper(parentNode, childNode); |
2927 | 2955 |
2928 if (thisFirstChild === childWrapper) | 2956 if (thisFirstChild === childWrapper) |
2929 this.firstChild_ = childWrapperNextSibling; | 2957 this.firstChild_ = childWrapperNextSibling; |
2930 if (thisLastChild === childWrapper) | 2958 if (thisLastChild === childWrapper) |
2931 this.lastChild_ = childWrapperPreviousSibling; | 2959 this.lastChild_ = childWrapperPreviousSibling; |
2932 if (childWrapperPreviousSibling) | 2960 if (childWrapperPreviousSibling) |
2933 childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling; | 2961 childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling; |
2934 if (childWrapperNextSibling) { | 2962 if (childWrapperNextSibling) { |
2935 childWrapperNextSibling.previousSibling_ = | 2963 childWrapperNextSibling.previousSibling_ = |
2936 childWrapperPreviousSibling; | 2964 childWrapperPreviousSibling; |
2937 } | 2965 } |
2938 | 2966 |
2939 childWrapper.previousSibling_ = childWrapper.nextSibling_ = | 2967 childWrapper.previousSibling_ = childWrapper.nextSibling_ = |
2940 childWrapper.parentNode_ = undefined; | 2968 childWrapper.parentNode_ = undefined; |
2941 } else { | 2969 } else { |
2942 originalRemoveChild.call(this.impl, childNode); | 2970 removeChildOriginalHelper(this.impl, childNode); |
2943 } | 2971 } |
2944 | 2972 |
2945 return childWrapper; | 2973 return childWrapper; |
2946 }, | 2974 }, |
2947 | 2975 |
2948 replaceChild: function(newChildWrapper, oldChildWrapper) { | 2976 replaceChild: function(newChildWrapper, oldChildWrapper) { |
2949 assertIsNodeWrapper(newChildWrapper); | 2977 assertIsNodeWrapper(newChildWrapper); |
2950 assertIsNodeWrapper(oldChildWrapper); | 2978 assertIsNodeWrapper(oldChildWrapper); |
2951 | 2979 |
2952 if (oldChildWrapper.parentNode !== this) { | 2980 if (oldChildWrapper.parentNode !== this) { |
(...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3719 registerWrapper(OriginalHTMLImageElement, HTMLImageElement, | 3747 registerWrapper(OriginalHTMLImageElement, HTMLImageElement, |
3720 document.createElement('img')); | 3748 document.createElement('img')); |
3721 | 3749 |
3722 function Image(width, height) { | 3750 function Image(width, height) { |
3723 if (!(this instanceof Image)) { | 3751 if (!(this instanceof Image)) { |
3724 throw new TypeError( | 3752 throw new TypeError( |
3725 'DOM object constructor cannot be called as a function.'); | 3753 'DOM object constructor cannot be called as a function.'); |
3726 } | 3754 } |
3727 | 3755 |
3728 var node = unwrap(document.createElement('img')); | 3756 var node = unwrap(document.createElement('img')); |
| 3757 HTMLElement.call(this, node); |
| 3758 rewrap(node, this); |
| 3759 |
3729 if (width !== undefined) | 3760 if (width !== undefined) |
3730 node.width = width; | 3761 node.width = width; |
3731 if (height !== undefined) | 3762 if (height !== undefined) |
3732 node.height = height; | 3763 node.height = height; |
3733 HTMLElement.call(this, node); | |
3734 rewrap(node, this); | |
3735 } | 3764 } |
3736 | 3765 |
3737 Image.prototype = HTMLImageElement.prototype; | 3766 Image.prototype = HTMLImageElement.prototype; |
3738 | 3767 |
3739 scope.wrappers.HTMLImageElement = HTMLImageElement; | 3768 scope.wrappers.HTMLImageElement = HTMLImageElement; |
3740 scope.wrappers.Image = Image; | 3769 scope.wrappers.Image = Image; |
3741 })(this.ShadowDOMPolyfill); | 3770 })(this.ShadowDOMPolyfill); |
3742 | 3771 |
3743 // Copyright 2013 The Polymer Authors. All rights reserved. | 3772 // Copyright 2013 The Polymer Authors. All rights reserved. |
3744 // Use of this source code is goverened by a BSD-style | 3773 // Use of this source code is goverened by a BSD-style |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3851 | 3880 |
3852 scope.wrappers.HTMLTemplateElement = HTMLTemplateElement; | 3881 scope.wrappers.HTMLTemplateElement = HTMLTemplateElement; |
3853 })(this.ShadowDOMPolyfill); | 3882 })(this.ShadowDOMPolyfill); |
3854 // Copyright 2013 The Polymer Authors. All rights reserved. | 3883 // Copyright 2013 The Polymer Authors. All rights reserved. |
3855 // Use of this source code is goverened by a BSD-style | 3884 // Use of this source code is goverened by a BSD-style |
3856 // license that can be found in the LICENSE file. | 3885 // license that can be found in the LICENSE file. |
3857 | 3886 |
3858 (function(scope) { | 3887 (function(scope) { |
3859 'use strict'; | 3888 'use strict'; |
3860 | 3889 |
| 3890 var HTMLElement = scope.wrappers.HTMLElement; |
| 3891 var registerWrapper = scope.registerWrapper; |
| 3892 |
| 3893 var OriginalHTMLMediaElement = window.HTMLMediaElement; |
| 3894 |
| 3895 function HTMLMediaElement(node) { |
| 3896 HTMLElement.call(this, node); |
| 3897 } |
| 3898 HTMLMediaElement.prototype = Object.create(HTMLElement.prototype); |
| 3899 |
| 3900 registerWrapper(OriginalHTMLMediaElement, HTMLMediaElement, |
| 3901 document.createElement('audio')); |
| 3902 |
| 3903 scope.wrappers.HTMLMediaElement = HTMLMediaElement; |
| 3904 })(this.ShadowDOMPolyfill); |
| 3905 |
| 3906 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 3907 // Use of this source code is goverened by a BSD-style |
| 3908 // license that can be found in the LICENSE file. |
| 3909 |
| 3910 (function(scope) { |
| 3911 'use strict'; |
| 3912 |
| 3913 var HTMLMediaElement = scope.wrappers.HTMLMediaElement; |
| 3914 var registerWrapper = scope.registerWrapper; |
| 3915 var unwrap = scope.unwrap; |
| 3916 var rewrap = scope.rewrap; |
| 3917 |
| 3918 var OriginalHTMLAudioElement = window.HTMLAudioElement; |
| 3919 |
| 3920 function HTMLAudioElement(node) { |
| 3921 HTMLMediaElement.call(this, node); |
| 3922 } |
| 3923 HTMLAudioElement.prototype = Object.create(HTMLMediaElement.prototype); |
| 3924 |
| 3925 registerWrapper(OriginalHTMLAudioElement, HTMLAudioElement, |
| 3926 document.createElement('audio')); |
| 3927 |
| 3928 function Audio(src) { |
| 3929 if (!(this instanceof Audio)) { |
| 3930 throw new TypeError( |
| 3931 'DOM object constructor cannot be called as a function.'); |
| 3932 } |
| 3933 |
| 3934 var node = unwrap(document.createElement('audio')); |
| 3935 HTMLMediaElement.call(this, node); |
| 3936 rewrap(node, this); |
| 3937 |
| 3938 node.setAttribute('preload', 'auto'); |
| 3939 if (src !== undefined) |
| 3940 node.setAttribute('src', src); |
| 3941 } |
| 3942 |
| 3943 Audio.prototype = HTMLAudioElement.prototype; |
| 3944 |
| 3945 scope.wrappers.HTMLAudioElement = HTMLAudioElement; |
| 3946 scope.wrappers.Audio = Audio; |
| 3947 })(this.ShadowDOMPolyfill); |
| 3948 |
| 3949 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 3950 // Use of this source code is goverened by a BSD-style |
| 3951 // license that can be found in the LICENSE file. |
| 3952 |
| 3953 (function(scope) { |
| 3954 'use strict'; |
| 3955 |
| 3956 var HTMLElement = scope.wrappers.HTMLElement; |
| 3957 var mixin = scope.mixin; |
| 3958 var registerWrapper = scope.registerWrapper; |
| 3959 var rewrap = scope.rewrap; |
| 3960 var unwrap = scope.unwrap; |
| 3961 var wrap = scope.wrap; |
| 3962 |
| 3963 var OriginalHTMLOptionElement = window.HTMLOptionElement; |
| 3964 |
| 3965 function trimText(s) { |
| 3966 return s.replace(/\s+/g, ' ').trim(); |
| 3967 } |
| 3968 |
| 3969 function HTMLOptionElement(node) { |
| 3970 HTMLElement.call(this, node); |
| 3971 } |
| 3972 HTMLOptionElement.prototype = Object.create(HTMLElement.prototype); |
| 3973 mixin(HTMLOptionElement.prototype, { |
| 3974 get text() { |
| 3975 return trimText(this.textContent); |
| 3976 }, |
| 3977 set text(value) { |
| 3978 this.textContent = trimText(String(value)); |
| 3979 }, |
| 3980 get form() { |
| 3981 return wrap(unwrap(this).form); |
| 3982 } |
| 3983 }); |
| 3984 |
| 3985 registerWrapper(OriginalHTMLOptionElement, HTMLOptionElement, |
| 3986 document.createElement('option')); |
| 3987 |
| 3988 function Option(text, value, defaultSelected, selected) { |
| 3989 if (!(this instanceof Option)) { |
| 3990 throw new TypeError( |
| 3991 'DOM object constructor cannot be called as a function.'); |
| 3992 } |
| 3993 |
| 3994 var node = unwrap(document.createElement('option')); |
| 3995 HTMLElement.call(this, node); |
| 3996 rewrap(node, this); |
| 3997 |
| 3998 if (text !== undefined) |
| 3999 node.text = text; |
| 4000 if (value !== undefined) |
| 4001 node.setAttribute('value', value); |
| 4002 if (defaultSelected === true) |
| 4003 node.setAttribute('selected', ''); |
| 4004 node.selected = selected === true; |
| 4005 } |
| 4006 |
| 4007 Option.prototype = HTMLOptionElement.prototype; |
| 4008 |
| 4009 scope.wrappers.HTMLOptionElement = HTMLOptionElement; |
| 4010 scope.wrappers.Option = Option; |
| 4011 })(this.ShadowDOMPolyfill); |
| 4012 |
| 4013 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 4014 // Use of this source code is goverened by a BSD-style |
| 4015 // license that can be found in the LICENSE file. |
| 4016 |
| 4017 (function(scope) { |
| 4018 'use strict'; |
| 4019 |
3861 var HTMLContentElement = scope.wrappers.HTMLContentElement; | 4020 var HTMLContentElement = scope.wrappers.HTMLContentElement; |
3862 var HTMLElement = scope.wrappers.HTMLElement; | 4021 var HTMLElement = scope.wrappers.HTMLElement; |
3863 var HTMLShadowElement = scope.wrappers.HTMLShadowElement; | 4022 var HTMLShadowElement = scope.wrappers.HTMLShadowElement; |
3864 var HTMLTemplateElement = scope.wrappers.HTMLTemplateElement; | 4023 var HTMLTemplateElement = scope.wrappers.HTMLTemplateElement; |
3865 var mixin = scope.mixin; | 4024 var mixin = scope.mixin; |
3866 var registerWrapper = scope.registerWrapper; | 4025 var registerWrapper = scope.registerWrapper; |
3867 | 4026 |
3868 var OriginalHTMLUnknownElement = window.HTMLUnknownElement; | 4027 var OriginalHTMLUnknownElement = window.HTMLUnknownElement; |
3869 | 4028 |
3870 function HTMLUnknownElement(node) { | 4029 function HTMLUnknownElement(node) { |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4030 }, | 4189 }, |
4031 set innerHTML(value) { | 4190 set innerHTML(value) { |
4032 setInnerHTML(this, value); | 4191 setInnerHTML(this, value); |
4033 this.invalidateShadowRenderer(); | 4192 this.invalidateShadowRenderer(); |
4034 }, | 4193 }, |
4035 | 4194 |
4036 get olderShadowRoot() { | 4195 get olderShadowRoot() { |
4037 return nextOlderShadowTreeTable.get(this) || null; | 4196 return nextOlderShadowTreeTable.get(this) || null; |
4038 }, | 4197 }, |
4039 | 4198 |
| 4199 get host() { |
| 4200 return shadowHostTable.get(this) || null; |
| 4201 }, |
| 4202 |
4040 invalidateShadowRenderer: function() { | 4203 invalidateShadowRenderer: function() { |
4041 return shadowHostTable.get(this).invalidateShadowRenderer(); | 4204 return shadowHostTable.get(this).invalidateShadowRenderer(); |
4042 }, | 4205 }, |
4043 | 4206 |
4044 elementFromPoint: function(x, y) { | 4207 elementFromPoint: function(x, y) { |
4045 return elementFromPoint(this, this.ownerDocument, x, y); | 4208 return elementFromPoint(this, this.ownerDocument, x, y); |
4046 }, | 4209 }, |
4047 | 4210 |
4048 getElementById: function(id) { | 4211 getElementById: function(id) { |
4049 return this.querySelector('#' + id); | 4212 return this.querySelector('#' + id); |
4050 } | 4213 } |
4051 }); | 4214 }); |
4052 | 4215 |
4053 scope.wrappers.ShadowRoot = ShadowRoot; | 4216 scope.wrappers.ShadowRoot = ShadowRoot; |
4054 scope.getHostForShadowRoot = function(node) { | |
4055 return shadowHostTable.get(node); | |
4056 }; | |
4057 })(this.ShadowDOMPolyfill); | 4217 })(this.ShadowDOMPolyfill); |
4058 // Copyright 2013 The Polymer Authors. All rights reserved. | 4218 // Copyright 2013 The Polymer Authors. All rights reserved. |
4059 // Use of this source code is governed by a BSD-style | 4219 // Use of this source code is governed by a BSD-style |
4060 // license that can be found in the LICENSE file. | 4220 // license that can be found in the LICENSE file. |
4061 | 4221 |
4062 (function(scope) { | 4222 (function(scope) { |
4063 'use strict'; | 4223 'use strict'; |
4064 | 4224 |
4065 var Element = scope.wrappers.Element; | 4225 var Element = scope.wrappers.Element; |
4066 var HTMLContentElement = scope.wrappers.HTMLContentElement; | 4226 var HTMLContentElement = scope.wrappers.HTMLContentElement; |
4067 var HTMLShadowElement = scope.wrappers.HTMLShadowElement; | 4227 var HTMLShadowElement = scope.wrappers.HTMLShadowElement; |
4068 var Node = scope.wrappers.Node; | 4228 var Node = scope.wrappers.Node; |
4069 var ShadowRoot = scope.wrappers.ShadowRoot; | 4229 var ShadowRoot = scope.wrappers.ShadowRoot; |
4070 var assert = scope.assert; | 4230 var assert = scope.assert; |
4071 var getHostForShadowRoot = scope.getHostForShadowRoot; | |
4072 var mixin = scope.mixin; | 4231 var mixin = scope.mixin; |
4073 var muteMutationEvents = scope.muteMutationEvents; | 4232 var muteMutationEvents = scope.muteMutationEvents; |
4074 var oneOf = scope.oneOf; | 4233 var oneOf = scope.oneOf; |
4075 var unmuteMutationEvents = scope.unmuteMutationEvents; | 4234 var unmuteMutationEvents = scope.unmuteMutationEvents; |
4076 var unwrap = scope.unwrap; | 4235 var unwrap = scope.unwrap; |
4077 var wrap = scope.wrap; | 4236 var wrap = scope.wrap; |
4078 | 4237 |
4079 /** | 4238 /** |
4080 * Updates the fields of a wrapper to a snapshot of the logical DOM as needed. | 4239 * Updates the fields of a wrapper to a snapshot of the logical DOM as needed. |
4081 * Up means parentNode | 4240 * Up means parentNode |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4303 | 4462 |
4304 function getShadowRootAncestor(node) { | 4463 function getShadowRootAncestor(node) { |
4305 for (; node; node = node.parentNode) { | 4464 for (; node; node = node.parentNode) { |
4306 if (node instanceof ShadowRoot) | 4465 if (node instanceof ShadowRoot) |
4307 return node; | 4466 return node; |
4308 } | 4467 } |
4309 return null; | 4468 return null; |
4310 } | 4469 } |
4311 | 4470 |
4312 function getRendererForShadowRoot(shadowRoot) { | 4471 function getRendererForShadowRoot(shadowRoot) { |
4313 return getRendererForHost(getHostForShadowRoot(shadowRoot)); | 4472 return getRendererForHost(shadowRoot.host); |
4314 } | 4473 } |
4315 | 4474 |
4316 var spliceDiff = new ArraySplice(); | 4475 var spliceDiff = new ArraySplice(); |
4317 spliceDiff.equals = function(renderNode, rawNode) { | 4476 spliceDiff.equals = function(renderNode, rawNode) { |
4318 return unwrap(renderNode.node) === rawNode; | 4477 return unwrap(renderNode.node) === rawNode; |
4319 }; | 4478 }; |
4320 | 4479 |
4321 /** | 4480 /** |
4322 * RenderNode is used as an in memory "render tree". When we render the | 4481 * RenderNode is used as an in memory "render tree". When we render the |
4323 * composed tree we create a tree of RenderNodes, then we diff this against | 4482 * composed tree we create a tree of RenderNodes, then we diff this against |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4732 var wrap = scope.wrap; | 4891 var wrap = scope.wrap; |
4733 | 4892 |
4734 var elementsWithFormProperty = [ | 4893 var elementsWithFormProperty = [ |
4735 'HTMLButtonElement', | 4894 'HTMLButtonElement', |
4736 'HTMLFieldSetElement', | 4895 'HTMLFieldSetElement', |
4737 'HTMLInputElement', | 4896 'HTMLInputElement', |
4738 'HTMLKeygenElement', | 4897 'HTMLKeygenElement', |
4739 'HTMLLabelElement', | 4898 'HTMLLabelElement', |
4740 'HTMLLegendElement', | 4899 'HTMLLegendElement', |
4741 'HTMLObjectElement', | 4900 'HTMLObjectElement', |
4742 'HTMLOptionElement', | 4901 // HTMLOptionElement is handled in HTMLOptionElement.js |
4743 'HTMLOutputElement', | 4902 'HTMLOutputElement', |
4744 'HTMLSelectElement', | 4903 'HTMLSelectElement', |
4745 'HTMLTextAreaElement', | 4904 'HTMLTextAreaElement', |
4746 ]; | 4905 ]; |
4747 | 4906 |
4748 function createWrapperConstructor(name) { | 4907 function createWrapperConstructor(name) { |
4749 if (!window[name]) | 4908 if (!window[name]) |
4750 return; | 4909 return; |
4751 | 4910 |
4752 // Ensure we are not overriding an already existing constructor. | 4911 // Ensure we are not overriding an already existing constructor. |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4917 'attributeChangedCallback', | 5076 'attributeChangedCallback', |
4918 ].forEach(function(name) { | 5077 ].forEach(function(name) { |
4919 var f = prototype[name]; | 5078 var f = prototype[name]; |
4920 if (!f) | 5079 if (!f) |
4921 return; | 5080 return; |
4922 newPrototype[name] = function() { | 5081 newPrototype[name] = function() { |
4923 f.apply(wrap(this), arguments); | 5082 f.apply(wrap(this), arguments); |
4924 }; | 5083 }; |
4925 }); | 5084 }); |
4926 | 5085 |
4927 var nativeConstructor = originalRegister.call(unwrap(this), tagName, | 5086 var p = {prototype: newPrototype}; |
4928 object.extends ? {prototype: newPrototype, extends: object.extends} : | 5087 if (object.extends) |
4929 {prototype: newPrototype}); | 5088 p.extends = object.extends; |
| 5089 var nativeConstructor = originalRegister.call(unwrap(this), tagName, p); |
4930 | 5090 |
4931 function GeneratedWrapper(node) { | 5091 function GeneratedWrapper(node) { |
4932 if (!node) | 5092 if (!node) { |
4933 return document.createElement(tagName); | 5093 if (object.extends) { |
| 5094 return document.createElement(object.extends, tagName); |
| 5095 } else { |
| 5096 return document.createElement(tagName); |
| 5097 } |
| 5098 } |
4934 this.impl = node; | 5099 this.impl = node; |
4935 } | 5100 } |
4936 GeneratedWrapper.prototype = prototype; | 5101 GeneratedWrapper.prototype = prototype; |
4937 GeneratedWrapper.prototype.constructor = GeneratedWrapper; | 5102 GeneratedWrapper.prototype.constructor = GeneratedWrapper; |
4938 | 5103 |
4939 scope.constructorTable.set(newPrototype, GeneratedWrapper); | 5104 scope.constructorTable.set(newPrototype, GeneratedWrapper); |
4940 scope.nativePrototypeTable.set(prototype, newPrototype); | 5105 scope.nativePrototypeTable.set(prototype, newPrototype); |
4941 | 5106 |
4942 return GeneratedWrapper; | 5107 return GeneratedWrapper; |
4943 }; | 5108 }; |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5297 'use strict'; | 5462 'use strict'; |
5298 | 5463 |
5299 var isWrapperFor = scope.isWrapperFor; | 5464 var isWrapperFor = scope.isWrapperFor; |
5300 | 5465 |
5301 // This is a list of the elements we currently override the global constructor | 5466 // This is a list of the elements we currently override the global constructor |
5302 // for. | 5467 // for. |
5303 var elements = { | 5468 var elements = { |
5304 'a': 'HTMLAnchorElement', | 5469 'a': 'HTMLAnchorElement', |
5305 'applet': 'HTMLAppletElement', | 5470 'applet': 'HTMLAppletElement', |
5306 'area': 'HTMLAreaElement', | 5471 'area': 'HTMLAreaElement', |
5307 'audio': 'HTMLAudioElement', | |
5308 'br': 'HTMLBRElement', | 5472 'br': 'HTMLBRElement', |
5309 'base': 'HTMLBaseElement', | 5473 'base': 'HTMLBaseElement', |
5310 'body': 'HTMLBodyElement', | 5474 'body': 'HTMLBodyElement', |
5311 'button': 'HTMLButtonElement', | 5475 'button': 'HTMLButtonElement', |
5312 // 'command': 'HTMLCommandElement', // Not fully implemented in Gecko. | 5476 // 'command': 'HTMLCommandElement', // Not fully implemented in Gecko. |
5313 'dl': 'HTMLDListElement', | 5477 'dl': 'HTMLDListElement', |
5314 'datalist': 'HTMLDataListElement', | 5478 'datalist': 'HTMLDataListElement', |
5315 'data': 'HTMLDataElement', | 5479 'data': 'HTMLDataElement', |
5316 'dir': 'HTMLDirectoryElement', | 5480 'dir': 'HTMLDirectoryElement', |
5317 'div': 'HTMLDivElement', | 5481 'div': 'HTMLDivElement', |
5318 'embed': 'HTMLEmbedElement', | 5482 'embed': 'HTMLEmbedElement', |
5319 'fieldset': 'HTMLFieldSetElement', | 5483 'fieldset': 'HTMLFieldSetElement', |
5320 'font': 'HTMLFontElement', | 5484 'font': 'HTMLFontElement', |
5321 'form': 'HTMLFormElement', | 5485 'form': 'HTMLFormElement', |
5322 'frame': 'HTMLFrameElement', | 5486 'frame': 'HTMLFrameElement', |
5323 'frameset': 'HTMLFrameSetElement', | 5487 'frameset': 'HTMLFrameSetElement', |
5324 'hr': 'HTMLHRElement', | 5488 'hr': 'HTMLHRElement', |
5325 'head': 'HTMLHeadElement', | 5489 'head': 'HTMLHeadElement', |
5326 'h1': 'HTMLHeadingElement', | 5490 'h1': 'HTMLHeadingElement', |
5327 'html': 'HTMLHtmlElement', | 5491 'html': 'HTMLHtmlElement', |
5328 'iframe': 'HTMLIFrameElement', | 5492 'iframe': 'HTMLIFrameElement', |
5329 'input': 'HTMLInputElement', | 5493 'input': 'HTMLInputElement', |
5330 'li': 'HTMLLIElement', | 5494 'li': 'HTMLLIElement', |
5331 'label': 'HTMLLabelElement', | 5495 'label': 'HTMLLabelElement', |
5332 'legend': 'HTMLLegendElement', | 5496 'legend': 'HTMLLegendElement', |
5333 'link': 'HTMLLinkElement', | 5497 'link': 'HTMLLinkElement', |
5334 'map': 'HTMLMapElement', | 5498 'map': 'HTMLMapElement', |
5335 'marquee': 'HTMLMarqueeElement', | 5499 'marquee': 'HTMLMarqueeElement', |
5336 // 'media', Covered by audio and video | |
5337 'menu': 'HTMLMenuElement', | 5500 'menu': 'HTMLMenuElement', |
5338 'menuitem': 'HTMLMenuItemElement', | 5501 'menuitem': 'HTMLMenuItemElement', |
5339 'meta': 'HTMLMetaElement', | 5502 'meta': 'HTMLMetaElement', |
5340 'meter': 'HTMLMeterElement', | 5503 'meter': 'HTMLMeterElement', |
5341 'del': 'HTMLModElement', | 5504 'del': 'HTMLModElement', |
5342 'ol': 'HTMLOListElement', | 5505 'ol': 'HTMLOListElement', |
5343 'object': 'HTMLObjectElement', | 5506 'object': 'HTMLObjectElement', |
5344 'optgroup': 'HTMLOptGroupElement', | 5507 'optgroup': 'HTMLOptGroupElement', |
5345 'option': 'HTMLOptionElement', | 5508 'option': 'HTMLOptionElement', |
5346 'output': 'HTMLOutputElement', | 5509 'output': 'HTMLOutputElement', |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5470 | 5633 |
5471 /* | 5634 /* |
5472 * Copyright 2012 The Polymer Authors. All rights reserved. | 5635 * Copyright 2012 The Polymer Authors. All rights reserved. |
5473 * Use of this source code is governed by a BSD-style | 5636 * Use of this source code is governed by a BSD-style |
5474 * license that can be found in the LICENSE file. | 5637 * license that can be found in the LICENSE file. |
5475 */ | 5638 */ |
5476 | 5639 |
5477 /* | 5640 /* |
5478 This is a limited shim for ShadowDOM css styling. | 5641 This is a limited shim for ShadowDOM css styling. |
5479 https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#style
s | 5642 https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#style
s |
5480 | 5643 |
5481 The intention here is to support only the styling features which can be | 5644 The intention here is to support only the styling features which can be |
5482 relatively simply implemented. The goal is to allow users to avoid the | 5645 relatively simply implemented. The goal is to allow users to avoid the |
5483 most obvious pitfalls and do so without compromising performance significantly
. | 5646 most obvious pitfalls and do so without compromising performance significantly
. |
5484 For ShadowDOM styling that's not covered here, a set of best practices | 5647 For ShadowDOM styling that's not covered here, a set of best practices |
5485 can be provided that should allow users to accomplish more complex styling. | 5648 can be provided that should allow users to accomplish more complex styling. |
5486 | 5649 |
5487 The following is a list of specific ShadowDOM styling features and a brief | 5650 The following is a list of specific ShadowDOM styling features and a brief |
5488 discussion of the approach used to shim. | 5651 discussion of the approach used to shim. |
5489 | 5652 |
5490 Shimmed features: | 5653 Shimmed features: |
5491 | 5654 |
5492 * @host: ShadowDOM allows styling of the shadowRoot's host element using the | 5655 * @host: ShadowDOM allows styling of the shadowRoot's host element using the |
5493 @host rule. To shim this feature, the @host styles are reformatted and | 5656 @host rule. To shim this feature, the @host styles are reformatted and |
5494 prefixed with a given scope name and promoted to a document level stylesheet. | 5657 prefixed with a given scope name and promoted to a document level stylesheet. |
5495 For example, given a scope name of .foo, a rule like this: | 5658 For example, given a scope name of .foo, a rule like this: |
5496 | 5659 |
5497 @host { | 5660 @host { |
5498 * { | 5661 * { |
5499 background: red; | 5662 background: red; |
5500 } | 5663 } |
5501 } | 5664 } |
5502 | 5665 |
5503 becomes: | 5666 becomes: |
5504 | 5667 |
5505 .foo { | 5668 .foo { |
5506 background: red; | 5669 background: red; |
5507 } | 5670 } |
5508 | 5671 |
5509 * encapsultion: Styles defined within ShadowDOM, apply only to | 5672 * encapsultion: Styles defined within ShadowDOM, apply only to |
5510 dom inside the ShadowDOM. Polymer uses one of two techniques to imlement | 5673 dom inside the ShadowDOM. Polymer uses one of two techniques to imlement |
5511 this feature. | 5674 this feature. |
5512 | 5675 |
5513 By default, rules are prefixed with the host element tag name | 5676 By default, rules are prefixed with the host element tag name |
5514 as a descendant selector. This ensures styling does not leak out of the 'top' | 5677 as a descendant selector. This ensures styling does not leak out of the 'top' |
5515 of the element's ShadowDOM. For example, | 5678 of the element's ShadowDOM. For example, |
5516 | 5679 |
5517 div { | 5680 div { |
5518 font-weight: bold; | 5681 font-weight: bold; |
5519 } | 5682 } |
5520 | 5683 |
5521 becomes: | 5684 becomes: |
5522 | 5685 |
5523 x-foo div { | 5686 x-foo div { |
5524 font-weight: bold; | 5687 font-weight: bold; |
5525 } | 5688 } |
5526 | 5689 |
5527 becomes: | 5690 becomes: |
5528 | 5691 |
5529 | 5692 |
5530 Alternatively, if Platform.ShadowCSS.strictStyling is set to true then | 5693 Alternatively, if Platform.ShadowCSS.strictStyling is set to true then |
5531 selectors are scoped by adding an attribute selector suffix to each | 5694 selectors are scoped by adding an attribute selector suffix to each |
5532 simple selector that contains the host element tag name. Each element | 5695 simple selector that contains the host element tag name. Each element |
5533 in the element's ShadowDOM template is also given the scope attribute. | 5696 in the element's ShadowDOM template is also given the scope attribute. |
5534 Thus, these rules match only elements that have the scope attribute. | 5697 Thus, these rules match only elements that have the scope attribute. |
5535 For example, given a scope name of x-foo, a rule like this: | 5698 For example, given a scope name of x-foo, a rule like this: |
5536 | 5699 |
5537 div { | 5700 div { |
5538 font-weight: bold; | 5701 font-weight: bold; |
5539 } | 5702 } |
5540 | 5703 |
5541 becomes: | 5704 becomes: |
5542 | 5705 |
5543 div[x-foo] { | 5706 div[x-foo] { |
5544 font-weight: bold; | 5707 font-weight: bold; |
5545 } | 5708 } |
5546 | 5709 |
5547 Note that elements that are dynamically added to a scope must have the scope | 5710 Note that elements that are dynamically added to a scope must have the scope |
5548 selector added to them manually. | 5711 selector added to them manually. |
5549 | 5712 |
5550 * ::pseudo: These rules are converted to rules that take advantage of the | 5713 * ::pseudo: These rules are converted to rules that take advantage of the |
5551 pseudo attribute. For example, a shadowRoot like this inside an x-foo | 5714 pseudo attribute. For example, a shadowRoot like this inside an x-foo |
5552 | 5715 |
(...skipping 11 matching lines...) Expand all Loading... |
5564 part attribute. For example, a shadowRoot like this inside an x-foo | 5727 part attribute. For example, a shadowRoot like this inside an x-foo |
5565 | 5728 |
5566 <div part="special">Special</div> | 5729 <div part="special">Special</div> |
5567 | 5730 |
5568 with a rule like this: | 5731 with a rule like this: |
5569 | 5732 |
5570 x-foo::part(special) { ... } | 5733 x-foo::part(special) { ... } |
5571 | 5734 |
5572 becomes: | 5735 becomes: |
5573 | 5736 |
5574 x-foo [part=special] { ... } | 5737 x-foo [part=special] { ... } |
5575 | 5738 |
5576 Unaddressed ShadowDOM styling features: | 5739 Unaddressed ShadowDOM styling features: |
5577 | 5740 |
5578 * upper/lower bound encapsulation: Styles which are defined outside a | 5741 * upper/lower bound encapsulation: Styles which are defined outside a |
5579 shadowRoot should not cross the ShadowDOM boundary and should not apply | 5742 shadowRoot should not cross the ShadowDOM boundary and should not apply |
5580 inside a shadowRoot. | 5743 inside a shadowRoot. |
5581 | 5744 |
5582 This styling behavior is not emulated. Some possible ways to do this that | 5745 This styling behavior is not emulated. Some possible ways to do this that |
5583 were rejected due to complexity and/or performance concerns include: (1) reset | 5746 were rejected due to complexity and/or performance concerns include: (1) reset |
5584 every possible property for every possible selector for a given scope name; | 5747 every possible property for every possible selector for a given scope name; |
5585 (2) re-implement css in javascript. | 5748 (2) re-implement css in javascript. |
5586 | 5749 |
5587 As an alternative, users should make sure to use selectors | 5750 As an alternative, users should make sure to use selectors |
5588 specific to the scope in which they are working. | 5751 specific to the scope in which they are working. |
5589 | 5752 |
5590 * ::distributed: This behavior is not emulated. It's often not necessary | 5753 * ::distributed: This behavior is not emulated. It's often not necessary |
5591 to style the contents of a specific insertion point and instead, descendants | 5754 to style the contents of a specific insertion point and instead, descendants |
5592 of the host element can be styled selectively. Users can also create an | 5755 of the host element can be styled selectively. Users can also create an |
5593 extra node around an insertion point and style that node's contents | 5756 extra node around an insertion point and style that node's contents |
5594 via descendent selectors. For example, with a shadowRoot like this: | 5757 via descendent selectors. For example, with a shadowRoot like this: |
5595 | 5758 |
5596 <style> | 5759 <style> |
5597 content::-webkit-distributed(div) { | 5760 content::-webkit-distributed(div) { |
5598 background: red; | 5761 background: red; |
5599 } | 5762 } |
5600 </style> | 5763 </style> |
5601 <content></content> | 5764 <content></content> |
5602 | 5765 |
5603 could become: | 5766 could become: |
5604 | 5767 |
5605 <style> | 5768 <style> |
5606 / *@polyfill .content-container div * / | 5769 / *@polyfill .content-container div * / |
5607 content::-webkit-distributed(div) { | 5770 content::-webkit-distributed(div) { |
5608 background: red; | 5771 background: red; |
5609 } | 5772 } |
5610 </style> | 5773 </style> |
5611 <div class="content-container"> | 5774 <div class="content-container"> |
5612 <content></content> | 5775 <content></content> |
5613 </div> | 5776 </div> |
5614 | 5777 |
5615 Note the use of @polyfill in the comment above a ShadowDOM specific style | 5778 Note the use of @polyfill in the comment above a ShadowDOM specific style |
5616 declaration. This is a directive to the styling shim to use the selector | 5779 declaration. This is a directive to the styling shim to use the selector |
5617 in comments in lieu of the next selector when running under polyfill. | 5780 in comments in lieu of the next selector when running under polyfill. |
5618 */ | 5781 */ |
5619 (function(scope) { | 5782 (function(scope) { |
5620 | 5783 |
5621 var ShadowCSS = { | 5784 var ShadowCSS = { |
5622 strictStyling: false, | 5785 strictStyling: false, |
5623 registry: {}, | 5786 registry: {}, |
5624 // Shim styles for a given root associated with a name and extendsName | 5787 // Shim styles for a given root associated with a name and extendsName |
5625 // 1. cache root styles by name | 5788 // 1. cache root styles by name |
5626 // 2. optionally tag root nodes with scope name | 5789 // 2. optionally tag root nodes with scope name |
(...skipping 15 matching lines...) Expand all Loading... |
5642 var cssText = this.stylesToShimmedCssText(def.scopeStyles, name, | 5805 var cssText = this.stylesToShimmedCssText(def.scopeStyles, name, |
5643 typeExtension); | 5806 typeExtension); |
5644 // note: we only need to do rootStyles since these are unscoped. | 5807 // note: we only need to do rootStyles since these are unscoped. |
5645 cssText += this.extractPolyfillUnscopedRules(def.rootStyles); | 5808 cssText += this.extractPolyfillUnscopedRules(def.rootStyles); |
5646 // provide shimmedStyle for user extensibility | 5809 // provide shimmedStyle for user extensibility |
5647 def.shimmedStyle = cssTextToStyle(cssText); | 5810 def.shimmedStyle = cssTextToStyle(cssText); |
5648 if (root) { | 5811 if (root) { |
5649 root.shimmedStyle = def.shimmedStyle; | 5812 root.shimmedStyle = def.shimmedStyle; |
5650 } | 5813 } |
5651 // remove existing style elements | 5814 // remove existing style elements |
5652 for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]); | 5815 for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]); |
5653 i++) { | 5816 i++) { |
5654 s.parentNode.removeChild(s); | 5817 s.parentNode.removeChild(s); |
5655 } | 5818 } |
5656 // add style to document | 5819 // add style to document |
5657 addCssToDocument(cssText); | 5820 addCssToDocument(cssText); |
5658 }, | 5821 }, |
5659 registerDefinition: function(root, name, extendsName) { | 5822 registerDefinition: function(root, name, extendsName) { |
5660 var def = this.registry[name] = { | 5823 var def = this.registry[name] = { |
5661 root: root, | 5824 root: root, |
5662 name: name, | 5825 name: name, |
(...skipping 23 matching lines...) Expand all Loading... |
5686 Array.prototype.forEach.call(root.querySelectorAll('template'), | 5849 Array.prototype.forEach.call(root.querySelectorAll('template'), |
5687 function(template) { | 5850 function(template) { |
5688 this.applyScopeToContent(template.content, name); | 5851 this.applyScopeToContent(template.content, name); |
5689 }, | 5852 }, |
5690 this); | 5853 this); |
5691 } | 5854 } |
5692 }, | 5855 }, |
5693 /* | 5856 /* |
5694 * Process styles to convert native ShadowDOM rules that will trip | 5857 * Process styles to convert native ShadowDOM rules that will trip |
5695 * up the css parser; we rely on decorating the stylesheet with comments. | 5858 * up the css parser; we rely on decorating the stylesheet with comments. |
5696 * | 5859 * |
5697 * For example, we convert this rule: | 5860 * For example, we convert this rule: |
5698 * | 5861 * |
5699 * (comment start) @polyfill :host menu-item (comment end) | 5862 * (comment start) @polyfill :host menu-item (comment end) |
5700 * shadow::-webkit-distributed(menu-item) { | 5863 * shadow::-webkit-distributed(menu-item) { |
5701 * | 5864 * |
5702 * to this: | 5865 * to this: |
5703 * | 5866 * |
5704 * scopeName menu-item { | 5867 * scopeName menu-item { |
5705 * | 5868 * |
5706 **/ | 5869 **/ |
5707 insertPolyfillDirectives: function(styles) { | 5870 insertPolyfillDirectives: function(styles) { |
5708 if (styles) { | 5871 if (styles) { |
5709 Array.prototype.forEach.call(styles, function(s) { | 5872 Array.prototype.forEach.call(styles, function(s) { |
5710 s.textContent = this.insertPolyfillDirectivesInCssText(s.textContent); | 5873 s.textContent = this.insertPolyfillDirectivesInCssText(s.textContent); |
5711 }, this); | 5874 }, this); |
5712 } | 5875 } |
5713 }, | 5876 }, |
5714 insertPolyfillDirectivesInCssText: function(cssText) { | 5877 insertPolyfillDirectivesInCssText: function(cssText) { |
5715 return cssText.replace(cssPolyfillCommentRe, function(match, p1) { | 5878 return cssText.replace(cssPolyfillCommentRe, function(match, p1) { |
5716 // remove end comment delimiter and add block start | 5879 // remove end comment delimiter and add block start |
5717 return p1.slice(0, -2) + '{'; | 5880 return p1.slice(0, -2) + '{'; |
5718 }); | 5881 }); |
5719 }, | 5882 }, |
5720 /* | 5883 /* |
5721 * Process styles to add rules which will only apply under the polyfill | 5884 * Process styles to add rules which will only apply under the polyfill |
5722 * | 5885 * |
5723 * For example, we convert this rule: | 5886 * For example, we convert this rule: |
5724 * | 5887 * |
5725 * (comment start) @polyfill-rule :host menu-item { | 5888 * (comment start) @polyfill-rule :host menu-item { |
5726 * ... } (comment end) | 5889 * ... } (comment end) |
5727 * | 5890 * |
5728 * to this: | 5891 * to this: |
5729 * | 5892 * |
5730 * scopeName menu-item {...} | 5893 * scopeName menu-item {...} |
5731 * | 5894 * |
5732 **/ | 5895 **/ |
5733 insertPolyfillRules: function(styles) { | 5896 insertPolyfillRules: function(styles) { |
5734 if (styles) { | 5897 if (styles) { |
5735 Array.prototype.forEach.call(styles, function(s) { | 5898 Array.prototype.forEach.call(styles, function(s) { |
5736 s.textContent = this.insertPolyfillRulesInCssText(s.textContent); | 5899 s.textContent = this.insertPolyfillRulesInCssText(s.textContent); |
5737 }, this); | 5900 }, this); |
5738 } | 5901 } |
5739 }, | 5902 }, |
5740 insertPolyfillRulesInCssText: function(cssText) { | 5903 insertPolyfillRulesInCssText: function(cssText) { |
5741 return cssText.replace(cssPolyfillRuleCommentRe, function(match, p1) { | 5904 return cssText.replace(cssPolyfillRuleCommentRe, function(match, p1) { |
5742 // remove end comment delimiter | 5905 // remove end comment delimiter |
5743 return p1.slice(0, -1); | 5906 return p1.slice(0, -1); |
5744 }); | 5907 }); |
5745 }, | 5908 }, |
5746 /* | 5909 /* |
5747 * Process styles to add rules which will only apply under the polyfill | 5910 * Process styles to add rules which will only apply under the polyfill |
5748 * and do not process via CSSOM. (CSSOM is destructive to rules on rare | 5911 * and do not process via CSSOM. (CSSOM is destructive to rules on rare |
5749 * occasions, e.g. -webkit-calc on Safari.) | 5912 * occasions, e.g. -webkit-calc on Safari.) |
5750 * For example, we convert this rule: | 5913 * For example, we convert this rule: |
5751 * | 5914 * |
5752 * (comment start) @polyfill-unscoped-rule menu-item { | 5915 * (comment start) @polyfill-unscoped-rule menu-item { |
5753 * ... } (comment end) | 5916 * ... } (comment end) |
5754 * | 5917 * |
5755 * to this: | 5918 * to this: |
5756 * | 5919 * |
5757 * menu-item {...} | 5920 * menu-item {...} |
5758 * | 5921 * |
5759 **/ | 5922 **/ |
5760 extractPolyfillUnscopedRules: function(styles) { | 5923 extractPolyfillUnscopedRules: function(styles) { |
5761 var cssText = ''; | 5924 var cssText = ''; |
5762 if (styles) { | 5925 if (styles) { |
5763 Array.prototype.forEach.call(styles, function(s) { | 5926 Array.prototype.forEach.call(styles, function(s) { |
5764 cssText += this.extractPolyfillUnscopedRulesFromCssText( | 5927 cssText += this.extractPolyfillUnscopedRulesFromCssText( |
5765 s.textContent) + '\n\n'; | 5928 s.textContent) + '\n\n'; |
5766 }, this); | 5929 }, this); |
(...skipping 18 matching lines...) Expand all Loading... |
5785 if (styles) { | 5948 if (styles) { |
5786 return this.convertAtHostStyles(styles, name, typeExtension); | 5949 return this.convertAtHostStyles(styles, name, typeExtension); |
5787 } | 5950 } |
5788 }, | 5951 }, |
5789 convertAtHostStyles: function(styles, name, typeExtension) { | 5952 convertAtHostStyles: function(styles, name, typeExtension) { |
5790 var cssText = stylesToCssText(styles), self = this; | 5953 var cssText = stylesToCssText(styles), self = this; |
5791 cssText = cssText.replace(hostRuleRe, function(m, p1) { | 5954 cssText = cssText.replace(hostRuleRe, function(m, p1) { |
5792 return self.scopeHostCss(p1, name, typeExtension); | 5955 return self.scopeHostCss(p1, name, typeExtension); |
5793 }); | 5956 }); |
5794 cssText = rulesToCss(this.findAtHostRules(cssToRules(cssText), | 5957 cssText = rulesToCss(this.findAtHostRules(cssToRules(cssText), |
5795 new RegExp('^' + name + selectorReSuffix, 'm'))); | 5958 this.makeScopeMatcher(name, typeExtension))); |
5796 return cssText; | 5959 return cssText; |
5797 }, | 5960 }, |
5798 scopeHostCss: function(cssText, name, typeExtension) { | 5961 scopeHostCss: function(cssText, name, typeExtension) { |
5799 var self = this; | 5962 var self = this; |
5800 return cssText.replace(selectorRe, function(m, p1, p2) { | 5963 return cssText.replace(selectorRe, function(m, p1, p2) { |
5801 return self.scopeHostSelector(p1, name, typeExtension) + ' ' + p2 + '\n\t'
; | 5964 return self.scopeHostSelector(p1, name, typeExtension) + ' ' + p2 + '\n\t'
; |
5802 }); | 5965 }); |
5803 }, | 5966 }, |
5804 // supports scopig by name and [is=name] syntax | 5967 // supports scopig by name and [is=name] syntax |
5805 scopeHostSelector: function(selector, name, typeExtension) { | 5968 scopeHostSelector: function(selector, name, typeExtension) { |
5806 var r = [], parts = selector.split(','), is = '[is=' + name + ']'; | 5969 var r = [], parts = selector.split(','), is = '[is=' + name + ']'; |
5807 parts.forEach(function(p) { | 5970 parts.forEach(function(p) { |
5808 p = p.trim(); | 5971 p = p.trim(); |
5809 // selector: *|:scope -> name | 5972 // selector: *|:scope -> name |
5810 if (p.match(hostElementRe)) { | 5973 if (p.match(hostElementRe)) { |
5811 p = p.replace(hostElementRe, typeExtension ? is + '$1$3' : | 5974 p = p.replace(hostElementRe, typeExtension ? is + '$1$3' : |
5812 name + '$1$3'); | 5975 name + '$1$3'); |
5813 // selector: .foo -> name.foo (OR) [bar] -> name[bar] | 5976 // selector: .foo -> name.foo (OR) [bar] -> name[bar] |
5814 } else if (p.match(hostFixableRe)) { | 5977 } else if (p.match(hostFixableRe)) { |
5815 p = typeExtension ? is + p : name + p; | 5978 p = typeExtension ? is + p : name + p; |
5816 } | 5979 } |
5817 r.push(p); | 5980 r.push(p); |
5818 }, this); | 5981 }, this); |
5819 return r.join(', '); | 5982 return r.join(', '); |
5820 }, | 5983 }, |
5821 // consider styles that do not include component name in the selector to be | 5984 // consider styles that do not include component name in the selector to be |
5822 // unscoped and in need of promotion; | 5985 // unscoped and in need of promotion; |
5823 // for convenience, also consider keyframe rules this way. | 5986 // for convenience, also consider keyframe rules this way. |
5824 findAtHostRules: function(cssRules, matcher) { | 5987 findAtHostRules: function(cssRules, matcher) { |
5825 return Array.prototype.filter.call(cssRules, | 5988 return Array.prototype.filter.call(cssRules, |
5826 this.isHostRule.bind(this, matcher)); | 5989 this.isHostRule.bind(this, matcher)); |
5827 }, | 5990 }, |
5828 isHostRule: function(matcher, cssRule) { | 5991 isHostRule: function(matcher, cssRule) { |
5829 return (cssRule.selectorText && cssRule.selectorText.match(matcher)) || | 5992 return (cssRule.selectorText && cssRule.selectorText.match(matcher)) || |
5830 (cssRule.cssRules && this.findAtHostRules(cssRule.cssRules, matcher).lengt
h) || | 5993 (cssRule.cssRules && this.findAtHostRules(cssRule.cssRules, matcher).lengt
h) || |
5831 (cssRule.type == CSSRule.WEBKIT_KEYFRAMES_RULE); | 5994 (cssRule.type == CSSRule.WEBKIT_KEYFRAMES_RULE); |
5832 }, | 5995 }, |
5833 /* Ensure styles are scoped. Pseudo-scoping takes a rule like: | 5996 /* Ensure styles are scoped. Pseudo-scoping takes a rule like: |
5834 * | 5997 * |
5835 * .foo {... } | 5998 * .foo {... } |
5836 * | 5999 * |
5837 * and converts this to | 6000 * and converts this to |
5838 * | 6001 * |
5839 * scopeName .foo { ... } | 6002 * scopeName .foo { ... } |
5840 */ | 6003 */ |
5841 shimScoping: function(styles, name, typeExtension) { | 6004 shimScoping: function(styles, name, typeExtension) { |
5842 if (styles) { | 6005 if (styles) { |
5843 return this.convertScopedStyles(styles, name, typeExtension); | 6006 return this.convertScopedStyles(styles, name, typeExtension); |
5844 } | 6007 } |
5845 }, | 6008 }, |
5846 convertScopedStyles: function(styles, name, typeExtension) { | 6009 convertScopedStyles: function(styles, name, typeExtension) { |
5847 var cssText = stylesToCssText(styles).replace(hostRuleRe, ''); | 6010 var cssText = stylesToCssText(styles).replace(hostRuleRe, ''); |
5848 cssText = this.insertPolyfillHostInCssText(cssText); | 6011 cssText = this.insertPolyfillHostInCssText(cssText); |
(...skipping 10 matching lines...) Expand all Loading... |
5859 }, | 6022 }, |
5860 convertParts: function(cssText) { | 6023 convertParts: function(cssText) { |
5861 return cssText.replace(cssPartRe, ' [part=$1]'); | 6024 return cssText.replace(cssPartRe, ' [part=$1]'); |
5862 }, | 6025 }, |
5863 /* | 6026 /* |
5864 * convert a rule like :host(.foo) > .bar { } | 6027 * convert a rule like :host(.foo) > .bar { } |
5865 * | 6028 * |
5866 * to | 6029 * to |
5867 * | 6030 * |
5868 * scopeName.foo > .bar, .foo scopeName > .bar { } | 6031 * scopeName.foo > .bar, .foo scopeName > .bar { } |
5869 * TODO(sorvell): file bug since native impl does not do the former yet. | 6032 * |
5870 * http://jsbin.com/OganOCI/2/edit | 6033 * and |
| 6034 * |
| 6035 * :host(.foo:host) .bar { ... } |
| 6036 * |
| 6037 * to |
| 6038 * |
| 6039 * scopeName.foo .bar { ... } |
5871 */ | 6040 */ |
5872 convertColonHost: function(cssText) { | 6041 convertColonHost: function(cssText) { |
5873 // p1 = :host, p2 = contents of (), p3 rest of rule | 6042 // p1 = :host, p2 = contents of (), p3 rest of rule |
5874 return cssText.replace(cssColonHostRe, function(m, p1, p2, p3) { | 6043 return cssText.replace(cssColonHostRe, function(m, p1, p2, p3) { |
5875 return p2 ? polyfillHostNoCombinator + p2 + p3 + ', ' | 6044 p1 = polyfillHostNoCombinator; |
5876 + p2 + ' ' + p1 + p3 : | 6045 if (p2) { |
5877 p1 + p3; | 6046 if (p2.match(polyfillHost)) { |
| 6047 return p1 + p2.replace(polyfillHost, '') + p3; |
| 6048 } else { |
| 6049 return p1 + p2 + p3 + ', ' + p2 + ' ' + p1 + p3; |
| 6050 } |
| 6051 } else { |
| 6052 return p1 + p3; |
| 6053 } |
5878 }); | 6054 }); |
5879 }, | 6055 }, |
5880 /* | 6056 /* |
5881 * Convert ^ and ^^ combinators by replacing with space. | 6057 * Convert ^ and ^^ combinators by replacing with space. |
5882 */ | 6058 */ |
5883 convertCombinators: function(cssText) { | 6059 convertCombinators: function(cssText) { |
5884 return cssText.replace('^^', ' ').replace('^', ' '); | 6060 return cssText.replace('^^', ' ').replace('^', ' '); |
5885 }, | 6061 }, |
5886 // change a selector like 'div' to 'name div' | 6062 // change a selector like 'div' to 'name div' |
5887 scopeRules: function(cssRules, name, typeExtension) { | 6063 scopeRules: function(cssRules, name, typeExtension) { |
5888 var cssText = ''; | 6064 var cssText = ''; |
5889 Array.prototype.forEach.call(cssRules, function(rule) { | 6065 Array.prototype.forEach.call(cssRules, function(rule) { |
5890 if (rule.selectorText && (rule.style && rule.style.cssText)) { | 6066 if (rule.selectorText && (rule.style && rule.style.cssText)) { |
5891 cssText += this.scopeSelector(rule.selectorText, name, typeExtension, | 6067 cssText += this.scopeSelector(rule.selectorText, name, typeExtension, |
5892 this.strictStyling) + ' {\n\t'; | 6068 this.strictStyling) + ' {\n\t'; |
5893 cssText += this.propertiesFromRule(rule) + '\n}\n\n'; | 6069 cssText += this.propertiesFromRule(rule) + '\n}\n\n'; |
5894 } else if (rule.media) { | 6070 } else if (rule.media) { |
5895 cssText += '@media ' + rule.media.mediaText + ' {\n'; | 6071 cssText += '@media ' + rule.media.mediaText + ' {\n'; |
5896 cssText += this.scopeRules(rule.cssRules, name); | 6072 cssText += this.scopeRules(rule.cssRules, name); |
5897 cssText += '\n}\n\n'; | 6073 cssText += '\n}\n\n'; |
5898 } else if (rule.cssText) { | 6074 } else if (rule.cssText) { |
5899 cssText += rule.cssText + '\n\n'; | 6075 cssText += rule.cssText + '\n\n'; |
5900 } | 6076 } |
5901 }, this); | 6077 }, this); |
5902 return cssText; | 6078 return cssText; |
5903 }, | 6079 }, |
5904 scopeSelector: function(selector, name, typeExtension, strict) { | 6080 scopeSelector: function(selector, name, typeExtension, strict) { |
5905 var r = [], parts = selector.split(','); | 6081 var r = [], parts = selector.split(','); |
5906 parts.forEach(function(p) { | 6082 parts.forEach(function(p) { |
5907 p = p.trim(); | 6083 p = p.trim(); |
5908 if (this.selectorNeedsScoping(p, name, typeExtension)) { | 6084 if (this.selectorNeedsScoping(p, name, typeExtension)) { |
5909 p = strict ? this.applyStrictSelectorScope(p, name) : | 6085 p = strict ? this.applyStrictSelectorScope(p, name) : |
5910 this.applySimpleSelectorScope(p, name, typeExtension); | 6086 this.applySimpleSelectorScope(p, name, typeExtension); |
5911 } | 6087 } |
5912 r.push(p); | 6088 r.push(p); |
5913 }, this); | 6089 }, this); |
5914 return r.join(', '); | 6090 return r.join(', '); |
5915 }, | 6091 }, |
5916 selectorNeedsScoping: function(selector, name, typeExtension) { | 6092 selectorNeedsScoping: function(selector, name, typeExtension) { |
5917 var matchScope = typeExtension ? name : '\\[is=' + name + '\\]'; | 6093 var re = this.makeScopeMatcher(name, typeExtension); |
5918 var re = new RegExp('^(' + matchScope + ')' + selectorReSuffix, 'm'); | |
5919 return !selector.match(re); | 6094 return !selector.match(re); |
5920 }, | 6095 }, |
| 6096 makeScopeMatcher: function(name, typeExtension) { |
| 6097 var matchScope = typeExtension ? '\\[is=[\'"]?' + name + '[\'"]?\\]' : name; |
| 6098 return new RegExp('^(' + matchScope + ')' + selectorReSuffix, 'm'); |
| 6099 }, |
5921 // scope via name and [is=name] | 6100 // scope via name and [is=name] |
5922 applySimpleSelectorScope: function(selector, name, typeExtension) { | 6101 applySimpleSelectorScope: function(selector, name, typeExtension) { |
5923 var scoper = typeExtension ? '[is=' + name + ']' : name; | 6102 var scoper = typeExtension ? '[is=' + name + ']' : name; |
5924 if (selector.match(polyfillHostRe)) { | 6103 if (selector.match(polyfillHostRe)) { |
5925 selector = selector.replace(polyfillHostNoCombinator, scoper); | 6104 selector = selector.replace(polyfillHostNoCombinator, scoper); |
5926 return selector.replace(polyfillHostRe, scoper + ' '); | 6105 return selector.replace(polyfillHostRe, scoper + ' '); |
5927 } else { | 6106 } else { |
5928 return scoper + ' ' + selector; | 6107 return scoper + ' ' + selector; |
5929 } | 6108 } |
5930 }, | 6109 }, |
(...skipping 18 matching lines...) Expand all Loading... |
5949 }, | 6128 }, |
5950 insertPolyfillHostInCssText: function(selector) { | 6129 insertPolyfillHostInCssText: function(selector) { |
5951 return selector.replace(hostRe, polyfillHost).replace(colonHostRe, | 6130 return selector.replace(hostRe, polyfillHost).replace(colonHostRe, |
5952 polyfillHost); | 6131 polyfillHost); |
5953 }, | 6132 }, |
5954 propertiesFromRule: function(rule) { | 6133 propertiesFromRule: function(rule) { |
5955 var properties = rule.style.cssText; | 6134 var properties = rule.style.cssText; |
5956 // TODO(sorvell): Chrome cssom incorrectly removes quotes from the content | 6135 // TODO(sorvell): Chrome cssom incorrectly removes quotes from the content |
5957 // property. (https://code.google.com/p/chromium/issues/detail?id=247231) | 6136 // property. (https://code.google.com/p/chromium/issues/detail?id=247231) |
5958 if (rule.style.content && !rule.style.content.match(/['"]+/)) { | 6137 if (rule.style.content && !rule.style.content.match(/['"]+/)) { |
5959 properties = 'content: \'' + rule.style.content + '\';\n' + | 6138 properties = 'content: \'' + rule.style.content + '\';\n' + |
5960 rule.style.cssText.replace(/content:[^;]*;/g, ''); | 6139 rule.style.cssText.replace(/content:[^;]*;/g, ''); |
5961 } | 6140 } |
5962 return properties; | 6141 return properties; |
5963 } | 6142 } |
5964 }; | 6143 }; |
5965 | 6144 |
5966 var hostRuleRe = /@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim, | 6145 var hostRuleRe = /@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim, |
5967 selectorRe = /([^{]*)({[\s\S]*?})/gim, | 6146 selectorRe = /([^{]*)({[\s\S]*?})/gim, |
5968 hostElementRe = /(.*)((?:\*)|(?:\:scope))(.*)/, | 6147 hostElementRe = /(.*)((?:\*)|(?:\:scope))(.*)/, |
5969 hostFixableRe = /^[.\[:]/, | 6148 hostFixableRe = /^[.\[:]/, |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6035 if (window.ShadowDOMPolyfill) { | 6214 if (window.ShadowDOMPolyfill) { |
6036 addCssToDocument('style { display: none !important; }\n'); | 6215 addCssToDocument('style { display: none !important; }\n'); |
6037 var head = document.querySelector('head'); | 6216 var head = document.querySelector('head'); |
6038 head.insertBefore(getSheet(), head.childNodes[0]); | 6217 head.insertBefore(getSheet(), head.childNodes[0]); |
6039 } | 6218 } |
6040 | 6219 |
6041 // exports | 6220 // exports |
6042 scope.ShadowCSS = ShadowCSS; | 6221 scope.ShadowCSS = ShadowCSS; |
6043 | 6222 |
6044 })(window.Platform); | 6223 })(window.Platform); |
6045 | |
6046 } | 6224 } |
OLD | NEW |