Last active
July 22, 2025 12:23
-
-
Save camAtGitHub/74bf8eabf1662971d6d648a353a6ec1d to your computer and use it in GitHub Desktop.
XRAY is a web development bookmarklet tool that provides detailed visual inspection of individual HTML elements and their CSS box model properties
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Modern XRAY - Web Development Tool | |
| // Modernized version of the original XRAY bookmarklet | |
| // To use host the xray.js file somewhere then create a bookmarklet with URL of: | |
| // javascript:function%20loadScript(scriptURL)%20{%20var%20scriptElem%20=%20document.createElement('SCRIPT');%20scriptElem.setAttribute('language',%20'JavaScript');%20scriptElem.setAttribute('src',%20scriptURL);%20document.body.appendChild(scriptElem);}loadScript('http://yoursite.com/xray.js'); | |
| // Then browse to a page and press your bookmarklet | |
| // - Element Box Model Visualization: Click any element to see its margins, padding, borders, and content area highlighted with different colored overlays | |
| // - CSS Property Inspector: Shows a detailed HUD with computed CSS values including dimensions, positioning, margins, padding, border widths, and inheritance hierarchy | |
| // - Visual Debugging: Helps developers understand how CSS properties affect element layout and spacing | |
| // - Keyboard Navigation: Use arrow keys to navigate between parent, child, and sibling elements in the DOM tree | |
| // - Selector Generation: Provides CSS/Stylus (browser extension) selectors for the inspected element | |
| /*XRAY version 0.91a - 20250722 | |
| Copyright (c) 2007 Western Civilisation pty. ltd. | |
| http://westciv.com/xray/ | |
| We aim to open source XRAY once the initial code is stabilized | |
| please email any suggestions, errors, feedback and so on to john allsopp | |
| [email protected] | |
| Some portions (c) Apple Computer | |
| Some portions adapted from Quirksmode http://quirksmode.org and | |
| a tutorial aby Patrick Hunlock http://www.hunlock.com/ | |
| bookmark loading code adapted from leftlogic http://leftlogic.com/lounge/articles/microformats_bookmarklet/ | |
| The XRAYHUD style inspired by the Shiira Project's HMBlkAppKit http://shiira.jp/hmblkappkit/en.html | |
| Concept inspired by Left Logic's Microformats Bookmarklet http://leftlogic.com/lounge/articles/microformats_bookmarklet/ | |
| itself from an original concept by Jon Hicks http://www.hicksdesign.co.uk/ | |
| XRAY uses jQuery, at present for one small but crucial aspect allowing support for Safari 2, though hopefully we'll take advantage of their fine effects in upcoming releases | |
| */ | |
| /* | |
| Copyright (C) 2007 Apple Computer, Inc. All rights reserved. | |
| Redistribution and use in source and binary forms, with or without | |
| modification, are permitted provided that the following conditions | |
| are met: | |
| 1. Redistributions of source code must retain the above copyright | |
| notice, this list of conditions and the following disclaimer. | |
| 2. Redistributions in binary form must reproduce the above copyright | |
| notice, this list of conditions and the following disclaimer in the | |
| documentation and/or other materials provided with the distribution. | |
| THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | |
| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | |
| CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| */ | |
| var WebKitDetect = { }; | |
| // If the user agent is WebKit, returns true. Otherwise, returns false. | |
| WebKitDetect.isWebKit = function isWebKit() | |
| { | |
| return RegExp(" AppleWebKit/").test(navigator.userAgent); | |
| } | |
| // If the user agent is WebKit, returns an array of numbers matching the "." separated | |
| // fields in the WebKit version number, with an "isNightlyBuild" property specifying | |
| // whether the user agent is a WebKit nightly build. Otherwise, returns null. | |
| // | |
| // Example: 418.10.1 => [ 418, 10, 1 ] isNightlyBuild: false | |
| WebKitDetect.version = function version() | |
| { | |
| /* Some example strings: | |
| Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/418.9.1 (KHTML, like Gecko) Safari/419.3 | |
| Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Safari/521.32 | |
| */ | |
| // grab (AppleWebKit/)(xxx.x.x) | |
| var webKitFields = RegExp("( AppleWebKit/)([^ ]+)").exec(navigator.userAgent); | |
| if (!webKitFields || webKitFields.length < 3) | |
| return null; | |
| var versionString = webKitFields[2]; | |
| var isNightlyBuild = versionString.indexOf("+") != -1; | |
| // Remove '+' or any other stray characters | |
| var invalidCharacter = RegExp("[^\\.0-9]").exec(versionString); | |
| if (invalidCharacter) | |
| versionString = versionString.slice(0, invalidCharacter.index); | |
| var version = versionString.split("."); | |
| version.isNightlyBuild = isNightlyBuild; | |
| return version; | |
| } | |
| // If the user agent is a WebKit version greater than or equal to the version specified | |
| // in the string minimumString, returns true. Returns false otherwise. minimumString | |
| // defaults to "". | |
| // | |
| // Example usage: WebKitDetect.versionIsAtLeast("418.10.1") | |
| WebKitDetect.versionIsAtLeast = function versionIsAtLeast(minimumString) | |
| { | |
| function toIntOrZero(s) | |
| { | |
| var toInt = parseInt(s); | |
| return isNaN(toInt) ? 0 : toInt; | |
| } | |
| if (minimumString === undefined) | |
| minimumString = ""; | |
| var minimum = minimumString.split("."); | |
| var version = WebKitDetect.version(); | |
| if (!version) | |
| return false; | |
| for (var i = 0; i < minimum.length; i++) { | |
| var versionField = toIntOrZero(version[i]); | |
| var minimumField = toIntOrZero(minimum[i]); | |
| if (versionField > minimumField) | |
| return true; | |
| if (versionField < minimumField) | |
| return false; | |
| } | |
| return true; | |
| } | |
| function isModernBrowser() { | |
| // Check for modern browser features instead of specific browsers | |
| return !!(window.getComputedStyle && document.querySelector && Array.prototype.forEach); | |
| } | |
| function supportsModernFeatures() { | |
| return !!(window.getComputedStyle && document.querySelector && Element.prototype.getBoundingClientRect); | |
| } | |
| function isSafari2() { | |
| // Legacy function - always return false for modern browsers | |
| return false; | |
| } | |
| function supportsCanvas(){ | |
| // Modern canvas support detection | |
| try { | |
| var canvas = document.createElement('canvas'); | |
| return !!(canvas.getContext && canvas.getContext('2d')); | |
| } | |
| catch (err){ | |
| return false; | |
| } | |
| } | |
| //end apple web kit detect | |
| //drag and drop support adapted fom http://www.hunlock.com/blogs/Javascript_Drag_and_Drop | |
| var savedTarget=null; // The target layer (effectively vidPane) | |
| var orgCursor=null; // The original mouse style so we can restore it | |
| var dragOK=false; // True if we're allowed to move the element under mouse | |
| var dragXoffset=0; // How much we've moved the element on the horozontal | |
| var dragYoffset=0; // How much we've moved the element on the verticle | |
| var didDrag=false; //set to true when we do a drag | |
| function moveHandler(e){ | |
| if (e == null) { e = window.event } | |
| if (e.button<=1&&dragOK){ | |
| savedTarget.style.left=e.clientX-dragXoffset+'px'; | |
| savedTarget.style.top=e.clientY-dragYoffset+'px'; | |
| return false; | |
| } | |
| } | |
| function cleanup(e) { | |
| document.onmousemove=null; | |
| document.onmouseup = xRayEvent; | |
| savedTarget.style.cursor=orgCursor; | |
| dragOK=false; //its been dragged now | |
| didDrag=true; | |
| } | |
| function dragHandler(e){ | |
| var htype='-moz-grabbing'; | |
| if (e == null) { e = window.event;} // htype='move';} | |
| var target = e.target != null ? e.target : e.srcElement; | |
| orgCursor=target.style.cursor; | |
| if (inHUD(target)) { | |
| target=document.getElementById("XRAYHUD"); | |
| //target.style.webkitBoxShadow='0px 0px 0px #777777'; | |
| savedTarget=target; | |
| target.style.cursor=htype; | |
| dragOK=true; | |
| dragXoffset=e.clientX-target.offsetLeft; | |
| dragYoffset=e.clientY-target.offsetTop; | |
| document.onmousemove=moveHandler; | |
| document.onmouseup=cleanup; | |
| return false; | |
| } | |
| else { | |
| hideCanvas; | |
| } | |
| } | |
| //end drag handling | |
| function GetNextStructuredSibling( objNode ){ | |
| // Copyright Ben Nadel @ KinkySolutions.com 2006 | |
| // Check for a valid starting node. | |
| if (objNode){ | |
| // Travel down the sibling chain looking for a non-text node. | |
| for ( | |
| objNode = objNode.nextSibling ; | |
| ( | |
| objNode && | |
| objNode.nodeType == 3 | |
| ) ; | |
| objNode = objNode.nextSibling | |
| ){ | |
| // Nothing has to happen here. The FOR loop itself is taking care | |
| // of the node traversing. We don't have to really worry about any | |
| // error checking as we can't really make it outside of HTML DOM | |
| // elements without hitting a structured node, or coming up with NULL. | |
| } | |
| } | |
| // Return the sibling node. | |
| if (!objNode) return (objNode); | |
| if (objNode.nodeName=="SCRIPT") return; | |
| if ((objNode.nodeName=='WCIECanvas') || (objNode.nodeName=='WCCanvas')) return; | |
| return( objNode ); | |
| } | |
| function GetPreviousStructuredSibling( objNode ){ | |
| // Travel up the sibling chain looking for a non-text node. | |
| for ( | |
| objNode = objNode.previousSibling ; | |
| ( | |
| objNode && | |
| objNode.nodeType == 3 | |
| ) ; | |
| objNode = objNode.previousSibling | |
| ){ | |
| // Nothing has to happen here. The FOR loop itself is taking care | |
| // of the node traversing. We don't have to really worry about any | |
| // error checking as we can't really make it outside of HTML DOM | |
| // elements without hitting a structured node, or coming up with NULL. | |
| } | |
| // Return the sibling node. | |
| return( objNode ); | |
| } | |
| function GetFirstStructuredChild( theElement ){ | |
| // var nodeChildren=theElement.children; | |
| var nodeChildren=theElement.childNodes; | |
| if(!nodeChildren) return theElement; | |
| //if it's the head, return the body | |
| if (theElement.nodeName=='HTML') return document.body; | |
| for (var i = 0; i < nodeChildren.length; i++) | |
| { | |
| var aChild=nodeChildren[i]; | |
| if (aChild.nodeName!=="#text") { | |
| break; | |
| } | |
| } | |
| if(!aChild) return theElement; | |
| if (aChild.nodeName=="SCRIPT") return theElement; | |
| if (aChild.nodeName=="#text") return theElement; | |
| return aChild; | |
| } | |
| function scrollToElement(theElement){ | |
| // http://radio.javaranch.com/pascarello/2005/01/09/1105293729000.html | |
| whereIs=getElementOffsetLocation(theElement); | |
| elementTop=whereIs[1]; | |
| elementLeft=whereIs[0]; | |
| elementHeight=theElement.offsetHeight | |
| if (elementTop>getClientHeight()+getScrollXY()[1] || elementTop+elementHeight<getScrollXY()[1]) | |
| window.scrollTo(0,elementTop-(getClientHeight()/2)); | |
| } | |
| function welcomeToXRAY(){ | |
| var theHUD = document.getElementById("XRAYHUD"); | |
| var newHUDContent | |
| newHUDContent= '<div class="elementInfo">'; | |
| newHUDContent= newHUDContent+'<span class="XRAYclosebox"></span>'; | |
| newHUDContent= newHUDContent+'<p class="XRAYtitlebar">XRAY</p>'; | |
| newHUDContent= newHUDContent+'<p><strong>Welcome to XRAY</strong></p>' | |
| newHUDContent= newHUDContent+'</div>'; | |
| newHUDContent= newHUDContent+'<p>Click any element on the page to XRAY it.</p>' | |
| newHUDContent= newHUDContent+'<p>Just click the close box or refresh the page to turn off XRAY.</p>' | |
| newHUDContent= newHUDContent +'<div id="XRAYabout">'; | |
| newHUDContent= newHUDContent+'<p><a href="#" class=' +'"XRAYdetailedLink"'+' onmousedown=' +"return true" +'>XRAY (v 2.0 - Modernized)</a></p>'; | |
| newHUDContent= newHUDContent+'</div>'; | |
| theHUD.innerHTML=newHUDContent; | |
| placeHUD(window.innerHeight/2-theHUD.offsetHeight/2, window.innerWidth/2); | |
| } | |
| function addCSS() { | |
| // Add inline CSS instead of external files for better compatibility | |
| const cssContent = ` | |
| #XRAYHUD { | |
| position: fixed !important; | |
| z-index: 999999 !important; | |
| background: rgba(0, 0, 0, 0.9) !important; | |
| color: white !important; | |
| font-family: Arial, sans-serif !important; | |
| font-size: 12px !important; | |
| padding: 10px !important; | |
| border-radius: 5px !important; | |
| max-width: 300px !important; | |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3) !important; | |
| } | |
| #XRAYHUD p, #XRAYHUD ul, #XRAYHUD li { | |
| margin: 5px 0 !important; | |
| padding: 0 !important; | |
| list-style: none !important; | |
| } | |
| #XRAYHUD strong { | |
| color: #4CAF50 !important; | |
| } | |
| #XRAYHUD .XRAYclosebox { | |
| position: absolute !important; | |
| top: 5px !important; | |
| right: 8px !important; | |
| cursor: pointer !important; | |
| font-weight: bold !important; | |
| color: #ff6b6b !important; | |
| } | |
| #XRAYHUD .XRAYclosebox:before { | |
| content: "✕" !important; | |
| } | |
| #XRAYWidthLabel, #XRAYHeightLabel, #XRAYTopLeftLabel { | |
| position: absolute !important; | |
| z-index: 999998 !important; | |
| background: rgba(255, 255, 255, 0.9) !important; | |
| color: black !important; | |
| font-family: Arial, sans-serif !important; | |
| font-size: 11px !important; | |
| padding: 2px 4px !important; | |
| border-radius: 3px !important; | |
| pointer-events: none !important; | |
| } | |
| #WCcanvas { | |
| position: absolute !important; | |
| top: 0 !important; | |
| left: 0 !important; | |
| z-index: 999997 !important; | |
| pointer-events: none !important; | |
| } | |
| `; | |
| const styleElement = document.createElement('style'); | |
| styleElement.textContent = cssContent; | |
| styleElement.id = 'XRAYStyles'; | |
| document.head.appendChild(styleElement); | |
| } | |
| function showDetails() { | |
| document.navigate("https://web.archive.org/web/20131202165448/http://westciv.com"); | |
| } | |
| function documentScrolled(){ | |
| //called by the scroll event on the document | |
| hideCanvas(); | |
| } | |
| function windowResized(){ | |
| //called by the resize event on the document | |
| hideCanvas(); | |
| } | |
| function keyPressed(e){ | |
| //called by the onkeypress event on the document | |
| var keythatwaspressed; | |
| if (window.event) keythatwaspressed = window.event.keyCode; | |
| else if (e) keythatwaspressed = e.which; | |
| //alert(keythatwaspressed); | |
| switch (keythatwaspressed){ | |
| case 38: //up | |
| if (currentPatient.parentNode){ | |
| while (currentPatient.parentNode.nodeName == '#text'){ | |
| currentPatient = currentPatient.parentNode; | |
| } | |
| // alert(currentPatient.nodeName); | |
| if (!(currentPatient.nodeName=='HTML')){ | |
| xRayElement(currentPatient.parentNode); | |
| } | |
| return false; | |
| } | |
| break; | |
| case 37: //left | |
| if (GetPreviousStructuredSibling(currentPatient)) xRayElement(GetPreviousStructuredSibling(currentPatient)); | |
| return false; | |
| break; | |
| case 39: //right | |
| if (GetNextStructuredSibling(currentPatient)) xRayElement(GetNextStructuredSibling(currentPatient)); | |
| return false; | |
| break; | |
| case 40: //down | |
| if (GetFirstStructuredChild(currentPatient)) xRayElement(GetFirstStructuredChild(currentPatient)); | |
| return false; | |
| break; | |
| default : return true; | |
| } | |
| } | |
| function giveLayout(obj){ | |
| //if this is IE, and theposition of the element is relative, give it haslayout - otherwise, calculating offset location is wrong | |
| if (obj.currentStyle){ //do the hasLayout if it is relative | |
| if (obj.currentStyle.position=='relative') { | |
| obj.style.zoom='100%' | |
| } | |
| } | |
| } | |
| function getElementOffsetLocation(obj) { | |
| // Modern way using getBoundingClientRect | |
| try { | |
| if (obj.getBoundingClientRect) { | |
| const rect = obj.getBoundingClientRect(); | |
| const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; | |
| const scrollTop = window.pageYOffset || document.documentElement.scrollTop; | |
| return [rect.left + scrollLeft, rect.top + scrollTop]; | |
| } | |
| } catch (err) { | |
| // Fallback to old method | |
| let curleft = 0, curtop = 0; | |
| if (obj.offsetParent) { | |
| curleft = obj.offsetLeft; | |
| curtop = obj.offsetTop; | |
| while (obj = obj.offsetParent) { | |
| curleft += obj.offsetLeft; | |
| curtop += obj.offsetTop; | |
| } | |
| } | |
| return [curleft, curtop]; | |
| } | |
| } | |
| function insertCanvas () { | |
| // inserts a canvas element to do the drawing | |
| var theCanvas = document.createElement('CANVAS'); | |
| document.body.appendChild(theCanvas); | |
| theCanvas.id='WCcanvas'; | |
| // Set canvas dimensions for modern browsers | |
| theCanvas.width=getDocumentWidth(); | |
| theCanvas.height=getDocumentHeight(); | |
| theCanvas.onmousedown=hideCanvas; | |
| if (!supportsCanvas()) { | |
| //as there is no context for the canvas, we are using a browser that doesn't support the canvas element, so we use overlays instead | |
| insertOverlays(); | |
| } | |
| } | |
| function insertHUD () { | |
| // inserts a div we use for reporting element information | |
| var theHUD = document.createElement('div'); | |
| document.body.appendChild(theHUD); | |
| theHUD.id='XRAYHUD'; | |
| setElementProperty(theHUD, "visibility", "visible" ); | |
| } | |
| function insertLabels () { | |
| // inserts the divs we use for reporting element information | |
| var theLabel = document.createElement('div'); | |
| document.body.appendChild(theLabel); | |
| theLabel.id='XRAYWidthLabel'; | |
| theLabel.onmousedown=hideCanvas; | |
| var theLabel = document.createElement('div'); | |
| document.body.appendChild(theLabel); | |
| theLabel.id='XRAYHeightLabel'; | |
| theLabel.onmousedown=hideCanvas; | |
| var theLabel = document.createElement('div'); | |
| document.body.appendChild(theLabel); | |
| theLabel.id='XRAYTopLeftLabel'; | |
| theLabel.onmousedown=hideCanvas; | |
| } | |
| function insertOverlays () { | |
| // inserts the divs we use for overlaying for IE because we don't use canvas | |
| var theIECanvas = document.createElement('div'); | |
| document.body.appendChild(theIECanvas); | |
| theIECanvas.id='WCIECanvas'; | |
| theIECanvas.onmousedown=hideCanvas; | |
| //theIECanvas.innerHTML="<!-- -->"; //supposed to fix the min height problem for divs in IE | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='pageOverlayTop'; | |
| theOverlay.onmousedown=hideCanvas; | |
| theOverlay.innerHTML="<!-- -->"; //supposed to fix the min height problem for divs in IE | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='pageOverlayLeft'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='pageOverlayBottom'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='pageOverlayRight'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='marginOverlayTop'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='marginOverlayLeft'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='marginOverlayBottom'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='marginOverlayRight'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='paddingOverlayTop'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='paddingOverlayLeft'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='paddingOverlayBottom'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| theIECanvas.appendChild(theOverlay); | |
| theOverlay.id='paddingOverlayRight'; | |
| theOverlay.onmousedown=hideCanvas; | |
| } | |
| function insertOverlays1 () { | |
| // inserts the divs we use for overlaying for IE because we don't use canvas | |
| // var theIECanvas = document.createElement('div'); | |
| // document.body.appendChild(theOverlay); | |
| // theIECanvas.id='WCIECanvas'; | |
| // theIECanvas.onmousedown=hideCanvas; | |
| // theIECanvas.innerHTML="<!-- -->"; //supposed to fix the min height problem for divs in IE | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='pageOverlayTop'; | |
| theOverlay.onmousedown=hideCanvas; | |
| theOverlay.innerHTML="<!-- -->"; //supposed to fix the min height problem for divs in IE | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='pageOverlayLeft'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='pageOverlayBottom'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='pageOverlayRight'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='marginOverlayTop'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='marginOverlayLeft'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='marginOverlayBottom'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='marginOverlayRight'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='paddingOverlayTop'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='paddingOverlayLeft'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='paddingOverlayBottom'; | |
| theOverlay.onmousedown=hideCanvas; | |
| var theOverlay = document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| theOverlay.id='paddingOverlayRight'; | |
| theOverlay.onmousedown=hideCanvas; | |
| } | |
| function getElement(elementId) { | |
| //get the element with the id, and if it doesn;t exist, inserrt it (a div) | |
| var theElement = document.getElementById(elementId); | |
| if (!theElement) { | |
| //alert(elementId); | |
| var theElement = document.createElement('div'); | |
| document.body.appendChild(theElement); | |
| theElement.id=elementId; | |
| theElement.onmousedown=hideCanvas; | |
| } | |
| return theElement; | |
| } | |
| function deleteNodeByID(nodeId) { | |
| //delete the node with the given id, if it exists | |
| try { | |
| var theNode = document.getElementById(nodeId); | |
| if (theNode) { | |
| theNode.parentNode.removeChild(theNode); | |
| } | |
| } | |
| catch (err) { | |
| //alert(err.message); | |
| } | |
| } | |
| function showWidthLabel (theElement) { | |
| // inserts a div we use for reporting element information | |
| var theLabel = document.getElementById("XRAYWidthLabel"); | |
| theLabel.style.visibility='visible'; | |
| whereIs=getElementOffsetLocation(theElement); | |
| elementTop=whereIs[1]; | |
| elementLeft=whereIs[0]; | |
| elementTopMargin=parseInt(getElementProperty(theElement, 'margin-top')); | |
| elementBottomMargin=parseInt(getElementProperty(theElement, 'margin-bottom')); | |
| elementTopPadding=parseInt(getElementProperty(theElement, 'padding-top')); | |
| elementBottomPadding=parseInt(getElementProperty(theElement, 'padding-bottom')); | |
| elementVerticalSpace=elementTopMargin+elementBottomMargin+elementTopPadding+elementBottomPadding; | |
| elementBottom=theElement.offsetHeight+elementTop+10;//elementVerticalSpace+5; | |
| elementWidth=theElement.offsetWidth; | |
| //make sure that the label is showing | |
| var labelLeft=elementLeft+(elementWidth/2)-(theLabel.offsetWidth/2); | |
| var labelTop=elementBottom; | |
| if (labelLeft<0) labelLeft=60; | |
| if (labelLeft>window.innerWidth) labelLeft=window.innerWidth-theLabel.offsetWidth-10; | |
| if (labelTop<0) labelTop=10; | |
| // if (labelTop>window.innerHeight) labelTop=window.innerWidth-theLabel.offsetHeight-10; | |
| theLabel.style.left=labelLeft +'px'; | |
| theLabel.style.top=labelTop+ 'px'; | |
| // theLabel.style.top=+'px'; | |
| // theLabel.style.left=+ 'px'; | |
| theLabel.innerHTML=getElementProperty(theElement, 'width'); | |
| } | |
| function showHeightLabel (theElement) { | |
| // show the heigth label for this element | |
| var theLabel = document.getElementById("XRAYHeightLabel"); | |
| theLabel.style.visibility='visible'; | |
| whereIs=getElementOffsetLocation(theElement); | |
| elementTop=whereIs[1]; | |
| elementLeft=whereIs[0]; | |
| elementLeftMargin=parseInt(getElementProperty(theElement, 'margin-left')); | |
| elementRightMargin=parseInt(getElementProperty(theElement, 'margin-right')); | |
| elementLeftPadding=parseInt(getElementProperty(theElement, 'padding-left')); | |
| elementRightPadding=parseInt(getElementProperty(theElement, 'padding-right')); | |
| elementHorizontalSpace=elementLeftMargin+elementRightMargin+elementLeftPadding+elementRightPadding; | |
| elementRight=theElement.offsetWidth+elementLeft+elementHorizontalSpace; | |
| elementHeight=theElement.offsetHeight; | |
| theLabel.innerHTML=getElementProperty(theElement, 'height'); | |
| //make sure that the label is showing | |
| var labelLeft=elementLeft-(theLabel.offsetWidth)-10; | |
| var labelTop=elementTop+(elementHeight/2)-(theLabel.offsetHeight/2); | |
| if (labelLeft<0) labelLeft=10; | |
| if (labelLeft>window.innerWidth) labelLeft=window.innerWidth-theLabel.offsetWidth-10; | |
| if (labelTop<0) labelTop=10; | |
| //if (labelTop>window.innerHeight) labelTop=window.innerWidth-theLabel.offsetHeight-10; | |
| theLabel.style.left=labelLeft +'px'; | |
| theLabel.style.top=labelTop+ 'px'; | |
| } | |
| function showTopLeftLabel (theElement) { | |
| // show the topleft label for this element | |
| var theLabel = document.getElementById("XRAYTopLeftLabel"); | |
| theLabel.style.visibility='visible'; | |
| whereIs=getElementOffsetLocation(theElement); | |
| elementTop=whereIs[1]; | |
| elementLeft=whereIs[0]; | |
| elementLeftMargin=parseInt(getElementProperty(theElement, 'margin-left')); | |
| elementRightMargin=parseInt(getElementProperty(theElement, 'margin-right')); | |
| elementLeftPadding=parseInt(getElementProperty(theElement, 'padding-left')); | |
| elementRightPadding=parseInt(getElementProperty(theElement, 'padding-right')); | |
| elementHorizontalSpace=elementLeftMargin+elementRightMargin+elementLeftPadding+elementRightPadding; | |
| elementRight=theElement.offsetWidth+elementLeft+elementHorizontalSpace; | |
| elementHeight=theElement.offsetHeight; | |
| theLabel.innerHTML=elementTop + "px" + ", " + elementLeft + "px"; | |
| //make sure that the label is showing | |
| var labelLeft=elementLeft-(theLabel.offsetWidth/2); | |
| var labelTop=elementTop-(theLabel.offsetHeight) -10; | |
| if (labelLeft<0) labelLeft=60; | |
| if (labelLeft>window.innerWidth) labelLeft=window.innerWidth-theLabel.offsetWidth-10; | |
| if (labelTop<0) labelTop=10; | |
| //if (labelTop>window.innerHeight) labelTop=window.innerWidth-theLabel.offsetHeight-10; | |
| theLabel.style.left=labelLeft +'px'; | |
| theLabel.style.top=labelTop+ 'px'; | |
| // theLabel.style.left= +'px'; | |
| // theLabel.style.top=+ 'px'; | |
| } | |
| function placeHUD(elementTop, elementLeft){ | |
| //place the HUD relative to the element we are displaying inforrmation on | |
| var theHUD = document.getElementById("XRAYHUD"); | |
| theHUD.style.visibility='visible'; | |
| if (didDrag) return; //once dragged, don't position it | |
| // theHUD.style.position='fixed'; | |
| setElementProperty(theHUD, 'top', elementTop + 'px'); | |
| setElementProperty(theHUD, 'left', elementLeft + 'px'); | |
| } | |
| function hideCanvas() { | |
| if (!supportsCanvas()) { | |
| hideOverlays(); | |
| } | |
| else { | |
| var canvas = document.getElementById("WCcanvas"); | |
| canvas.style.visibility='hidden'; | |
| } | |
| hideLabels(); | |
| } | |
| function hideLabels() { | |
| var widthLabel = document.getElementById("XRAYWidthLabel"); | |
| widthLabel.style.visibility='hidden'; | |
| var heightLabel = document.getElementById("XRAYHeightLabel"); | |
| heightLabel.style.visibility='hidden'; | |
| var topLeftLabel = document.getElementById("XRAYTopLeftLabel"); | |
| topLeftLabel.style.visibility='hidden'; | |
| } | |
| function hideOverlays() { | |
| var overlayElement = document.getElementById("WCIECanvas"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("pageOverlayTop"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("pageOverlayLeft"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("pageOverlayBottom"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("pageOverlayRight"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("marginOverlayTop"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("marginOverlayLeft"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("marginOverlayBottom"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("marginOverlayRight"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("paddingOverlayTop"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("paddingOverlayLeft"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("paddingOverlayBottom"); | |
| overlayElement.style.visibility='hidden'; | |
| var overlayElement = document.getElementById("paddingOverlayRight"); | |
| overlayElement.style.visibility='hidden'; | |
| } | |
| function showCanvas() { | |
| var canvas = document.getElementById("WCcanvas"); | |
| //canvas.style.display='block'; | |
| canvas.style.visibility='visible'; | |
| } | |
| function hideHUD() { | |
| var theHUD = document.getElementById("XRAYHUD"); | |
| theHUD.style.visibility='hidden'; | |
| } | |
| function showHUD() { | |
| var theHUD = document.getElementById("XRAYHUD"); | |
| theHUD.style.visibility='visible'; | |
| } | |
| function inHUD(obj) { | |
| //is the element in the HUD element? | |
| if (obj.id=="XRAYHUD") return true; | |
| // alert(obj.parentNode); | |
| if (obj.parentNode) { | |
| while (obj = obj.parentNode) { | |
| if (obj.id=="XRAYHUD") return true; | |
| } | |
| } | |
| } | |
| function showElementDetails(theElement){ | |
| //show details about the element in the HUD | |
| var theHUD = document.getElementById("XRAYHUD"); | |
| var newHUDContent | |
| //alert(); | |
| newHUDContent= '<div class="elementInfo">'; | |
| newHUDContent= newHUDContent+'<span class="XRAYclosebox"></span>'; | |
| newHUDContent= newHUDContent+'<p class="XRAYtitlebar">XRAY</p>'; | |
| newHUDContent= newHUDContent+'<p><strong>element:</strong> ' + (theElement.nodeName).toLowerCase() +'</p>'; | |
| newHUDContent= newHUDContent+'<p><strong>id:</strong> ' + (theElement.id) +'</p>'; | |
| newHUDContent= newHUDContent+'<p><strong>class:</strong> ' + (theElement.className) +'</p>'; | |
| newHUDContent= newHUDContent+'</div>'; | |
| newHUDContent= newHUDContent+'<div id="HUDHierarchy">'; | |
| newHUDContent= newHUDContent+'<p><strong>inheritance hierarchy</strong> '+'</p>'; | |
| newHUDContent= newHUDContent+'<p>'+ getElementHierarchy(theElement) +'</p>'; | |
| newHUDContent= newHUDContent+'<p><strong>stylus selector:</strong> <code style="background: rgba(255,255,255,0.2); padding: 2px 4px; border-radius: 3px;">'+ getStylusSelector(theElement) +' {}</code></p>'; | |
| newHUDContent= newHUDContent+'</div>'; | |
| newHUDContent= newHUDContent+'<div class="group">'; | |
| newHUDContent= newHUDContent+'<p><strong>position:</strong> '+ getElementProperty(theElement, 'position') +'</p>'; | |
| whereIs=getElementOffsetLocation(theElement); | |
| elementTop=whereIs[1]; | |
| elementLeft=whereIs[0]; | |
| // newHUDContent= newHUDContent+'<div class="groupRow">'; | |
| newHUDContent= newHUDContent+'<ul>'; | |
| newHUDContent= newHUDContent+'<li><strong>top: </strong> ' + getElementProperty(theElement, 'top')+ ' (' + elementTop +'px)</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>left: </strong>' + getElementProperty(theElement, 'left') + ' (' + elementLeft +'px)</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>width: </strong>' + getElementProperty(theElement, 'width')+ ' (' + theElement.offsetWidth +'px)</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>height: </strong>' + getElementProperty(theElement, 'height')+ ' (' + theElement.offsetHeight +'px)</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>float: </strong>' + getElementProperty(theElement, 'float')+'</li>'; | |
| newHUDContent= newHUDContent+'</ul>'; | |
| newHUDContent= newHUDContent+'</div>'; | |
| newHUDContent= newHUDContent+'<div class="group">'; | |
| newHUDContent= newHUDContent+'<p><strong>border</strong> '+'</p>'; | |
| newHUDContent= newHUDContent+'<ul>'; | |
| newHUDContent= newHUDContent+'<li><strong>top:</strong> ' + getBorderWidth(theElement, 'border-top')+ 'px</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>right:</strong> ' + getBorderWidth(theElement, 'border-right')+'px</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>bottom:</strong> ' + getBorderWidth(theElement, 'border-bottom')+'px</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>left:</strong> ' + getBorderWidth(theElement, 'border-left')+'px</li>'; | |
| newHUDContent= newHUDContent+'</ul>'; | |
| newHUDContent= newHUDContent+'</div>'; | |
| // newHUDContent= newHUDContent+'</div>'; //end group row | |
| // newHUDContent= newHUDContent+'<div class="groupRow">'; | |
| newHUDContent= newHUDContent+'<div class="group">'; | |
| newHUDContent= newHUDContent+'<p><strong>margin</strong> '+'</p>'; | |
| newHUDContent= newHUDContent+'<ul>'; | |
| newHUDContent= newHUDContent+'<li><strong>top:</strong> ' + getElementProperty(theElement, 'margin-top')+'</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>right:</strong> ' + getElementProperty(theElement, 'margin-right')+'</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>bottom:</strong> ' + getElementProperty(theElement, 'margin-bottom')+'</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>left:</strong> ' + getElementProperty(theElement, 'margin-left')+'</li>'; | |
| newHUDContent= newHUDContent+'</ul>'; | |
| newHUDContent= newHUDContent+'</div>'; | |
| newHUDContent= newHUDContent+'<div class="group">'; | |
| newHUDContent= newHUDContent+'<p><strong>padding</strong> '+'</p>'; | |
| newHUDContent= newHUDContent+'<ul>'; | |
| newHUDContent= newHUDContent+'<li><strong>top:</strong> ' + getElementProperty(theElement, 'padding-top')+'</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>right:</strong> ' + getElementProperty(theElement, 'padding-right')+'</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>bottom:</strong> ' + getElementProperty(theElement, 'padding-bottom')+'</li>'; | |
| newHUDContent= newHUDContent+'<li><strong>left:</strong> ' + getElementProperty(theElement, 'padding-left')+'</li>'; | |
| newHUDContent= newHUDContent+'</ul>'; | |
| newHUDContent= newHUDContent+'</div>'; | |
| // newHUDContent= newHUDContent+'</div>'; //end group row | |
| newHUDContent= newHUDContent +'<div id="XRAYabout">'; | |
| newHUDContent= newHUDContent+'<p><a href="#" class=' +'"XRAYdetailedLink"'+' onmousedown=' +"return true" +'>XRAY (v 2.0 - Modernized)</a></p>'; | |
| newHUDContent= newHUDContent+'</div>'; | |
| theHUD.innerHTML=newHUDContent; | |
| } | |
| function getClientSize() { | |
| //http://www.howtocreate.co.uk/tutorials/javascript/browserwindow | |
| var myWidth = 0, myHeight = 0; | |
| if( typeof( window.innerWidth ) == 'number' ) { | |
| //Non-IE | |
| myWidth = window.innerWidth; | |
| myHeight = window.innerHeight; | |
| } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { | |
| //IE 6+ in 'standards compliant mode' | |
| myWidth = document.documentElement.clientWidth; | |
| myHeight = document.documentElement.clientHeight; | |
| } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { | |
| //IE 4 compatible | |
| myWidth = document.body.clientWidth; | |
| myHeight = document.body.clientHeight; | |
| } | |
| return [myHeight, myWidth]; | |
| } | |
| function getClientHeight(){ | |
| //return the height of the display area | |
| theSize=getClientSize(); | |
| theHeight=theSize[0]; | |
| return theHeight | |
| } | |
| function getClientWidth(){ | |
| //return the height of the display area | |
| theSize=getClientSize(); | |
| theWidth=theSize[1]; | |
| return theWidth | |
| } | |
| function getDocumentWidth() { | |
| if (document.body.scrollWidth) | |
| return document.body.scrollWidth; | |
| var w = document.documentElement.offsetWidth; | |
| if (window.scrollMaxX) | |
| w += window.scrollMaxX; | |
| return w; | |
| } | |
| function getDocumentHeight() { | |
| if (document.body.scrollHeight) | |
| return document.body.scrollHeight; | |
| return document.documentElement.offsetHeight; | |
| } | |
| function getScrollXY() { | |
| //http://www.howtocreate.co.uk/tutorials/javascript/browserwindow | |
| var scrOfX = 0, scrOfY = 0; | |
| if( typeof( window.pageYOffset ) == 'number' ) { | |
| //Netscape compliant | |
| scrOfY = window.pageYOffset; | |
| scrOfX = window.pageXOffset; | |
| } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) { | |
| //DOM compliant | |
| scrOfY = document.body.scrollTop; | |
| scrOfX = document.body.scrollLeft; | |
| } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) { | |
| //IE6 standards compliant mode | |
| scrOfY = document.documentElement.scrollTop; | |
| scrOfX = document.documentElement.scrollLeft; | |
| } | |
| return [scrOfX,scrOfY] | |
| } | |
| function getScrollX(){ | |
| //return the current x scroll - always return 0 for modern browsers | |
| return 0; | |
| } | |
| function getScrollY(){ | |
| //return the current y scroll - always return 0 for modern browsers | |
| return 0; | |
| } | |
| function getIEPropertyName(thePropertyName){ | |
| //IE properties have the form propertyName, as opposed to the property-name | |
| var newName=""; | |
| if (thePropertyName.indexOf('-')!=0) { | |
| var parts = new Array(); | |
| parts = thePropertyName.split('-'); | |
| } | |
| newName=parts[0]; | |
| for (var i = 1; i < parts.length; i++){ | |
| nextPart=parts[i].substring(0, 1).toUpperCase(); | |
| newName=newName+nextPart+parts[i].substring(1,parts[i].length) | |
| } | |
| if (newName=="float") newName='styleFloat'; //IE uses this fo rthe float property | |
| return newName; | |
| } | |
| function setElementProperty (theElement, whichStyle, theValue) { | |
| // set the value for the named property for the element to the given value | |
| try { | |
| if (window.getComputedStyle) { | |
| // Modern browsers - use setProperty | |
| theElement.style.setProperty(whichStyle, theValue, null); | |
| } else { | |
| // Fallback for old browsers | |
| const camelCaseProperty = whichStyle.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase()); | |
| theElement.style[camelCaseProperty] = theValue; | |
| } | |
| } catch (err) { | |
| console.error('Error setting style property:', whichStyle, theValue, err); | |
| } | |
| } | |
| function getElementProperty(theElement, whichStyle) { | |
| // Modern cross-browser computed style getter | |
| try { | |
| if (window.getComputedStyle) { | |
| const computedStyle = window.getComputedStyle(theElement, null); | |
| return computedStyle.getPropertyValue(whichStyle) || computedStyle[whichStyle]; | |
| } | |
| // Fallback for very old browsers | |
| return theElement.style[whichStyle] || 'auto'; | |
| } catch (err) { | |
| return 'auto'; | |
| } | |
| } | |
| function getBorderWidth(theElement, whichBorder){ | |
| //with IE, the default border is medium, but if the style is none, then this should be 0 | |
| if(supportsCanvas()) { | |
| return getIntegerValue(getElementProperty(theElement, whichBorder+"-width")); | |
| } | |
| //otherwise, it's IE, so we determine if that border has a style, and if it does, return the width, else 0 | |
| //alert(getElementProperty(theElement, whichBorder+"-style")); | |
| if(getElementProperty(theElement, whichBorder+"-style")=='none') { | |
| //alert(getElementProperty(theElement, whichBorder+"-width")); | |
| return 0; //no style so any width is irrelevant | |
| } | |
| else{ | |
| //alert(getElementProperty(theElement, whichBorder+"-width")); | |
| return getIntegerValue(getElementProperty(theElement, whichBorder+"-width")); | |
| } | |
| } | |
| function getElementHierarchy (theElement) { | |
| // return the inheritance hierarchy in the form parent<grandparent...<root | |
| //it's returned as a string so convert to an integer if you need to use it rather than display it | |
| var theHierarchy=""; | |
| var i=0; | |
| theHierarchy=theElement.nodeName.toLowerCase(); | |
| if (theElement.parentNode) { | |
| while ((theElement = theElement.parentNode) && (theElement.parentNode!=null)) { | |
| i++; | |
| //theHierarchy=theHierarchy+'<'+ '<a href="#" onmousedown="xRayAncestor('+ i +')">'+theElement.nodeName.toLowerCase() +'</a>'; | |
| theHierarchy= '<a href="#" onmousedown="xRayAncestor('+ i +')">'+theElement.nodeName.toLowerCase() +'</a>' +' > '+ theHierarchy; | |
| } | |
| //alert(theHierarchy); | |
| return theHierarchy;//.toLowerCase(); | |
| } | |
| } | |
| function getStylusSelector(theElement) { | |
| // Generate a Stylus CSS selector for the element | |
| var selector = theElement.nodeName.toLowerCase(); | |
| // Add ID if present | |
| if (theElement.id) { | |
| selector += '#' + theElement.id; | |
| } | |
| // Add classes if present | |
| if (theElement.className && theElement.className.trim()) { | |
| var classes = theElement.className.trim().split(/\s+/); | |
| for (var i = 0; i < classes.length; i++) { | |
| selector += '.' + classes[i]; | |
| } | |
| } | |
| // If no ID or class, try to make it more specific with attributes | |
| if (!theElement.id && (!theElement.className || !theElement.className.trim())) { | |
| // Check for common attributes to make selector more specific | |
| if (theElement.getAttribute('data-testid')) { | |
| selector += '[data-testid="' + theElement.getAttribute('data-testid') + '"]'; | |
| } else if (theElement.getAttribute('role')) { | |
| selector += '[role="' + theElement.getAttribute('role') + '"]'; | |
| } else if (theElement.getAttribute('type')) { | |
| selector += '[type="' + theElement.getAttribute('type') + '"]'; | |
| } | |
| } | |
| return selector; | |
| } | |
| function getIntegerValue(theVal) { | |
| //alert(theVal); | |
| //these are for the values of border widths. All but IE return an integer value - here we translate based on what IE does | |
| if (theVal=='thin') return 2; | |
| if (theVal=='medium') return 4; | |
| if (theVal=='thick') return 6; | |
| var newVal= theVal.substr(0, theVal.length-2).valueOf(); | |
| if (isNaN(newVal)) { | |
| //alert(theVal); | |
| return 0; | |
| } | |
| else { | |
| return parseInt(newVal); | |
| } | |
| } | |
| function clearCanvas () { | |
| //delete it and reinsert it | |
| if (!supportsCanvas()) { | |
| hideOverlays() | |
| } | |
| else { | |
| var canvas = document.getElementById("WCcanvas"); | |
| canvas.parentNode.removeChild(canvas); | |
| insertCanvas(); | |
| } | |
| } | |
| function eraseCanvas (elementTop, elementLeft, elementWidth, elementHeight) { | |
| var canvas = document.getElementById("WCcanvas"); | |
| var ctx = canvas.getContext("2d"); | |
| ctx.clearRect(elementLeft, elementTop, elementWidth, elementHeight); | |
| } | |
| function draw(elementTop, elementLeft, elementWidth, elementHeight, fillColor) { | |
| var canvas = document.getElementById("WCcanvas"); | |
| var ctx = canvas.getContext("2d"); | |
| showCanvas(); | |
| ctx.fillStyle = fillColor | |
| ctx.fillRect (elementLeft, elementTop, elementWidth, elementHeight); | |
| //alert(elementLeft + " " + elementTop + " " + elementWidth + " " + elementHeight); | |
| } | |
| function drawWidthLine(theElement) { | |
| //draw the line to show the width of the content | |
| var canvas = document.getElementById("WCcanvas"); | |
| var ctx = canvas.getContext("2d"); | |
| //assume it's already showing - called after draw - which shows the canvas | |
| windowScrollX=getScrollX(); | |
| windowScrollY=getScrollY(); | |
| whereIs=getElementOffsetLocation(theElement); | |
| elementTop=parseInt(whereIs[1])-windowScrollY; | |
| elementLeft=parseInt(whereIs[0])-windowScrollX; | |
| elementTopMargin=parseInt(getElementProperty(theElement, 'margin-top')); | |
| elementBottomMargin=parseInt(getElementProperty(theElement, 'margin-bottom')); | |
| elementTopPadding=parseInt(getElementProperty(theElement, 'padding-top')); | |
| elementBottomPadding=parseInt(getElementProperty(theElement, 'padding-bottom')); | |
| elementLeftPadding=parseInt(getElementProperty(theElement, 'padding-left')); | |
| elementRightPadding=parseInt(getElementProperty(theElement, 'padding-right')); | |
| elementVerticalSpace=elementBottomMargin+elementBottomPadding; | |
| elementBottom=parseInt(theElement.offsetHeight)+elementTop+5; | |
| elementWidth=parseInt(theElement.offsetWidth); | |
| ctx.strokeColor='rgba(255,255,255,1)' | |
| ctx.beginPath; | |
| //do the line | |
| ctx.moveTo(elementLeft+elementLeftPadding, elementBottom+2); | |
| ctx.lineTo(elementLeft+elementWidth-elementRightPadding, elementBottom+2); | |
| //now do the line limits | |
| ctx.lineWidth=1; | |
| ctx.moveTo(elementLeft+elementWidth-elementRightPadding, elementBottom-1); | |
| ctx.lineTo(elementLeft+elementWidth-elementRightPadding, elementBottom+5); | |
| ctx.moveTo(elementLeft+elementLeftPadding, elementBottom-1); | |
| ctx.lineTo(elementLeft+elementLeftPadding, elementBottom+5); | |
| ctx.stroke(); | |
| //alert(elementLeft+elementWidth); | |
| ctx.closePath; | |
| } | |
| function drawHeightLine(theElement) { | |
| //draw the line to show the height of the content | |
| var canvas = document.getElementById("WCcanvas"); | |
| var ctx = canvas.getContext("2d"); | |
| //assume it's already showing - called after draw - which shows the canvas | |
| windowScrollX=getScrollX(); | |
| windowScrollY=getScrollY(); | |
| whereIs=getElementOffsetLocation(theElement); | |
| elementTop=parseInt(whereIs[1])-windowScrollY; | |
| elementLeft=parseInt(whereIs[0])-windowScrollX; | |
| elementLeftMargin=parseInt(getElementProperty(theElement, 'margin-left')); | |
| elementRightMargin=parseInt(getElementProperty(theElement, 'margin-right')); | |
| elementLeftPadding=parseInt(getElementProperty(theElement, 'padding-left')); | |
| elementRightPadding=parseInt(getElementProperty(theElement, 'padding-right')); | |
| elementTopPadding=parseInt(getElementProperty(theElement, 'padding-top')); | |
| elementTopMargin=parseInt(getElementProperty(theElement, 'margin-top')); | |
| //alert(elementTopPadding); | |
| elementHorizontalSpace=elementLeftMargin+elementRightMargin+elementLeftPadding+elementRightPadding; | |
| elementRight=parseInt(theElement.offsetWidth)+elementLeft+elementHorizontalSpace; | |
| elementHeight=parseInt(theElement.offsetHeight); | |
| //elementHeight=parseInt(getElementProperty(theElement, 'top')); | |
| ctx.strokeColor='rgba(255,255,255,1)' | |
| ctx.beginPath; | |
| ctx.moveTo(elementLeft-elementRightMargin-5, elementTop+elementTopPadding); | |
| ctx.lineTo(elementLeft-elementRightMargin-5, elementTop+elementHeight-elementBottomPadding); | |
| ctx.moveTo(elementLeft-elementRightMargin-7, elementTop+elementTopPadding); | |
| ctx.lineTo(elementLeft-elementRightMargin-3, elementTop+elementTopPadding); | |
| ctx.moveTo(elementLeft-elementRightMargin-7, elementTop+elementHeight-elementBottomPadding); | |
| ctx.lineTo(elementLeft-elementRightMargin-3, elementTop+elementHeight-elementBottomPadding); | |
| ctx.stroke(); | |
| //alert(elementLeft+elementWidth); | |
| ctx.closePath; | |
| } | |
| function drawTopLeft(theElement) { | |
| //drawindicate where the top left is - it tricks people | |
| var canvas = document.getElementById("WCcanvas"); | |
| var ctx = canvas.getContext("2d"); | |
| //assume it's already showing - called after draw - which shows the canvas | |
| windowScrollX=getScrollX(); | |
| windowScrollY=getScrollY(); | |
| whereIs=getElementOffsetLocation(theElement); | |
| elementTop=parseInt(whereIs[1])-windowScrollY; | |
| elementLeft=parseInt(whereIs[0])-windowScrollX; | |
| elementLeftMargin=parseInt(getElementProperty(theElement, 'margin-left')); | |
| elementRightMargin=parseInt(getElementProperty(theElement, 'margin-right')); | |
| elementLeftPadding=parseInt(getElementProperty(theElement, 'padding-left')); | |
| elementRightPadding=parseInt(getElementProperty(theElement, 'padding-right')); | |
| elementTopPadding=parseInt(getElementProperty(theElement, 'padding-top')); | |
| elementHorizontalSpace=elementLeftMargin+elementRightMargin+elementLeftPadding+elementRightPadding; | |
| elementRight=parseInt(theElement.offsetWidth)+elementLeft+elementHorizontalSpace; | |
| elementHeight=parseInt(theElement.offsetHeight); | |
| ctx.save(); | |
| ctx.strokeColor='rgba(255,0,0,1)' | |
| ctx.beginPath; | |
| ctx.arc(elementLeft, elementTop, 4, 0, (Math.PI*2), 1); | |
| ctx.closePath(); | |
| ctx.fill(); | |
| ctx.restore(); | |
| } | |
| function xRayElement(theElement) { | |
| // alert(theElement.nodeName); | |
| // alert(theElement.nodeName); | |
| if(!theElement) return; | |
| //if not in sight, scroll to it | |
| currentPatient=theElement; | |
| drawElementSkeleton(theElement); | |
| showElementDetails(theElement); | |
| showWidthLabel(theElement); | |
| showHeightLabel(theElement); | |
| showTopLeftLabel(theElement); | |
| scrollToElement(theElement); | |
| } | |
| function xRayAncestor(ancestorIndex) { | |
| //show the details for the nth ancestor of the currently targetted element | |
| var ancestorNode; | |
| var i=0; | |
| if (currentPatient){ | |
| ancestorNode=currentPatient; | |
| for (var i = 0; i < ancestorIndex; i++){ | |
| ancestorNode = ancestorNode.parentNode; | |
| } | |
| } | |
| if (ancestorNode) { | |
| xRayElement(ancestorNode); | |
| } | |
| } | |
| function drawPageOverlay(elementTop, elementLeft, elementWidth, elementHeight, color){ | |
| //for UE - this uses a div element to create the semi transparent overlay over all but the current element | |
| //we use four elements for this pageOverlayTop, pageOverlayLeft, pageOverlayBottom, pageOverlayRight | |
| IECanvas=getElement('WCIECanvas'); | |
| IECanvas.style.visibility='visible'; | |
| IECanvas.style.left='0px'; | |
| IECanvas.style.top='0px'; | |
| if (elementTop<0) elementTop=0; | |
| if (elementHeight<0) elementHeight=0; | |
| //alert(elementTop); | |
| if (elementTop>0) { | |
| topOverlay=getElement('pageOverlayTop'); | |
| topOverlay.style.left='0px'; | |
| topOverlay.style.top='0px'; | |
| topOverlay.style.width=getClientWidth(); | |
| topOverlay.style.height=elementTop + "px"; | |
| topOverlay.style.visibility='visible'; | |
| topOverlay.style.backgroundColor=color; | |
| topOverlay.style.fontSize=0; | |
| topOverlay.style.lineHeight=0; | |
| } | |
| if (getDocumentHeight()-(elementTop + elementHeight)>0) { | |
| var bottomHeight=getDocumentHeight()-(elementTop + elementHeight); | |
| } | |
| else { | |
| bottomHeight=0; | |
| } | |
| if (bottomHeight>0) { | |
| bottomOverlay=getElement('pageOverlayBottom'); | |
| bottomOverlay.style.position='absolute'; | |
| bottomOverlay.style.left='0px'; | |
| bottomOverlay.style.height=bottomHeight + 'px'; | |
| bottomOverlay.style.top=elementHeight + elementTop+ "px"; | |
| bottomOverlay.style.width=getClientWidth(); | |
| bottomOverlay.style.visibility='visible'; | |
| bottomOverlay.style.backgroundColor=color; | |
| bottomOverlay.style.fontSize=0; | |
| bottomOverlay.style.lineHeight=0; | |
| } | |
| if (elementHeight>0 && elementLeft>0) { | |
| leftOverlay=getElement('pageOverlayLeft'); | |
| leftOverlay.style.position='absolute'; | |
| leftOverlay.style.left='0px'; | |
| leftOverlay.style.top=elementTop + "px"; | |
| leftOverlay.style.width=elementLeft + "px"; | |
| leftOverlay.style.height=elementHeight + 'px'; | |
| leftOverlay.style.visibility='visible'; | |
| leftOverlay.style.backgroundColor=color; | |
| leftOverlay.style.fontSize=0; | |
| leftOverlay.style.lineHeight=0; | |
| rightOverlay=getElement('pageOverlayRight'); | |
| rightOverlay.style.position='absolute'; | |
| rightOverlay.style.left=elementLeft + elementWidth + 'px'; | |
| rightOverlay.style.top=elementTop + "px"; | |
| if ((getClientWidth()-elementWidth)>0) { | |
| var rightWidth=getClientWidth()-elementWidth + 'px'; | |
| } | |
| else { | |
| rightWidth=0; | |
| } | |
| rightOverlay.style.width=rightWidth; | |
| rightOverlay.style.height=elementHeight+ 'px'; // + elementTop + "px"; | |
| rightOverlay.style.visibility='visible'; | |
| rightOverlay.style.backgroundColor=color; | |
| rightOverlay.style.fontSize=0; | |
| rightOverlay.style.lineHeight=0; | |
| } | |
| } | |
| function drawTopMargin(elementTop, elementLeft, topMarginWidth, elementWidth, color){ | |
| //for IE - this uses div elements to create the semi transparent overlay over all but the current element | |
| //we use four elements for this marginOverlayTop, marginOverlayLeft, marginOverlayBottom, marginOverlayRight | |
| if (elementTop<0) elementTop=0; | |
| if (topMarginWidth<1) return; | |
| marginOverlay=getElement('marginOverlayTop'); | |
| marginOverlay.style.left=elementLeft+'px'; | |
| marginOverlay.style.top=elementTop+'px'; | |
| marginOverlay.style.width=elementWidth+'px'; | |
| marginOverlay.style.height=topMarginWidth + "px"; | |
| marginOverlay.style.visibility='visible'; | |
| marginOverlay.style.backgroundColor=color; | |
| marginOverlay.style.fontSize=0; | |
| marginOverlay.style.lineHeight=0; | |
| } | |
| function drawBottomMargin(marginTop, marginLeft, bottomMarginWidth, elementWidth, color){ | |
| //for IE - this uses div elements to create the semi transparent overlay over all but the current element | |
| //we use four elements for this marginOverlayTop, marginOverlayLeft, marginOverlayBottom, marginOverlayRight | |
| if (marginTop<0) marginTop=0; | |
| if (bottomMarginWidth<1) return; | |
| marginOverlay=getElement('marginOverlayBottom'); | |
| marginOverlay.style.left=marginLeft+'px'; | |
| marginOverlay.style.top=marginTop+'px'; | |
| marginOverlay.style.width=elementWidth+'px'; | |
| marginOverlay.style.height=bottomMarginWidth + "px"; | |
| marginOverlay.style.visibility='visible'; | |
| marginOverlay.style.backgroundColor=color; | |
| marginOverlay.style.fontSize=0; | |
| marginOverlay.style.lineHeight=0; | |
| } | |
| function drawLeftMargin(elementTop, elementLeft, leftMarginWidth, elementHeight, color){ | |
| //for IE - this uses div elements to create the semi transparent overlay over all but the current element | |
| //we use four elements for this marginOverlayTop, marginOverlayLeft, marginOverlayBottom, marginOverlayRight | |
| if (elementTop<0) elementTop=0; | |
| if (leftMarginWidth<1) return; //don't draw it if its tiny | |
| marginOverlay=getElement('marginOverlayLeft'); | |
| marginOverlay.style.left=elementLeft+'px'; | |
| marginOverlay.style.top=elementTop+'px'; | |
| marginOverlay.style.width=leftMarginWidth+'px'; | |
| marginOverlay.style.height=elementHeight + "px"; | |
| marginOverlay.style.visibility='visible'; | |
| marginOverlay.style.backgroundColor=color; | |
| marginOverlay.style.fontSize=0; | |
| marginOverlay.style.lineHeight=0; | |
| } | |
| function drawRightMargin(marginTop, marginLeft, rightMarginWidth, elementHeight, color){ | |
| //for IE - this uses div elements to create the semi transparent overlay over all but the current element | |
| //we use four elements for this marginOverlayTop, marginOverlayLeft, marginOverlayBottom, marginOverlayRight | |
| if (marginTop<0) marginTop=0; | |
| if (rightMarginWidth<1) return; //don't draw it if its tiny | |
| marginOverlay=getElement('marginOverlayRight'); | |
| marginOverlay.style.left=marginLeft+'px'; | |
| marginOverlay.style.top=marginTop+'px'; | |
| marginOverlay.style.width=rightMarginWidth+'px'; | |
| marginOverlay.style.height=elementHeight + "px"; | |
| marginOverlay.style.visibility='visible'; | |
| marginOverlay.style.backgroundColor=color; | |
| marginOverlay.style.fontSize=0; | |
| marginOverlay.style.lineHeight=0; | |
| } | |
| function drawTopPadding(paddingTop, paddingLeft, topPaddingWidth, elementWidth, color){ | |
| //for IE - this uses div elements to create the semi transparent overlay over all but the current element | |
| //we use four elements for this marginOverlayTop, marginOverlayLeft, marginOverlayBottom, marginOverlayRight | |
| if (paddingTop<0) paddingTop=0; | |
| if (topPaddingWidth<1) return; | |
| paddingOverlay=getElement('paddingOverlayTop'); | |
| paddingOverlay.style.left=paddingLeft+'px'; | |
| paddingOverlay.style.top=paddingTop+'px'; | |
| paddingOverlay.style.width=elementWidth+'px'; | |
| paddingOverlay.style.height=topPaddingWidth + "px"; | |
| paddingOverlay.style.visibility='visible'; | |
| paddingOverlay.style.backgroundColor=color; | |
| paddingOverlay.style.fontSize=0; | |
| paddingOverlay.style.lineHeight=0; | |
| } | |
| function drawBottomPadding(paddingTop, paddingLeft, bottomPaddingWidth, elementWidth, color){ | |
| //for IE - this uses div elements to create the semi transparent overlay over all but the current element | |
| //we use four elements for this marginOverlayTop, marginOverlayLeft, marginOverlayBottom, marginOverlayRight | |
| if (paddingTop<0) paddingTop=0; | |
| if (bottomPaddingWidth<1) return; | |
| paddingOverlay=getElement('paddingOverlayBottom'); | |
| paddingOverlay.style.left=paddingLeft+'px'; | |
| paddingOverlay.style.top=paddingTop+'px'; | |
| paddingOverlay.style.width=elementWidth+'px'; | |
| paddingOverlay.style.height=bottomPaddingWidth + "px"; | |
| paddingOverlay.style.visibility='visible'; | |
| paddingOverlay.style.backgroundColor=color; | |
| paddingOverlay.style.fontSize=0; | |
| paddingOverlay.style.lineHeight=0; | |
| } | |
| function drawLeftPadding(paddingTop, paddingLeft, leftPaddingWidth, elementHeight, color){ | |
| //for IE - this uses div elements to create the semi transparent overlay over all but the current element | |
| //we use four elements for this marginOverlayTop, marginOverlayLeft, marginOverlayBottom, marginOverlayRight | |
| if (paddingTop<0) elementTop=0; | |
| if (leftPaddingWidth<1) return; //don't draw it if its tiny | |
| paddingOverlay=getElement('paddingOverlayLeft'); | |
| paddingOverlay.style.left=paddingLeft+'px'; | |
| paddingOverlay.style.top=paddingTop+'px'; | |
| paddingOverlay.style.width=leftPaddingWidth+'px'; | |
| paddingOverlay.style.height=elementHeight + "px"; | |
| paddingOverlay.style.visibility='visible'; | |
| paddingOverlay.style.backgroundColor=color; | |
| paddingOverlay.style.fontSize=0; | |
| paddingOverlay.style.lineHeight=0; | |
| } | |
| function drawRightPadding(paddingTop, paddingLeft, rightPaddingWidth, elementHeight, color){ | |
| //for IE - this uses div elements to create the semi transparent overlay over all but the current element | |
| //we use four elements for this marginOverlayTop, marginOverlayLeft, marginOverlayBottom, marginOverlayRight | |
| if (paddingTop<0) paddingTop=0; | |
| if (rightPaddingWidth<1) return; //don't draw it if its tiny | |
| paddingOverlay=getElement('paddingOverlayRight'); | |
| paddingOverlay.style.left=paddingLeft+'px'; | |
| paddingOverlay.style.top=paddingTop+'px'; | |
| paddingOverlay.style.width=rightPaddingWidth+'px'; | |
| paddingOverlay.style.height=elementHeight + "px"; | |
| paddingOverlay.style.visibility='visible'; | |
| paddingOverlay.style.backgroundColor=color; | |
| paddingOverlay.style.fontSize=0; | |
| paddingOverlay.style.lineHeight=0; | |
| } | |
| var currentPatient; //this is the element currently being xrayed | |
| function xRayEvent(e) { | |
| //xray the element - called by the click handler | |
| if (!e) var e = window.event; | |
| if (e.target) var tg = e.target; | |
| else if (e.srcElement) var tg = e.srcElement; | |
| while (tg.nodeName == '#text'){ | |
| tg = tg.parentNode; | |
| } | |
| if (tg.className=='XRAYclosebox'){ | |
| uninstallXRAY(); | |
| return false; | |
| } | |
| if (tg.className=='XRAYdetailedLink'){ | |
| document.navigate("https://web.archive.org/web/20131202165448/http://westciv.com"); | |
| return true; | |
| } | |
| if (inHUD(tg)) return false; | |
| xRayElement(tg); | |
| return false; | |
| } | |
| function drawElementSkeleton(theElement){ | |
| //draws the 'skeleton' of the given element | |
| whereIs=getElementOffsetLocation(theElement); | |
| elementTop=parseInt(whereIs[1]); | |
| elementLeft=parseInt(whereIs[0]); | |
| elementWidth=theElement.offsetWidth.valueOf(); | |
| elementHeight=theElement.offsetHeight.valueOf(); | |
| topPadding=getElementProperty(theElement,'padding-top'); | |
| topPadding=getIntegerValue(topPadding); | |
| bottomPadding=getElementProperty(theElement,'padding-bottom'); | |
| bottomPadding=getIntegerValue(bottomPadding); | |
| leftPadding=getElementProperty(theElement,'padding-left'); | |
| leftPadding=getIntegerValue(leftPadding); | |
| rightPadding=getElementProperty(theElement,'padding-right'); | |
| rightPadding=getIntegerValue(rightPadding); | |
| topMargin=getElementProperty(theElement,'margin-top'); | |
| topMargin=getIntegerValue(topMargin); | |
| bottomMargin=getElementProperty(theElement,'margin-bottom'); | |
| bottomMargin=getIntegerValue(bottomMargin); | |
| leftMargin=getElementProperty(theElement,'margin-left'); | |
| leftMargin=getIntegerValue(leftMargin); | |
| rightMargin=getElementProperty(theElement,'margin-right'); | |
| rightMargin=getIntegerValue(rightMargin); | |
| topBorder=getBorderWidth(theElement,'border-top'); | |
| bottomBorder=getBorderWidth(theElement,'border-bottom'); | |
| leftBorder=getBorderWidth(theElement,'border-left'); | |
| rightBorder=getBorderWidth(theElement,'border-right'); | |
| clearCanvas(); | |
| windowScrollX=getScrollX(); | |
| windowScrollY=getScrollY(); | |
| if (supportsCanvas()) { | |
| //add opaque background | |
| //semi opaque the whole window- needs to adjust canvas width and scale for window without scrollbars | |
| draw(0,0,getDocumentWidth() ,getDocumentHeight(), 'rgba(0,0,0,.4)'); | |
| //clear the area where the element is | |
| eraseCanvas(elementTop-topMargin-topBorder-windowScrollY, elementLeft-leftMargin-leftBorder-windowScrollX, elementWidth+leftMargin+rightMargin+leftBorder+rightBorder, elementHeight+ topMargin + bottomMargin+bottomBorder+topBorder); | |
| //draw the margin box | |
| draw(elementTop-topMargin-topBorder-windowScrollY, elementLeft-leftMargin-leftBorder, elementWidth+leftMargin+rightMargin+leftBorder+rightBorder, elementHeight+ topMargin + bottomMargin+bottomBorder+topBorder, 'rgba(0, 0, 255 , .4)'); | |
| //draw the padding box | |
| draw(elementTop-windowScrollY, elementLeft-windowScrollX, elementWidth, elementHeight, 'rgba(255, 0, 0, .4)'); | |
| //draw the content box | |
| eraseCanvas(elementTop+topPadding+topBorder-windowScrollY, elementLeft+leftPadding+leftBorder-windowScrollX, elementWidth-leftPadding-rightPadding-leftBorder-rightBorder, elementHeight-topPadding-bottomPadding-topBorder-bottomBorder); | |
| drawWidthLine(theElement); | |
| drawHeightLine(theElement); | |
| } //not ie | |
| else { | |
| //ie, so we use elements not the canvas | |
| //this overlays all but the element itself | |
| var boxWidth=elementWidth+leftMargin+rightMargin; //element width includes padding | |
| var boxHeight=elementHeight+topMargin+bottomMargin; //element height includes padding | |
| drawPageOverlay(elementTop-topMargin, elementLeft-leftMargin, boxWidth, boxHeight, '#000'); | |
| //draw the margin box | |
| drawTopMargin(elementTop-topMargin, elementLeft-leftMargin, topMargin, boxWidth, '#00f'); | |
| drawLeftMargin(elementTop, elementLeft-leftMargin, leftMargin, elementHeight, '#00f'); | |
| drawBottomMargin(elementTop + elementHeight, elementLeft-leftMargin, bottomMargin, boxWidth, '#00f'); | |
| drawRightMargin(elementTop, elementLeft+elementWidth, rightMargin, elementHeight, '#00f'); | |
| //draw the padding box | |
| drawTopPadding(elementTop, elementLeft, topPadding, elementWidth, '#f00'); | |
| drawLeftPadding(elementTop+topPadding, elementLeft, leftPadding, elementHeight-topPadding-bottomPadding, '#f00'); | |
| drawBottomPadding(elementTop + elementHeight-bottomPadding, elementLeft, bottomPadding, elementWidth, '#f00'); | |
| drawRightPadding(elementTop+topPadding, elementLeft+elementWidth-rightPadding, rightPadding, elementHeight-topPadding-bottomPadding, '#f00'); | |
| } | |
| // placeHUD(window.innerHeight/2, window.innerWidth/2); | |
| } | |
| function uninstallXRAY(){ | |
| // Clean removal of all XRAY elements and event handlers | |
| // Remove event listeners properly | |
| document.removeEventListener('click', xRayEvent); | |
| document.removeEventListener('mouseup', xRayEvent); | |
| document.removeEventListener('mousedown', dragHandler); | |
| document.removeEventListener('scroll', documentScrolled); | |
| window.removeEventListener('resize', windowResized); | |
| document.removeEventListener('keydown', keyPressed); | |
| // Remove all XRAY elements | |
| const elementsToRemove = [ | |
| 'XRAYHUD', 'XRAYWidthLabel', 'XRAYHeightLabel', 'XRAYTopLeftLabel', | |
| 'WCcanvas', 'XRAYStyles', 'pageOverlayTop', 'pageOverlayLeft', | |
| 'pageOverlayBottom', 'pageOverlayRight', 'marginOverlayTop', | |
| 'marginOverlayLeft', 'marginOverlayBottom', 'marginOverlayRight', | |
| 'paddingOverlayTop', 'paddingOverlayLeft', 'paddingOverlayBottom', | |
| 'paddingOverlayRight', 'WCIECanvas' | |
| ]; | |
| elementsToRemove.forEach(id => deleteNodeByID(id)); | |
| } | |
| function installXRAY() { | |
| // Modern event listener installation | |
| try { | |
| addCSS(); | |
| insertCanvas(); | |
| insertHUD(); | |
| insertLabels(); | |
| welcomeToXRAY(); | |
| // Use modern event listeners instead of onxxx properties | |
| document.addEventListener('click', xRayEvent, true); | |
| document.addEventListener('mouseup', xRayEvent, true); | |
| document.addEventListener('mousedown', dragHandler, true); | |
| document.addEventListener('scroll', documentScrolled); | |
| window.addEventListener('resize', windowResized); | |
| document.addEventListener('keydown', keyPressed); | |
| const theHUD = document.getElementById("XRAYHUD"); | |
| if (theHUD) { | |
| theHUD.addEventListener('mousedown', dragHandler); | |
| } | |
| deleteNodeByID('XRAYLoading'); | |
| } catch (err) { | |
| console.error('XRAY installation failed:', err); | |
| } | |
| } | |
| installXRAY(); | |
| /* | |
| FILE ARCHIVED ON 16:54:48 Dec 02, 2013 AND RETRIEVED FROM THE | |
| INTERNET ARCHIVE ON 11:02:07 Jul 22, 2025. | |
| JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. | |
| ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. | |
| SECTION 108(a)(3)). | |
| */ | |
| /* | |
| playback timings (ms): | |
| captures_list: 0.534 | |
| exclusion.robots: 0.017 | |
| exclusion.robots.policy: 0.008 | |
| esindex: 0.01 | |
| cdx.remote: 32.644 | |
| LoadShardBlock: 2308.779 (3) | |
| PetaboxLoader3.datanode: 269.8 (5) | |
| PetaboxLoader3.resolve: 3034.007 (3) | |
| load_resource: 1095.713 (2) | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment