Blakeyrat's JavaScript Is Rusty Thread



  • Ok, just in case this hasn't been brought up:

    Is there something preventing you from using querySelector to find the specific element you want? It's basically $('foo') except built into browsers.



  • @ben_lubar said in Blakeyrat's JavaScript Is Rusty Thread:

    Ok, just in case this hasn't been brought up:
    Is there something preventing you from using querySelector to find the specific element you want? It's basically $('foo') except built into browsers.

    I would also argue jQuery is still the king for dealing with DOM stuff in a cross-browser compatible manner.



  • @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    Is there any difference whatsoever between
    for (var value of list)
    and
    for (var value of list.values())
    ?
    Is there some way that list.values() works that's better? Because the example uses for...of, which works just as well with list as it does with list.values()... does it not?

    I presume list.values() will return an actual iterator object, that you can use in ways other than for ... of. For example, list.values().next() to return the first found node.

    Not sure what iterating over just the list does. Probably automagically gets the iterator behind the scenes. But I have no idea by which mechanism.


  • đźš˝ Regular

    @japonicus said in Blakeyrat's JavaScript Is Rusty Thread:

    The accepted solution is usually to wrap loop body with a test to avoid inherited properties

    Careful. ( [] ).hasOwnProperty('length') === true


  • Java Dev

    @coderpatsy said in Blakeyrat's JavaScript Is Rusty Thread:

    @japonicus said in Blakeyrat's JavaScript Is Rusty Thread:

    @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    @createdtodislikethis I think what he's saying is that to loop a NodeList using the for (var i = 0; i < list.length; ++i) method, he thinks that under the hood it has to loop the whole NodeList at least once in order to find its length, before his loop can even begin to run.

    I don't know if it does or not. It might have some reasonably cheap way of keeping the length property up-to-date when the live NodeList changes.

    avoid for (var i = 0; i < list.length; ++i) which will repeat the fairly expensive length calculation for each iteration of the loop, for (var i = 0, n = list.length; i < n; ++i) is faster.

    I can't think of many cases where the array slice alternative would be an efficient approach.

    If order of iteration doesn't matter, you could always go backwards. for (var i = list.length - 1; i >= 0; --i) No need to worry about whether accessing .length is expensive because you only do it once.

    But yeah as said this is largely over-optimization.

    But then you're iterating backwards which is less cache-friendly.

    Not that any of that is likely to be significant on javascript.



  • @createdtodislikethis said in Blakeyrat's JavaScript Is Rusty Thread:

    Also, since you hate primitive javascript, why not use typescript? (which I think you also had a thread about)
    It would allow you to use for-of (for arrays, at least), classes & lambdas (which don't have the 'this' problem), etc.
    It generally sits in the sweet spot between 'primitive' and 'too far from the target language'.

    Not only that, but to my knowledge TypeScript is a first class language in Visual Studio. Which isn't a surprise if you realize Microsoft made TypeScript in the first place.



  • @zecc said in Blakeyrat's JavaScript Is Rusty Thread:

    @japonicus said in Blakeyrat's JavaScript Is Rusty Thread:

    The accepted solution is usually to wrap loop body with a test to avoid inherited properties

    Careful. ( [] ).hasOwnProperty('length') === true

    TIL

    yuck, that's really nasty.


  • FoxDev

    @powerlord said in Blakeyrat's JavaScript Is Rusty Thread:

    Not only that, but to my knowledge TypeScript is a first class language in Visual Studio.

    I don't know if it's got quite the same lofty status as VB and C#, but yes, VS does have pretty strong TypeScript support. If it's not a first-class citizen, it's knocking on the club door 🙂



  • @ben_lubar said in Blakeyrat's JavaScript Is Rusty Thread:

    Is there something preventing you from using querySelector to find the specific element you want? It's basically $('foo') except built into browsers.

    Yes; the something is "I've never heard of it before in my life".



  • @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    @ben_lubar said in Blakeyrat's JavaScript Is Rusty Thread:

    Is there something preventing you from using querySelector to find the specific element you want? It's basically $('foo') except built into browsers.

    Yes; the something is "I've never heard of it before in my life".

    Ok, but now that I've brought it up, do the browsers you're running your code in support it? Any browser version in the last few years should be fine. document.querySelector for one element, document.querySelectorAll for all matching elements. You can use a node instead of document if you want children of a specific node.



  • @ben_lubar said in Blakeyrat's JavaScript Is Rusty Thread:

    do the browsers you're running your code in support it?

    I looked it up on MDN because I was wondering the same thing. Apparently it's been around pretty much forever.
    0_1500038660558_e06dd1ce-fe18-4d21-a257-2ac87424dfaf-image.png


  • FoxDev

    @hungrier I was about to post https://www.caniuse.com/#search=querySelector, which says the same thing. It also mentions a small IE8 bug, but 1) IE8 having a bug isn't news, and 2) Only four people still use IE8 anyway.



  • @raceprouk said in Blakeyrat's JavaScript Is Rusty Thread:

    , and 2) Only four people still use IE8 anyway.

    I wonder whether the last person using IE8 will be a developer trying to make their software support it or a user getting really confused about why everyone's telling them to update to a different browser.


  • đźš˝ Regular

    @ben_lubar Third option: a nerd for the lulz.


  • FoxDev

    @zecc Fourth option: one of @Lorne-Kates's cousins


  • :belt_onion:

    @raceprouk said in Blakeyrat's JavaScript Is Rusty Thread:

    1. Only four people still use IE8 anyway.

    Oh, my sweet summer child.


  • Winner of the 2016 Presidential Election

    @ben_lubar
    TIL that document.querySelectorAll, unlike document.getElementsByTagName, returns a static NodeList.




  • :belt_onion:

    @asdf said in Blakeyrat's JavaScript Is Rusty Thread:

    @ben_lubar
    TIL that document.querySelectorAll, unlike document.getElementsByTagName, returns a static NodeList.

    I didn't know that the NodeList returned by document.getElementsByTagName could change under me in the first place, so this thread is helpful to more than just Blakeyrat. :)



  • @heterodox Stop it, this is a coding help thread. Go elsewhere to do your dumb memes.


  • :belt_onion:

    @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    @heterodox Stop it, this is a coding help thread. Go elsewhere to do your dumb memes.

    I'm unaware of that being a meme; it's my way of saying more people use IE 8 than one would expect/hope, and thus that bug might be relevant to you. But at least it sounds like it's a small bug and not a total lack of support.

    Also, get bent.



  • @raceprouk said in Blakeyrat's JavaScript Is Rusty Thread:

    @blakeyrat No, you're right: for (x in y) will iterate through an object's properties. The only way to force it to iterate through the array as an array is for (var i = 0; i < a.length; i++).

    Of course, a JS expert will come along soon with about 5678392564839025784302 edge cases.

    not useful but I can't help myself:

    JS SO ADVANCED AND COOL THAT IT AUTOMATICALLY BY DESIGN DOES CODE REFLECTION PRECISELY WHEN NOBODY ASKED FOR IT OR EVEN KNOWS ITS HAPPENING!



  • So... uh... I just realized something...

    0_1500090975756_2f480203-dce1-4f9a-8caf-2d5cf2e8c094-image.png

    for ... in iterates over the enumerable properties of an object (including enumerable inherited properties)... notice anything different between the length property of an array vs. a nodelist?



  • Ok; I need to cover a webpage (someone else's webpage-- I do not control their DOM nor JS) with a DIV I can use to swallow click events to them. This problem has several aspects:

    • Ensure the z-index puts my div on top of all the others on the page (difficult, since the range of z-index is {undefined}. Seriously. There's no maximum value. WTF CSS!)
    • Swallow click events on my DIV so they don't "leak" through to the page below (I believe it's still possible to turn event bubbling off, right? And events still bubble top-to-bottom, right? So this should be relatively trivial.)
    • (The tough one) Create a simulcrum of the page's visible divs atop my div to identify certain parts of the page.

    The tool I'm building is a location-aware feedback tool. The idea is that you can click the "feedback" button and then get into "feedback mode" where you can then hover over elements of the page and provide feedback to them independently. For example, on NodeBB the user might mouse over their avatar icon in the upper right, and you'd want to draw a red rectangle over it and if the user clicks it you'd want to pop-up a little dialog box that says, "what do you like/dislike about this part of the page?"

    Since I don't "own" the client page, this is going to be tough-- I need to basically go through their DOM and detect which elements are actually client-facing (tons might be hidden, or exist but not expose a single pixel to the actual viewport-- think a DIV which contains another DIV of the same dimensions), then draw my own simulcrum of those on my own DIV. And it needs to work when the page resizes. And... wow I have my work cut out for me don't I?


  • FoxDev

    @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    Ensure the z-index puts my div on top of all the others on the page

    It's not a cast-iron guarantee, but setting it to 2^16 should do the trick.

    @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    Swallow click events on my DIV so they don't "leak" through to the page below

    This should do the trick:

    @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    Create a simulcrum of the page's visible divs atop my div to identify certain parts of the page.

    It may be easier to make your div transparent, so the page underneath shows through.



  • @raceprouk said in Blakeyrat's JavaScript Is Rusty Thread:

    It may be easier to make your div transparent, so the page underneath shows through.

    Well derp, but I need the regions to detect what the user clicked on. I figured (possibly dumbly) that if I made the regions DIVs, I could apply the same classes to them as the originals so when the window was resized, they'd resize in the same way, but now I'm not so sure that will work.


    New problem: Chrome's debugger stopped showing me styles when I'm inspecting elements-- any clues? Closing and restarting Chrome hasn't fixed it.


  • Impossible Mission - B

    @blakeyrat ISTM that trying to do it as a div is the source of a lot of your problems. In order to properly comply with those requirements, you're going to have to essentially reimpliment a non-trivial fraction of the browser itself.

    Any particular reason why you can't do it by iterating the DOM and attaching onclick events to everything relevant? (You've still got the same problem of determining "what is relevant?" but most of the other problems go away.)



  • @masonwheeler said in Blakeyrat's JavaScript Is Rusty Thread:

    Any particular reason why you can't do it by iterating the DOM and attaching onclick events to everything relevant? (You've still got the same problem of determining "what is relevant?" but most of the other problems go away.)

    Well I wanted to draw some pattern on the page so it was obvious to the user that it was in "feedback mode" and links/buttons/etc wouldn't work correctly. Otherwise, the page looks fine but nothing works, which isn't going to make anybody happy.

    As far as simple installing my own click handlers-- I'm all about that, but how can I guarantee my handlers fire before theirs do, so I can properly stop bubbling?


  • Impossible Mission - B

    @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    As far as simple installing my own click handlers-- I'm all about that, but how can I guarantee my handlers fire before theirs do, so I can properly stop bubbling?

    That's easy: Remove their handlers. Store them in a map so they can be replaced once you exit feedback mode.



  • @masonwheeler said in Blakeyrat's JavaScript Is Rusty Thread:

    That's easy: Remove their handlers. Store them in a map so they can be replaced once you exit feedback mode.

    And if they add new handlers while "feedback mode" is open?

    That sounds WAY more bug-prone than what I'm doing, IMO.

    Also, when answering, "wait, is that even possible?" I came across this: https://stackoverflow.com/questions/2623118/inspect-attached-event-handlers-for-any-dom-element

    Event handlers attached using DOM Level 2 Events addEventListener methods and IE's attachEvent cannot currently be retrieved from script at all. DOM Level 3 once proposed element.eventListenerList to get all listeners, but it is unclear whether this will make it to the final specification. There is no implementation in any browser today.

    EDIT: after some more reading, it's kind of possible iff:

    • You are willing to overwrite DOM object prototypes (risky proposition at best)
    • You can guarantee your JS will run before any handlers are added

    Neither of those apply to this project.



  • @blakeyrat I think what you want to do should be handled slightly differently.

    You say that you don't have control over their DOM/JS. I take it you're able to add a div to the root node, at least, and add your own JS (which could interact with their DOM/JS).

    You should be able to totally suppress all click events on the page with something like this:

    document.body.addEventListener('click', (e) => {
        console.log(e);
        e.stopPropagation();
        e.preventDefault();
    }, true);
    

    The extra argument, true, registers the handler as a "capturing" event handler. This means that the event handler on document.body will capture events -- any event that fires will be handled by this first, before propagating down to child elements. (Ordinarily, a non-captured event will first propagate all the way down to the lowest possible child element -- the event target -- triggering the event handler on that element, and then bubble back up to the root element, triggering event handlers on each of the parent elements in sequence. The root element would then be the last to receive the click event in the bubbling process, but it is the first to have the opportunity to capture the event during propagation.

    So the event handler, after capturing the event at the root node level, stops the event's propagation (none of the event handlers on descendant elements will even be notified of this event), and also prevents the default (the browser's default action, if any -- e.g. for hyperlinks -- won't be taken).



  • @masonwheeler said in Blakeyrat's JavaScript Is Rusty Thread:

    That's easy: Remove their handlers.

    That's not easy. In fact, it's not even possible.



  • @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    You say that you don't have control over their DOM/JS. I take it you're able to add a div to the root node, at least, and add your own JS (which could interact with their DOM/JS).

    I can do everything a Chrome extension can do, which is quite a bit.

    @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    You should be able to totally suppress all click events on the page with something like this:

    That's still a race condition, though: what if the site already has a handler defined that way? How do I guarantee mine runs before theirs?

    @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    The extra argument, true, registers the handler as a "capturing" event handler. This means that the event handler on document.body will capture events -- any event that fires will be handled by this first, before propagating down to child elements.

    Weird; so it's basically a bool that says "for only this event, ignore the normal event bubbling process and put me at the head of the line"? Why the fuck does DOM implement garbage like this. But hey if I can use it, I can use it.

    @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    So the event handler, after capturing the event at the root node level, stops the event's propagation (none of the event handlers on descendant elements will even be notified of this event), and also prevents the default (the browser's default action, if any -- e.g. for hyperlinks -- won't be taken).

    But does it allow me to cover the page with a graphic effect DIV, or would the DIV covering the page receive all the clicks making it useless to find what the actual page element clicked was?


  • Impossible Mission - B

    @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    That's not easy. In fact, it's not even possible.

    :wtf:

    ...oh. Right. JavaScript. :headdesk:



  • @masonwheeler That's DOM buddy. Not JavaScript. Put the blame where it belongs.


    Ok so there's a handy DOM function called document.elementFromPoint() which does exactly what it says: you pass in a cursor location, and it returns the topmost element under it.

    Problem is: there's no way to get the cursor location without capturing an event? So you can't wire this thing up on a timer. WTF DOM. You find something helpful, then find it's crippled by an obvious lack. Every fucking time.

    Now I could do something really fucking stupid, like looping over every single pixel of the viewport and running elementFromPoint() making my own map of elements, but holy shit would that be time/memory intensive. Although it's a goofy enough idea I might try it on a lark.



  • @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    That's still a race condition, though: what if the site already has a handler defined that way? How do I guarantee mine runs before theirs?

    I'm actually not sure. I think it's pretty unlikely that they would, though.

    @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    Weird; so it's basically a bool that says "for only this event, ignore the normal event bubbling process and put me at the head of the line"? Why the fuck does DOM implement garbage like this. But hey if I can use it, I can use it.

    Long ago, at least one major browser defaulted to the capturing event model, and another major browser defaulted to the bubbling event model. When things got more standardized, they combined both ideas, so now we have events that capture first and then bubble. More info here:

    @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    But does it allow me to cover the page with a graphic effect DIV, or would the DIV covering the page receive all the clicks making it useless to find what the actual page element clicked was?

    You'd still be able to cover the page with the div. Just give it the style pointer-events: none; and the mouse events will pass through it.



  • @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    I'm actually not sure. I think it's pretty unlikely that they would, though.

    I'm not a sloppy-ass Javascript dev, if I'm writing code I want to ensure that code is correct, not just "well I guess maybe it might work most of the times I guess".

    @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    You'd still be able to cover the page with the div. Just give it the style pointer-events: none;, and the mouse events will pass through it.

    That I didn't know. Thanks.

    It looks like I'm going to have to prototype a few ideas and see what works best on the most sites I have access to.



  • @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    Problem is: there's no way to get the cursor location without capturing an event? So you can't wire this thing up on a timer. WTF DOM. You find something helpful, then find it's crippled by an obvious lack. Every fucking time.

    Set a mousemove event handler on document.body, then update your overlay whenever the mouse moves. It'll give you the mouse position (and the target element, too, for that matter).



  • @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    Set a mousemove event handler on document.body, then update your overlay whenever the mouse moves. It'll give you the mouse position (and the target element, too, for that matter).

    Well derp, the problem is there's no way to get the cursor's position before the user moves it, which means right after my overlay draws (but before the user moves their cursor) it's already wrong. Web development is stinky assfarts.



  • @blakeyrat Another thing that you might potentially find useful would be element.getBoundingClientRect(). It returns

    the smallest rectangle which contains the entire element, with read-only left, top, right, bottom, x, y, width, and height properties describing the overall border-box in pixels. Properties other than width and height are relative to the top-left of the viewport.

    Note that if an overlay div has position: fixed, its coordinates are also relative to the viewport, so there'd be no conversion between them.



  • @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    Set a mousemove event handler on document.body, then update your overlay whenever the mouse moves. It'll give you the mouse position (and the target element, too, for that matter).

    Well derp, the problem is there's no way to get the cursor's position before the user moves it, which means right after my overlay draws (but before the user moves their cursor) it's already wrong. Web development is stinky assfarts.

    You can trick the browser into generating a mouse event. E.g.:

    var d = document.createElement('div');
    d.style.display = 'block';
    d.style.zIndex = '9999999999';
    d.style.position = 'fixed';
    d.style.top = d.style.left = d.style.bottom = d.style.right = '0px';
    d.addEventListener('mouseover', e => {
        d.remove();
        console.log(e.x, e.y);
    });
    document.body.appendChild(d);
    

    Adding a child element that covers the whole viewport will trigger a mouseover event on that element, assuming the mouse is actually over it. That will give you the mouse's coordinates.



  • Here's a fun thing I did that might be helpful.

    (function () {
        var d = document.createElement('div'), t;
        document.body.appendChild(d);
    
        d.style.display = 'block';
        d.style.position = 'fixed';
        d.style.background = 'rgba(255, 255, 255, 0.15)';
        d.style.zIndex = '99999999999';
        d.style.pointerEvents = 'none';
    
        function highlightTarget(e) {
            if (e.target) t = e.target;
    
            if (e.type == "mouseout") {
                d.style.width = '0px';
            } else if (t) {
                var r = t.getBoundingClientRect();
                // the bounding client rectangle of an element can lie partly or
                // entirely out of view; walk up the DOM tree and adjust if necessary
                for (var n = t; n && n != document.body; n = n.parentElement) {
                    var s = window.getComputedStyle(n);
                    var b = n.getBoundingClientRect();
                    if (s.overflowX != "visible") {
                        r = {left: Math.max(r.left, b.left), right: Math.min(r.right, b.right), top: r.top, bottom: r.bottom};
                    }
                    if (s.overflowY != "visible") {
                        r = {left: r.left, right: r.right, top: Math.max(r.top, b.top), bottom: Math.min(r.bottom, b.bottom)};
                    }
                }
                
                d.style.top = r.top + 'px';
                d.style.left = r.left + 'px';
                d.style.width = (r.right - r.left) + 'px';
                d.style.height = (r.bottom - r.top) + 'px';
                d.style.outline = Math.max(window.innerWidth, window.innerHeight) + 'px solid rgba(0, 0, 0, 0.35)';
            }
        }
        
        document.body.addEventListener('mousemove', highlightTarget);
        document.body.addEventListener('mouseover', highlightTarget);
        document.body.addEventListener('mouseout', highlightTarget);
        window.addEventListener('scroll', highlightTarget);
    })();
    


  • @anotherusername Stupid question but if the cursor is over an element, isn't it by definition visible on the page? It seems like you're doing a hell of a lot of work instead of just:

    function mouseMoveHandler(e)
    {
      var element = document.elementFromPoint(e.pageX, e.pageY);
      element.style = "border: 3px solid red;";
    }
    

    My highlight's a lot uglier than yours, but it seems like the code's equivalent.

    EDIT: oh I see what you're doing, you're basically "clipping" the bounding rectangle to the viewport. Fancier than I need.



  • @blakeyrat it's complicated.

    First of all, border is complicated. Using outline is better. When you change borders, things tend to move. You don't want that. Outline is explicitly outside of any position/size computations, so you don't have to worry about stuff moving. However, the element might have an ancestor element that has overflow: hidden, and part or all of the outline might extend outside of that, and be hidden. You can't fix that without messing with the ancestor elements, and that would get messy fast. That's mainly why I used an overlay div instead of just styling the element itself.

    Second, if you do change a style on the element itself, you have to remove it when you un-highlight the element, and you should really restore the original style, or else you'll wipe out the style that it had before. So you'd have to store the style that it had before you changed it, in order to restore it later.

    I basically just used an overlay div with a yuuuuuuuge grey transparent outline, to simulate shading the whole page. You could make it a thin red opaque outline; that'd be just as easy. Although then, my trick of setting width = '0px' wouldn't suffice to hide it; you'd have to put display = 'none' instead, and then you'd also have to put display = 'block' in the else section of that if so it'd be visible again when it's highlighting something else.



  • @blakeyrat here's an example of what I'm talking about that demonstrates both the problem of it moving (when you use border) and it being clipped (by its parent element).

    When I add/remove a red border on the code element in my post, this happens:

    0_1501189308663_Untitled.gif

    The border's only visible on the left edge (the top, right, and bottom borders are scrolled out of view), and adding the border moves everything.

    Using an outline instead won't cause it to move, but it's still not visible on the top/right/bottom sides. And the only reason it's visible on the left side is because the pre element that contains the code element has a padding of 9.5px; if it didn't have any padding, the outline on the code element wouldn't even be visible at all.

    Also, the reason why I had that loop: all by itself, calling getBoundingClientRect() on the code element will return the whole area of the screen that it would occupy if the pre element's clipping rectangle was removed, but left in the position it's currently scrolled at:

    0_1501189712482_44fa37b4-6216-4207-a056-f00cdd7e75ce-image.png

    getBoundingClientRect() does not adjust the code element's rectangle for the fact that the pre is clipping it into a scrolling container.



  • @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    First of all, border is complicated. Using outline is better. When you change borders, things tend to move.

    Yes I know.

    ... You wrote a lot of paragraphs about something I already knew.

    @anotherusername said in Blakeyrat's JavaScript Is Rusty Thread:

    here's an example of what I'm talking about that demonstrates both the problem of it moving (when you use border) and it being clipped (by its parent element).

    Then you wrote a second post about something I already knew, sheesh. I KNOW! Why did you even think I didn't know that adding a border would reflow the page? Christ.


  • đźš˝ Regular

    @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    Problem is: there's no way to get the cursor location without capturing an event? So you can't wire this thing up on a timer. WTF DOM. You find something helpful, then find it's crippled by an obvious lack. Every fucking time.

    FWIW, this is working for me:

    overlay.addEventListener('click', function(ev){
    	console.info('Clicked overlay');
    	var parentNode = overlay.parentNode;
    	parentNode.removeChild(overlay);
    	var target = document.elementFromPoint(ev.clientX, ev.clientY);
    	console.debug('Found', target, 'at', ev.clientX, ',', ev.clientY);
    	parentNode.appendChild(overlay);
    }, false);
    


  • @zecc ehh... yeah, that works, but I feel like it's less hacky to just let clicks go through the overlay, and capture them on the document.body. Then the event's target is automatically included.

    Also, both methods could break if document.body has another capturing event handler for the events that was added by the page's scripts (your overlay div would break; it won't even see them if they're captured above it... my method would break if they're captured by the other event handler and that event handler happens to run first and it calls stopImmediatePropagation). So it doesn't really gain robustness for being hacky.


  • Winner of the 2016 Presidential Election

    @blakeyrat said in Blakeyrat's JavaScript Is Rusty Thread:

    Weird; so it's basically a bool that says "for only this event, ignore the normal event bubbling process and put me at the head of the line"?

    Nope. Events are always captured from the root element down, and then bubble up again. You're not ignoring the normal event bubbling process, you're simply telling the browser to execute your handler in the first phase instead of the second.



  • @blakeyrat This seems to be doing the thing you want:

    http://jsfiddle.net/dixalex/mngtozwg/14/

    Found on:

    Looks hacky


Log in to reply