Last active
July 23, 2025 13:18
-
-
Save camAtGitHub/105ced6456478085db7645d3ffb0ebd0 to your computer and use it in GitHub Desktop.
a web development bookmarklet tool that helps developers visualize and inspect CSS selectors on web pages.
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
| // Modernized version of the MRI bookmarklet | |
| // To use, host the mri.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/mri.js'); | |
| // Then browse to a page and press your bookmarklet | |
| // You enter a CSS selector and MRI highlights all matching elements on the page with colored overlays | |
| // Click any element to get suggested CSS selectors for targeting that specific element | |
| // Shows element boundaries, margins, padding, and borders with semi-transparent colored overlays | |
| // Automatically suggests various selector combinations (tag, ID, class, descendant, child selectors) for clicked elements | |
| var _____WB$wombat$assign$function_____ = function(name) {return (self._wb_wombat && self._wb_wombat.local_init && self._wb_wombat.local_init(name)) || self[name]; }; | |
| if (!self.__WB_pmw) { self.__WB_pmw = function(obj) { this.__WB_source = obj; return this; } } | |
| { | |
| let window = _____WB$wombat$assign$function_____("window"); | |
| let self = _____WB$wombat$assign$function_____("self"); | |
| let document = _____WB$wombat$assign$function_____("document"); | |
| let location = _____WB$wombat$assign$function_____("location"); | |
| let top = _____WB$wombat$assign$function_____("top"); | |
| let parent = _____WB$wombat$assign$function_____("parent"); | |
| let frames = _____WB$wombat$assign$function_____("frames"); | |
| let opener = _____WB$wombat$assign$function_____("opener"); | |
| /*MRI version 0.91a - 202507 | |
| Copyright (c) 2007 Western Civilisation pty. ltd. | |
| http://westciv.com/mri/ | |
| 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 MRIHUD 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 isWebKit() { | |
| // String found if this is a AppleWebKit based product | |
| var kitName = "applewebkit/"; | |
| var tempStr = navigator.userAgent.toLowerCase(); | |
| var pos = tempStr.indexOf(kitName); | |
| var isAppleWebkit = (pos != -1); | |
| return isAppleWebkit; | |
| } | |
| function isNightlyBuild (){ | |
| //is this a nightly build of webkit? | |
| var version = WebKitDetect.version(); | |
| return (version.isNightlyBuild) | |
| } | |
| function isSafari2() { | |
| // Legacy function - always return false for modern browsers | |
| return false; | |
| } | |
| function isSafari3() { | |
| // 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; | |
| } | |
| } | |
| function setInnerText(theElement){ | |
| //sets the innerText for the element | |
| } | |
| //end apple web kit detect | |
| function setOpacity(obj, opacity) { | |
| opacity = (opacity == 100)?99.999:opacity; | |
| // Modern browsers - just use standard opacity | |
| obj.style.opacity = opacity/100; | |
| } | |
| function fadeIn(objId,opacity) { | |
| if (document.getElementById) { | |
| obj = document.getElementById(objId); | |
| if (opacity <= 100) { | |
| setOpacity(obj, opacity); | |
| opacity += 20; | |
| window.setTimeout("fadeIn('"+objId+"',"+opacity+")", 20); | |
| } | |
| } | |
| } | |
| //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'; | |
| lastHUDTop=(e.clientY-dragYoffset-getScrollXY()[1]); | |
| return false; | |
| } | |
| } | |
| function cleanup(e) { | |
| document.onmousemove=null; | |
| document.onmouseup = null; | |
| 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("MRIHUD"); | |
| 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 | |
| var lastHUDTop=100; //last HUD top position | |
| function scrollHUD(){ | |
| // called when the window scrolls - scrll the HUD into view | |
| var theHUD = document.getElementById("MRIHUD"); | |
| if (theHUD.currentStyle){ | |
| // alert(theHUD.offsetTop-document.documentElement.scrollTop); | |
| theHUD.style.top = (document.documentElement.scrollTop + lastHUDTop) + 'px'; | |
| //lastHUDTop=document.documentElement.scrollTop + lastHUDTop; | |
| } | |
| // theHUD.style.top=; | |
| documentScrolled(); | |
| } | |
| // Cross-browser implementation of element.addEventListener() | |
| function addListener(element, type, expression, bubbling) | |
| { | |
| bubbling = bubbling || false; | |
| if(window.addEventListener) { // Standard | |
| element.addEventListener(type, expression, bubbling); | |
| return true; | |
| } else if(window.attachEvent) { // IE | |
| // element.attachEvent('on' + type, expression); | |
| element.attachEvent('on' + type, expression); | |
| return true; | |
| } else return false; | |
| } | |
| 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 addCSS() { | |
| // Inline modern CSS instead of loading from archived URLs | |
| var style = document.createElement('style'); | |
| style.type = 'text/css'; | |
| style.innerHTML = ` | |
| #MRIHUD { | |
| position: fixed; | |
| top: 10px; | |
| right: 10px; | |
| width: 300px; | |
| background: #fff; | |
| border: 2px solid #333; | |
| border-radius: 5px; | |
| box-shadow: 0 4px 8px rgba(0,0,0,0.3); | |
| font-family: Arial, sans-serif; | |
| font-size: 12px; | |
| z-index: 10000; | |
| padding: 10px; | |
| } | |
| .MRItitlebar { | |
| font-weight: bold; | |
| background: #333; | |
| color: #fff; | |
| margin: -10px -10px 10px -10px; | |
| padding: 5px 10px; | |
| border-radius: 3px 3px 0 0; | |
| } | |
| .MRIclosebox { | |
| float: right; | |
| cursor: pointer; | |
| color: #fff; | |
| font-weight: bold; | |
| margin-top: -2px; | |
| } | |
| .MRIclosebox:before { | |
| content: '×'; | |
| } | |
| #txtMRIquery { | |
| width: 200px; | |
| padding: 5px; | |
| margin-bottom: 10px; | |
| } | |
| #btnMRI { | |
| background: #333; | |
| color: #fff; | |
| padding: 5px 15px; | |
| cursor: pointer; | |
| border-radius: 3px; | |
| } | |
| .MRIOverlay { | |
| position: absolute; | |
| background: rgba(255, 0, 0, 0.3); | |
| border: 2px solid #ff0000; | |
| pointer-events: none; | |
| z-index: 9999; | |
| } | |
| #WCcanvas { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| pointer-events: none; | |
| z-index: 9998; | |
| } | |
| `; | |
| document.head.appendChild(style); | |
| } | |
| function linkJquery(){ | |
| // Use modern CSS selector API instead of jQuery | |
| if (!window.$) { | |
| window.$ = function(selector) { | |
| return document.querySelectorAll(selector); | |
| }; | |
| } | |
| } | |
| function insertHUD () { | |
| // inserts a div we use for reporting element information | |
| var theHUD = document.createElement('div'); | |
| document.body.appendChild(theHUD); | |
| theHUD.id='MRIHUD'; | |
| var newHUDContent | |
| newHUDContent= '<div class="elementInfo">'; | |
| newHUDContent= newHUDContent+'<span class="MRIclosebox"></span>'; | |
| newHUDContent= newHUDContent+'<p class="MRItitlebar">MRI</p>'; | |
| newHUDContent= newHUDContent+'<p>Enter a selector and click MRI.</p> <p>MRI will highlight any element that matches the selector</p>' | |
| newHUDContent= newHUDContent+'</div>'; | |
| newHUDContent= newHUDContent+'<div class="group">'; | |
| newHUDContent= newHUDContent+'<p><textarea id="txtMRIquery"></textarea> <span id="btnMRI">MRI</span></p></div>' | |
| newHUDContent= newHUDContent+'<div class="group"><span id="mriItemCount"></span></div>'; | |
| newHUDContent= newHUDContent+'<div class="group" id="MRISuggestedSelectors"><p>Suggest Selectors</p><p>Click any element to suggest selectors for it.</p></div>'; | |
| newHUDContent= newHUDContent +'<div id="MRIabout">'; | |
| newHUDContent= newHUDContent+'<p><a href="#" class="MRIdetailedLink">about MRI (v 1.0 modernized)</a></p>'; | |
| newHUDContent= newHUDContent+'</div>'; | |
| theHUD.innerHTML=newHUDContent; | |
| // Add modern event listeners instead of inline handlers | |
| theHUD.querySelector('.MRIclosebox').addEventListener('click', uninstallMRI); | |
| theHUD.querySelector('#btnMRI').addEventListener('click', doMRI); | |
| theHUD.querySelector('#txtMRIquery').addEventListener('keypress', keyPressed); | |
| placeHUD(window.innerHeight/2-theHUD.offsetHeight/2, window.innerWidth/2); | |
| } | |
| function showDetails() { | |
| document.navigate("https://web.archive.org/web/20120628214052/http://westciv.com/mri"); | |
| } | |
| function documentScrolled(){ | |
| //called by the scroll event on the document | |
| // alert(isSafari3()); | |
| if (isSafari2()||isSafari3()) 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; | |
| if (keythatwaspressed==13){ | |
| doMRI(); | |
| return false; | |
| } | |
| } | |
| 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) { | |
| //adapted from an example at quirksmode.org - a must read resource for javascript, DOM and all web development | |
| giveLayout(obj); | |
| var curleft = curtop = 0; | |
| if (obj.offsetParent) { | |
| curleft = obj.offsetLeft; | |
| curtop = obj.offsetTop; | |
| while (obj = obj.offsetParent) { | |
| giveLayout(obj); | |
| 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'; | |
| if (isSafari3()) { | |
| //safari 3 betas | |
| theCanvas.width=window.innerWidth-16; | |
| theCanvas.height=window.innerHeight; | |
| } | |
| else if (!isSafari2()) { | |
| //canvas is scaled in all browsers when it is resized using CSS, other than Safari 2 | |
| //in safari 2, we set the width and hiieght to 100% using CSS | |
| //in all other browsers, we set the canvas width and geight tothe visible width and height of the canvas | |
| theCanvas.width=getDocumentWidth(); | |
| theCanvas.height=getDocumentHeight(); | |
| } | |
| else { | |
| 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 suggestSelectors(e){ | |
| //for the selected element, suggest selectors that select it | |
| 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=='MRIclosebox'){ | |
| uninstallMRI(); | |
| return false; | |
| } | |
| if (tg.className=='MRIdetailedLink'){ | |
| document.navigate("https://web.archive.org/web/20120628214052/http://westciv.com"); | |
| return true; | |
| } | |
| if (tg.id=='txtMRIquery'){ | |
| return true; | |
| } | |
| if (inHUD(tg)) return false; | |
| suggestElementSelectors(tg); | |
| // alert(); | |
| return false; | |
| } | |
| function suggestElementSelectors (theElement) { | |
| // create selectors for the given element, then send these to the HUD | |
| var theSelectors="<p>Suggest Selectors</p><ul>"; | |
| theSelectors=theSelectors+'<li><a href="#" onmousedown="useSelector('+ "'"+ theElement.nodeName.toLowerCase() + "'"+')">'+theElement.nodeName.toLowerCase() +' {}</a></li>'; | |
| if (theElement.id!='') theSelectors=theSelectors + " " + '<li><a href="#" onmousedown="useSelector('+ "'#"+ theElement.id+ "'"+')">#'+theElement.id +' {}</a></li>'; | |
| if (theElement.className!='') theSelectors=theSelectors + " " + '<li><a href="#" onmousedown="useSelector('+ "'."+ theElement.className +"'"+')">.'+theElement.className +' {}</a></li>'; | |
| //want to check ancestors - create descendant selector based on ids and classes, and child selectors based on | |
| var theDescendents=''; | |
| var theChildren=''; | |
| var elementCopy=theElement; | |
| if (theElement.id!=''){ | |
| theDescendents=theElement.nodeName.toLowerCase()+"#" + theElement.id; | |
| theChildren=theElement.nodeName.toLowerCase()+"#" + theElement.id; | |
| } | |
| else if (theElement.className!=''){ | |
| theDescendents=theElement.nodeName.toLowerCase()+"." + theElement.className; | |
| theChildren=theElement.nodeName.toLowerCase()+"." + theElement.className; | |
| } | |
| else { | |
| theDescendents=theElement.nodeName.toLowerCase(); | |
| theChildren=theElement.nodeName.toLowerCase(); | |
| } | |
| if (theElement.parentNode) { | |
| while ((theElement = theElement.parentNode) && (theElement.parentNode!=null)) { | |
| if (theElement.id!=''){ | |
| theDescendents= theElement.nodeName.toLowerCase()+"#" + theElement.id+ " " + theDescendents; | |
| theChildren= theElement.nodeName.toLowerCase()+"#" + theElement.id+ ">" + theChildren; | |
| } | |
| else if (theElement.className!=''){ | |
| theDescendents= theElement.nodeName.toLowerCase()+"." + theElement.className+ " " + theDescendents; | |
| theChildren= theElement.nodeName.toLowerCase()+"." + theElement.className+ ">" + theChildren; | |
| } | |
| else { | |
| theDescendents=theElement.nodeName.toLowerCase()+ " " + theDescendents; | |
| theChildren=theElement.nodeName.toLowerCase()+ ">" + theChildren; | |
| } | |
| } | |
| } | |
| theSelectors=theSelectors + " " + '<li><a href="#" onmousedown="useSelector('+ "'"+ theDescendents+ "'"+')">'+theDescendents +' {}</a></li>'; | |
| theSelectors=theSelectors + " " + '<li><a href="#" onmousedown="useSelector('+ "'"+ theChildren+ "'"+')">'+theChildren +' {}</a></li>'; | |
| theSelectors=theSelectors+'</ul>'; | |
| var suggestedPlaceholder = document.getElementById('MRISuggestedSelectors'); | |
| suggestedPlaceholder.innerHTML=theSelectors; | |
| } | |
| function useSelector(theSelector) { | |
| var mriRequest=document.getElementById('txtMRIquery'); | |
| mriRequest.value=theSelector; | |
| doMRI(); | |
| } | |
| 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) { | |
| 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) { | |
| } | |
| } | |
| 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("MRIHUD"); | |
| theHUD.style.visibility='visible'; | |
| if (didDrag) return; //once dragged, don't position it | |
| // theHUD.style.position='fixed'; | |
| setElementProperty(theHUD, 'top', elementTop); | |
| setElementProperty(theHUD, 'left', elementLeft); | |
| } | |
| 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() { | |
| } | |
| function showCanvas() { | |
| var canvas = document.getElementById("WCcanvas"); | |
| //canvas.style.display='block'; | |
| setOpacity(canvas, 0);//sets opacity to 0 for the fadein | |
| canvas.style.visibility='visible'; | |
| } | |
| function hideHUD() { | |
| var theHUD = document.getElementById("MRIHUD"); | |
| theHUD.style.visibility='hidden'; | |
| } | |
| function showHUD() { | |
| var theHUD = document.getElementById("MRIHUD"); | |
| theHUD.style.visibility='visible'; | |
| } | |
| function inHUD(obj) { | |
| //is the element in the HUD element? | |
| if (obj.id=="MRIHUD") return true; | |
| if (obj.id=='txtMRIquery') return false; | |
| if (obj.parentNode) { | |
| while (obj = obj.parentNode) { | |
| if (obj.id=="MRIHUD") return true; | |
| } | |
| } | |
| } | |
| function showMRIDetails(mriCount){ | |
| //show how many eleents are selected by this selector | |
| var newHUDContent | |
| var theMRICount = document.getElementById("mriItemCount"); | |
| theMRICount.innerHTML=mriCount+' elements are selected by this selector'; | |
| } | |
| function showElementDetails(theElement){ | |
| //show details about the element in the HUD | |
| var theHUD = document.getElementById("MRIHUD"); | |
| var newHUDContent | |
| newHUDContent= '<div class="elementInfo">'; | |
| newHUDContent= newHUDContent+'<span class="MRIclosebox"></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+'</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="https://web.archive.org/web/20120628214052/http://westciv.com/xray/" class=' +'"XRAYdetailedLink"'+' onmousedown="' +"return true" +'">about XRAY (v 0.91a)</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 - now that the canvas is abosolute not fixed for all but Safari 2, we return 0,except for Safari 2 | |
| if (isSafari2()||isSafari3()) { | |
| return getScrollXY()[0] | |
| } | |
| else { | |
| return 0 | |
| // return (getScrollXY()[0]) | |
| } | |
| } | |
| function getScrollY(){ | |
| //return the current y scroll - now that the canvas is abosolute not fixed for all but Safari 2, we return 0,except for Safari 2 | |
| if (isSafari2()||isSafari3()) { | |
| return getScrollXY()[1] | |
| } | |
| else { | |
| return 0 | |
| // return getScrollXY()[1] | |
| } | |
| } | |
| 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 | |
| //it's returned as a string so convert to an integer if you need to use it rather than display it | |
| //elementCSSDeclaration=document.defaultView.getComputedStyle(theElement,""); | |
| // | |
| if(!document.defaultView) { | |
| whichStyle=getIEPropertyName(whichStyle) | |
| } | |
| // Ensure numeric values for position properties have 'px' units | |
| if ((whichStyle === 'top' || whichStyle === 'left') && !isNaN(theValue) && theValue.toString().indexOf('px') === -1) { | |
| theValue = theValue + 'px'; | |
| } | |
| if (theElement.currentStyle) { | |
| theElement.style.whichStyle=theValue; | |
| } | |
| else if (window.getComputedStyle) | |
| theElement.style.setProperty(whichStyle, theValue, null); | |
| } | |
| function getElementProperty(theElement, whichStyle) | |
| { | |
| //adapted from quirksmode.org | |
| //if IE, change format of property name | |
| if(!document.defaultView) { | |
| whichStyle=getIEPropertyName(whichStyle); | |
| } | |
| if (theElement.currentStyle){ //problem is that this is not computed, its th evalue set, so could be 'auto' | |
| var y = theElement.currentStyle[whichStyle]; | |
| } | |
| else if (window.getComputedStyle) { | |
| var y = document.defaultView.getComputedStyle(theElement,null).getPropertyValue(whichStyle); | |
| } | |
| else { | |
| elementCSSDeclaration=document.defaultView.getComputedStyle(theElement,null); | |
| y= elementCSSDeclaration.getPropertyValue(whichStyle); | |
| } | |
| return y; | |
| } | |
| 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 | |
| if(getElementProperty(theElement, whichBorder+"-style")=='none') { | |
| return 0; //no style so any width is irrelevant | |
| } | |
| else{ | |
| 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; | |
| } | |
| return theHierarchy;//.toLowerCase(); | |
| } | |
| } | |
| function getIntegerValue(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)) { | |
| 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 overlayElement (elementTop, elementLeft, elementWidth, elementHeight) { | |
| // add a div that overlays the element with these dimensions | |
| var theOverlay=document.createElement('div'); | |
| document.body.appendChild(theOverlay); | |
| var newID='MRIOverlay' + currentMRIOverlays.length; | |
| theOverlay.id=newID; | |
| theOverlay.className='MRIOverlay'; | |
| theOverlay.style.top= elementTop+'px'; | |
| theOverlay.style.left= elementLeft+'px'; | |
| theOverlay.style.width= elementWidth+'px'; | |
| theOverlay.style.height= elementHeight+'px'; | |
| // theOverlay.style.zIndex= '1001'; | |
| // theOverlay.style.backgroundColor='red'; | |
| // theOverlay.style.visibility='visible'; | |
| currentMRIOverlays.push(newID); | |
| // alert(theOverlay.id); | |
| } | |
| 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"); | |
| ctx.fillStyle = fillColor | |
| ctx.fillRect (elementLeft, elementTop, elementWidth, elementHeight); | |
| } | |
| var currentPatient; //this is the element currently being xrayed | |
| function mriElement(theElement) { | |
| //show the element | |
| if (inHUD(theElement)) return false; | |
| drawElementSkeleton(theElement); | |
| return false; | |
| } | |
| var currentMRIOverlays = new Array(); | |
| // 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); | |
| // | |
| // topBorder=getElementProperty(theElement,'border-top-width'); | |
| // topBorder=getIntegerValue(topBorder); | |
| // bottomBorder=getElementProperty(theElement,'border-bottom-width'); | |
| // bottomBorder=getIntegerValue(bottomBorder); | |
| // leftBorder=getElementProperty(theElement,'border-left-width'); | |
| // leftBorder=getIntegerValue(leftBorder); | |
| // rightBorder=getElementProperty(theElement,'border-right-width'); | |
| // rightBorder=getIntegerValue(rightBorder); | |
| // | |
| // | |
| // 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); | |
| 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'); | |
| //semi opaque the whole window- needs to adjust canvas width and scale for window without scrollbars | |
| windowScrollX=getScrollX(); | |
| windowScrollY=getScrollY(); | |
| // alert(windowScrollY); | |
| // alert(elementTop-topMargin-topBorder-windowScrollY); | |
| // alert(windowScrollY); | |
| // alert(getScrollY()); | |
| if (supportsCanvas()) { | |
| // | |
| try { | |
| //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); | |
| // draw(elementTop-topMargin-topBorder-windowScrollY, elementLeft-leftMargin-leftBorder-windowScrollX, elementWidth+leftMargin+rightMargin+leftBorder+rightBorder, elementHeight+ topMargin + bottomMargin+bottomBorder+topBorder); | |
| } | |
| catch(err) { | |
| } | |
| } | |
| else{ | |
| overlayElement(elementTop-topMargin-topBorder-windowScrollY, elementLeft-leftMargin-leftBorder-windowScrollX, elementWidth+leftMargin+rightMargin+leftBorder+rightBorder, elementHeight+ topMargin + bottomMargin+bottomBorder+topBorder); | |
| } | |
| //need to do windows with class - add class and remove class | |
| } | |
| function uninstallMRI(){ | |
| // Clean removal of all MRI elements and event handlers | |
| clearMRIArray(); | |
| // Remove event listeners properly | |
| window.removeEventListener('scroll', scrollHUD); | |
| document.removeEventListener('mousedown', dragHandler); | |
| document.removeEventListener('click', suggestSelectors); | |
| document.removeEventListener('mouseup', suggestSelectors); | |
| // Remove DOM elements | |
| var canvas = document.getElementById("WCcanvas"); | |
| if (canvas) canvas.parentNode.removeChild(canvas); | |
| var theHUD = document.getElementById('MRIHUD'); | |
| if (theHUD) theHUD.parentNode.removeChild(theHUD); | |
| // Remove injected CSS | |
| var styles = document.querySelectorAll('style'); | |
| styles.forEach(style => { | |
| if (style.innerHTML.includes('#MRIHUD')) { | |
| style.parentNode.removeChild(style); | |
| } | |
| }); | |
| deleteNodeByID('MRIjs'); | |
| deleteNodeByID('JQjs'); | |
| } | |
| function clearMRIArray(){ | |
| //iterate throughthe current array of elements we have MRI'd and remove the class | |
| // alert(currentMRIOverlays.length); | |
| for (var i=0; i < currentMRIOverlays.length; i++) { | |
| // $(currentMRIElements[i]).removeClass('MRIClass'); | |
| var currentOverlayName = currentMRIOverlays[i] | |
| deleteNodeByID(currentOverlayName); | |
| } | |
| currentMRIElements=new Array(); | |
| } | |
| function doMRI(){ | |
| //take the current mri text from the input field and mri with it | |
| //uses jquery to find all matching elements | |
| clearMRIArray();//clear the array of elements we MRI'd | |
| var mriRequest=document.getElementById('txtMRIquery'); | |
| var matching=$(mriRequest.value); | |
| //initialize canvas for this MRI | |
| if (supportsCanvas()) { | |
| clearCanvas(); | |
| draw(0,0,getDocumentWidth() ,getDocumentHeight(), 'rgba(0,0,0,.4)'); | |
| } | |
| for (var i=0; i < matching.length; i++) { | |
| mriElement(matching[i]); | |
| } | |
| showCanvas(); | |
| showMRIDetails(i); | |
| fadeIn("WCcanvas", 0); | |
| } | |
| function installMRI() { | |
| // Modern event listener installation | |
| try { | |
| linkJquery(); | |
| addCSS(); | |
| insertCanvas(); | |
| insertHUD(); | |
| // Use modern addEventListener instead of legacy handlers | |
| window.addEventListener('scroll', scrollHUD, {passive: true}); | |
| document.addEventListener('mousedown', dragHandler, false); | |
| document.addEventListener('click', suggestSelectors, false); | |
| document.addEventListener('mouseup', suggestSelectors, false); | |
| var theHUD = document.getElementById("MRIHUD"); | |
| if (theHUD) { | |
| theHUD.addEventListener('mousedown', dragHandler, false); | |
| } | |
| } catch (err) { | |
| console.error('MRI installation failed:', err); | |
| } | |
| } | |
| installMRI(); | |
| // window.onload=installMRI//(); | |
| } | |
| /* | |
| FILE ARCHIVED ON 21:40:52 Jun 28, 2012 AND RETRIEVED FROM THE | |
| INTERNET ARCHIVE ON 11:33:58 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.811 | |
| exclusion.robots: 0.032 | |
| exclusion.robots.policy: 0.019 | |
| esindex: 0.016 | |
| cdx.remote: 68.106 | |
| LoadShardBlock: 863.649 (3) | |
| PetaboxLoader3.resolve: 656.32 (4) | |
| PetaboxLoader3.datanode: 525.357 (4) | |
| load_resource: 543.515 | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment