html - Highlight Deepest Child DOM Element with Div Overlay when Moused Over in Pure Javascript -


the short version:

i want mimic google chrome's inspect element tool in pure javascript.

the long version:

i working on extension google chrome. want implement similar inspect element tool in pure javascript (no jquery or other libraries/frameworks/dependencies). if uses adblock, want mimic "block ad on page" functionality allows user select element on page.

while extension active, user should able to:

  • mouse on element
  • if 'p' element 'code' element nested inside being moused over, entire 'p' element should have 'div' overlay on
  • if mouse moves on nested 'code' element should re-size 'div' overlay cover only deeper nested 'code' element
  • when clicked, underlying element should stored , 'div' overlay hidden

why use 'div' overlay instead of adding class element adds border/outline/background color?

the overlay prevents user directly interacting element. if there href/onclick attribute not want activate when clicked.

can write stores inline 'onclick' attributes, sets them null/return false; , restores original 'onclick' code?

tried that:

onclicks = document.queryselectorall('[onclick]'); saved = [];  // disable onclicks function disableonclicks() {     (var = 0; < onclicks.length; i++) {         saved[i] = onclicks[i].clonenode();         onclicks[i].onclick = "return false;";     };     console.log("onclicks disabled"); }  // enable onclicks function enableonclicks() {     (var = 0; < onclicks.length; i++) {         onclicks[i].onclick = saved[i].onclick;     };     console.log("onclicks enabled"); }  // if injecting script, make sure elements have loaded window.onload = function(){     disableonclicks();     console.log("onclicks disabled");     enableonclicks();     console.log("onclicks enabled"); } 

unfortunately, doesn't handle invisible event listeners may on given page.

my current code formatted paste console:

// css highlight element var overlaycss = document.createelement("style"); overlaycss.type = "text/css"; overlaycss.innerhtml = "body .highlight-element{z-index:2147483647!important}.highlight-element{background-color:rgba(130,180,230,.4);outline:#0f4d9a solid 1px;box-sizing:border-box;position:absolute;display:none}"; document.body.appendchild(overlaycss);  // append style tag body  // create div overlay highlight elements & prevent onclick events var overlay = document.createelement("div"); overlay.classname = "highlight-element"; document.body.appendchild(overlay);  // append div overlay body  // check if overlay appended if (overlay === document.getelementsbyclassname('highlight-element')[0]) {     console.log("overlay exists"); };  // positions div overlay based on targetrect aka element.getboundingclientrect() function moveoverlay (targetrect) {     var overlay = document.getelementsbyclassname('highlight-element')[0];     // correct page scroll     overlay.style.top = (targetrect.top + window.scrolly) + "px";     overlay.style.left = targetrect.left + "px";     overlay.style.height = targetrect.height + "px";     overlay.style.width = targetrect.width + "px";     overlay.style.display = "block"; }  // set start time lastfire var lastfire = date.now();  function getinnermosthovered(e) {     // difference between , last event     var difference = date.now() - lastfire;     // console.log(difference);      // delay handling mousemove milliseconds     // making 0 may induce epileptic shock...     if (difference > 100) {         // prevent endless highlight loop         if (e.target.getattribute('class') == "highlight-element") {             e.target.style.display = "none";         }          // element under mouse         var n = document.queryselector(":hover");         var nn;          // deepest child element has :hover         while (n) {             nn = n;             n = nn.queryselector(":hover");         }         console.log("nn: " + nn);          // dimensions pass div overlay         var targetrect = nn.getboundingclientrect();         // console.log(targetrect.top);          // display overlay div @ element position under mouse         moveoverlay(targetrect);          // event fired, overwrite last fire time         lastfire = date.now();     } }  // onmousemove deepest child element under mouse document.addeventlistener('mousemove', getinnermosthovered, false); 

feel free test out on page (refresh page cancel), have overlay sort-of working alternating displaying/hiding overlay 'div' on 'mousemove' event. ideally want run smooth chrome's inspect element , give me element data. , ideas appreciated, must stress want in pure javascript.

edit: solved document.elementfrompoint(x,y)!

after few days of research, able find simple solution problem. code work pasted in chrome's console, press esc cancel.

var rootnode = document.documentelement; var currentnode = currentnode || {}; var lastnode = lastnode || {}; var nodeclone = nodeclone || {}; var prevonclick = prevonclick || {};  function nodehandler (e) {      var x = e.clientx;     var y = e.clienty;     // console.log(x+", "+y);      currentnode = document.elementfrompoint(x, y);      if (currentnode === rootnode || currentnode === document.body){         // if current node html or body, nothing      } else {          if (currentnode === lastnode) {             // if still on same node, nothing             // console.log('same node');          } else {             // console.log('different node');              // if lastnode has classlist, check onclick attribute , remove highlight-element class             if (lastnode.classlist) {                  // if lastnode had onclick attribute, replace untouched value nodeclone                 if (lastnode.getattribute("onclick") != null) {                     prevonclick = nodeclone.getattribute("onclick");                     lastnode.setattribute("onclick", prevonclick);                 }                  lastnode.classlist.remove('highlight-element');             }              // save currentnode , preserve inline event (onclick) attributes             nodeclone = currentnode.clonenode();              // if currentnode has onclick attribute, disable             if (currentnode.getattribute("onclick")) {                 currentnode.setattribute("onclick", "return false;");             };              // add highlight class currentnode             currentnode.classlist.add('highlight-element');         }          // store node         lastnode = currentnode;     }  }  function clickhandler (e) {     e.preventdefault();     e.stoppropagation();     e.stopimmediatepropagation();      console.log("clicked node:\n");     console.log(nodeclone); }  function cancelnodeselect (e) {     if (e.keycode == 27) {         // if lastnode has classlist, check onclick attribute , remove highlight-element class         if (lastnode.classlist) {              if (lastnode.getattribute("onclick") != null) {                 prevonclick = nodeclone.getattribute("onclick");                 lastnode.setattribute("onclick", prevonclick);             }              lastnode.classlist.remove('highlight-element');         }          // remove event listeners         document.removeeventlistener('click', clickhandler, false);         document.removeeventlistener('mousemove', nodehandler, false);         document.removeeventlistener('keyup', cancelnodeselect, false);          console.log("escape pressed");     }; }  document.addeventlistener('click', clickhandler, false); document.addeventlistener('mousemove', nodehandler, false); document.addeventlistener('keyup', cancelnodeselect, false); 

edit 2: forgot add css using

.highlight-element {     background-color: rgba(130, 180, 230, 0.4);     outline: solid 1px #0f4d9a;     box-sizing: border-box; } 


Comments

Popular posts from this blog

php - Invalid Cofiguration - yii\base\InvalidConfigException - Yii2 -

How to show in django cms breadcrumbs full path? -

ruby on rails - npm error: tunneling socket could not be established, cause=connect ETIMEDOUT -