Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: include.postload.js

Issue 5455501458407424: Issue 1325 - Use Shadow DOM if possible when highlighting page elements (Closed)
Patch Set: Created Sept. 6, 2014, 2:57 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: include.postload.js
===================================================================
--- a/include.postload.js
+++ b/include.postload.js
@@ -19,45 +19,135 @@
var clickHide_activated = false;
var clickHide_filters = null;
var currentElement = null;
-var currentElement_boxShadow = null;
-var currentElement_backgroundColor;
var clickHideFilters = null;
var highlightedElementsSelector = null;
-var highlightedElementsBoxShadows = null;
-var highlightedElementsBGColors = null;
var clickHideFiltersDialog = null;
var lastRightClickEvent = null;
+function createShadowRootIfPossible(element)
+{
+ if (!("createShadowRoot" in element))
+ return null;
+
+ // Those elements ignore insertion points.
+ if (element.localName == "applet" || element.localName == 'input' ||
+ element.localName == "object" || element.localName == 'embed' ||
+ element.localName == "details" || element.localName == "summary")
+ return null;
Wladimir Palant 2014/09/10 21:16:33 Where does this list come from? This seems to be h
Sebastian Noack 2014/09/22 11:55:42 I finally found a way to test insertion points.
+
+ // There are some other elements (e.g. <textarea>), which don't even
+ // support author created shadow roots and throw an exception.
+ try
+ {
+ return element.createShadowRoot();
+ }
+ catch (e)
+ {
+ return null;
+ }
+}
+
+function highlightElement(element, shadowColor, backgroundColor)
+{
+ unhighlightElement(element);
+
+ var originalBoxShadowPriority = element.style.getPropertyPriority("box-shadow");
+ var originalBackgroundColorPriority = element.style.getPropertyPriority("background-color");
+ var boxShadow = "inset 0px 0px 5px " + shadowColor;
+
+ var highlightWithStyleAttribute = function()
+ {
+ var originalBoxShadow = element.style.getPropertyValue("box-shadow");
+ var originalBackgroundColor = element.style.getPropertyValue("background-color");
+
+ element.style.setProperty("box-shadow", boxShadow, "important");
+ element.style.setProperty("background-color", backgroundColor, "important");
+
+ element._unhighlight = function()
+ {
+ this.style.removeProperty("box-shadow");
+ this.style.setProperty(
+ "box-shadow",
+ originalBoxShadow,
+ originalBoxShadowPriority
+ );
+
+ this.style.removeProperty("background-color");
+ this.style.setProperty(
+ "background-color",
+ originalBackgroundColor,
+ originalBackgroundColorPriority
+ );
+ };
+ };
+
+ var highlightWithShadowDOM = function()
+ {
+ var style = document.createElement("style");
+
+ root.appendChild(document.createElement("shadow"));
+ root.appendChild(style);
+
+ style.sheet.insertRule(":host { box-shadow: " + boxShadow + " !important; background-color: " + backgroundColor + " !important; }", 0);
Wladimir Palant 2014/09/10 21:16:33 Use style.textContent = ... here for simplicity? N
+
+ element._unhighlight = function()
+ {
+ root.removeChild(style);
+ };
+ };
+
+ // If the element has important styles we have to replace the
+ // style attribute, and can't override them with shadow DOM.
+ if (originalBoxShadowPriority == "important" ||
+ originalBackgroundColorPriority == "important")
+ {
+ highlightWithStyleAttribute();
+ return;
+ }
+
+ // Otherwise we use Shadow DOM if possbile to avoid side effects
+ // when the web page updates style while highlighted.
+ var root = createShadowRootIfPossible(element);
+ if (root)
+ highlightWithShadowDOM();
+ else
+ highlightWithStyleAttribute();
+}
+
+
+function unhighlightElement(element)
+{
+ if ("_unhighlight" in element)
+ {
+ element._unhighlight();
+ delete element._unhighlight;
+ }
+}
+
// Highlight elements according to selector string. This would include
// all elements that would be affected by proposed filters.
function highlightElements(selectorString) {
- if(highlightedElementsSelector)
- unhighlightElements();
+ unhighlightElements();
var highlightedElements = document.querySelectorAll(selectorString);
highlightedElementsSelector = selectorString;
- highlightedElementsBoxShadows = new Array();
- highlightedElementsBGColors = new Array();
- for(var i = 0; i < highlightedElements.length; i++) {
- highlightedElementsBoxShadows[i] = highlightedElements[i].style.getPropertyValue("-webkit-box-shadow");
- highlightedElementsBGColors[i] = highlightedElements[i].style.backgroundColor;
- highlightedElements[i].style.setProperty("-webkit-box-shadow", "inset 0px 0px 5px #fd6738");
- highlightedElements[i].style.backgroundColor = "#f6e1e5";
- }
+ for(var i = 0; i < highlightedElements.length; i++)
+ highlightElement(highlightedElements[i], "#fd6738", "#f6e1e5");
}
// Unhighlight all elements, including those that would be affected by
// the proposed filters
function unhighlightElements() {
- if(highlightedElementsSelector == null)
- return;
- var highlightedElements = document.querySelectorAll(highlightedElementsSelector);
- for(var i = 0; i < highlightedElements.length; i++) {
- highlightedElements[i].style.setProperty("-webkit-box-shadow", highlightedElementsBoxShadows[i]);
- highlightedElements[i].style.backgroundColor = highlightedElementsBGColors[i];
+ if (highlightedElementsSelector)
+ {
+ Array.prototype.forEach.call(
+ document.querySelectorAll(highlightedElementsSelector),
+ unhighlightElement
+ );
+
+ highlightedElementsSelector = null;
}
- highlightedElementsSelector = null;
}
// Gets the absolute position of an element by walking up the DOM tree,
@@ -183,8 +273,7 @@
if(currentElement) {
currentElement.removeEventListener("contextmenu", clickHide_elementClickHandler, false);
unhighlightElements();
- currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxShadow);
- currentElement.style.backgroundColor = currentElement_backgroundColor;
+ unhighlightElement(currentElement);
currentElement = null;
clickHideFilters = null;
}
@@ -227,11 +316,8 @@
if (target && target instanceof HTMLElement)
{
currentElement = target;
- currentElement_boxShadow = target.style.getPropertyValue("-webkit-box-shadow");
- currentElement_backgroundColor = target.style.backgroundColor;
- target.style.setProperty("-webkit-box-shadow", "inset 0px 0px 5px #d6d84b");
- target.style.backgroundColor = "#f8fa47";
+ highlightElement(target, "#d6d84b", "#f8fa47");
target.addEventListener("contextmenu", clickHide_elementClickHandler, false);
}
}
@@ -242,9 +328,7 @@
if (!clickHide_activated || !currentElement)
return;
- currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxShadow);
- currentElement.style.backgroundColor = currentElement_backgroundColor;
-
+ unhighlightElement(currentElement);
currentElement.removeEventListener("contextmenu", clickHide_elementClickHandler, false);
}
@@ -320,13 +404,11 @@
// Highlight the unlucky elements
// Restore currentElement's box-shadow and bgcolor so that highlightElements won't save those
- currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxShadow);
- currentElement.style.backgroundColor = currentElement_backgroundColor;
+ unhighlightElement(currentElement);
// Highlight the elements specified by selector in yellow
highlightElements(selectorList.join(","));
// Now, actually highlight the element the user clicked on in red
- currentElement.style.setProperty("-webkit-box-shadow", "inset 0px 0px 5px #fd1708");
- currentElement.style.backgroundColor = "#f6a1b5";
+ highlightElement(currentElement, "#fd1708", "#f6a1b5");
// Make sure the browser doesn't handle this click
e.preventDefault();
@@ -526,7 +608,6 @@
// Coerce red highlighted overlay on top of element to remove.
// TODO: Wow, the design of the clickHide stuff is really dumb - gotta fix it sometime
currentElement = addElementOverlay(target);
- currentElement_backgroundColor = target.style.backgroundColor;
// clickHide_mouseOver(lastRightClickEvent);
clickHide_mouseClick(lastRightClickEvent);
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld