Detect change to element id=ASIN when Ajax is making changes - javascript

This question is more of a general coding practice question. I am writing an extension for Google Chrome that gathers the ASIN number from Amazon.com when viewing an item page.
Design requirements:
When viewing a page that contains an element with id=ASIN, capture the ASIN. (E.g. B004FYJFNA from http://www.amazon.com/gp/product/B004FYJFNA/?tag=justinreinhart-20 )
When user changes platforms (e.g. from Playstation 3 to Xbox 360), detect that a change has occurred and capture the new ASIN value.
I have a "content script", injection.js, that is injected on every amazon page and can successfully perform requirement #1.
The issue I have is with #2. I am not able to efficiently detect a change to the ASIN value. Either the code doesn't fire OR I pick an element that fires ~100 times. I am at a loss how to do this efficiently.
Failure examples:
// (A) This fires ~100 times when user changes platforms,
// and also fires during mouseover events.
// Unacceptable but it does work.
$("#handleBuy").bind('DOMNodeRemoved', OnProductChange);
// (B) This doesn't fire at all. I have a few guesses why but no certainties.
$("#ASIN").on('change', OnProductChange);
Blathering:
Switching product platforms when the user clicks seems to tear the Amazon page apart and it destroys any event binding that I attempt. (I believe the element is removed and reinserted--not just changed.) I do not know javascript well enough to skillfully take these massive DOM changes into account.
Your help and knowledge is appreciated.

Related

How to update a web page javascript counter live when the browser doesn't have focus?

I am making a browser game in html, css, and javascript, written in perl. Health and stamina are kept in the server and I use javascript to show the user a live updated count of these stats while the current page is loaded. This works fine, however if the user switches tabs or switches away from the browser and leaves it running in the background, the count value you see when you return does not keep up properly. So when you switch back to the browser, your counter might say 50/100 stamina when you actually have 100/100. So when you do something in the game (loads a new page) the server updates the counter to the true amount because the javascript is just keeping time to show the user a "live" rolling view in the browser.
Is there a way to ensure the javascript counter will continue to function even if the page/tab isn't active or on the forefront? Aside from completely re-writing my game to include continuous live server pushes in what is displayed on the browser to the user?
Say you are playing the game. You see your health and stamina regenerating. You switch to another program for a minute, then return to the game in the browser. You notice your health and stamina have not updated while you were away. But when you perform an action in the game, this value is updated to what it should be because it is tracked internally on the server. This is what I would like to fix. Hope that makes sense!
I have not tried anything to fix this issue yet besides searching the web and ending up on this site without a really "good" answer in sight, so I decided to ask the question.
Continuous server pushes wouldn't work either. Anything in the main event loop like a timer, or events happening when it's out of focus, gets slowed down by the browser to conserve resources. Some mobile browsers will stop it together.
The answer to the question is to change how your app keeps track of these stats.
Now some will say to use WebWorkers to run the timer in a separate thread but this won't solve all your issues. You'd still have a different version of the issue, like if someone restored your webpage from sleep or something along those lines. No background task can survive that.
You mention that you track these stats also on the server. That's convenient, so the most obvious thing you should do is detect when the tab comes back into focus using the Window focus event. You would then make all the calls to the server to fetch the most up-to-date stats and reset the timers based on that fresh data. To stop it from showing stale data while the request is in flight, you might choose to show a loading spinner or something during that period.
Another common way of fixing this is you keep around on each timer increment a var which says when the data last came back (a timestamp). When you leave focus, you detect this with the blur event and store that last timestamp somewhere. Then they come back into focus, you handle the focus event and calculate the difference between the current time and the last recorded time before defocus (blur). You may be able to recalculate from this period what the values should be.
But if your server has this info, it'd be far less error-prone and easy to just ask the server when they refocus.

How do I locate the function that is stealing DOM focus?

I'm trying to debug the integration between my app and Stripe's Elements component library. Everything works fine in sandbox mode, but we ran into a problem on production in the 3D Secure authentication process. This involves loading an iframe, into our app, that contains a form from the credit card's issuer (usually via a technology partner, like Arcot).
The form loads correctly and its buttons are working as expected, but the element (for a SMS one time code) is not behaving. Every time I click on the input, something is immediately pushing the focus back to the element of the iframe. This makes it impossible to type anything in, since by the time I touch a key, the input is not in focus. For reference, it is possible to change the input's value using document.getElementById('enterPIN').value = '123456';
I'm not sure if my app is triggering focus() calls (I don't think so) or if it is some part of the iframe code or even Stripe's. Is there a good way to monitor DOM events and do a stack trace for the trigger of each one?
I tried two tactics. Neither gave an obvious answer, but they did point my search in the right direction.
I opened the Event Listeners panel (in the Elements tab of my browser's developer tools) and removed everything I could find, but it seems that this doesn't actually change the behavior of the page- focus kept being stolen away. Luckily, I also noticed some listeners that were defined by the Material UI library.
I used monitorEvents() to get a few more details, but the src & target values were not much help and event.relatedTarget was always null.
In the end, I found this discussion and realized that my MUI Dialog component was stealing focus whenever I clicked on the iframe triggered by its content. This was easily fixed by adding the disableEnforceFocus attribute.

Monitor which javascript variable changes on a user action

I have a large existing web app with a lot of javascript that I didn't write.
On this web app, a user action is performed in the browser (clicking on a link).
I need to see which variable(s) change(s) on click.
Using the watch pane in sources in the dev tools is not effective, because there are thousands of variables and I need to find the one that changes. I do not want to view all variables, only the one that changes. The script is very large and complex, following the event listener might not be feasible.
If you use Google Chrome, you can use the devtools, go to the Sources panel. Then if you look at the right side, you will see a column with "Watch", "Call Stack", etc... Expand the "Event Listener Breakpoints" part, then the "Mouse" category, and tick the "Click" checkbox.
Now Chrome will break (start a debugging session) at the click listener. You can now go step by step to see all the variables modifications, and their values.

How does HotJar generate their recordings?

Tracking mouse movement/scroll/click events is easy but how do they save the screen and keep it in sync so well?
The pages are rendered very quite well (at least for static HTML pages, haven't tested on Angular or any SPA), the sync is almost perfect.
To generate and upload a 23fps recording of my screen (1920x1080) it would take about 2Mbps of bandwidth. Maybe when recording only when there are some mouse events it would still take some 300-500Kbps on average? That seems way too much...
HTML content and DOM changes get pumped through a websocket and stored by Hotjar (minus sensitive information such as form inputs from the user, unless you've whitelisted them), the CSS isn't stored (it gets loaded by you when you watch the recording).
Because they're only recording user activity and DOM changes, there's a lot less data to record than if they were capturing a full video. The downside is that some Javascript driven widgets won't function correctly in the replay.
Relevant information from Hotjar docs:
When it comes to recordings, changes to the page are captured using the MutationObserver API which is built-in into every modern browser.
This makes it efficient since the change itself is already happening
on the page and the browser MutationObserver API allows us to record
this change which we then parse and also send through the websocket.
At regular short intervals, every 100ms or 10 times per second, the cursor position and scroll position are recorded. Clicks are recorded
when they happen, capturing the position of the cursor relative to the
element being clicked. These are functions which in no way hinder a
user's experience as they only capture the location of the pointer
when a click happens or every 100ms. The events are sent to the Hotjar
servers through frames within the websocket, which is more efficient
than sending XHR requests at regular intervals.
Source: https://help.hotjar.com/hc/en-us/articles/115009335727-Will-Hotjar-Slow-Down-My-Site-

How to i stop clients using firefox's search box showing up when playing my HTML5 game with WASD?

I have a question thats semi-related to this question, except for instead of it being from the end-user perspective i need it from the content providers perspective.
I would be surprised if the mozilla foundation would have introduced this semi-intrusive feature with no way of it being disabled for selected content.
I have a web page that consists of nothing but a canvas element which is drawn to via javascript creating a game for the user to play. When a user uses the control keys (W, A, S & D) FireFox sees the user is not in some form of input box and decides they must be wanting to search for something of the page (opening the ctrl+f search box), forcing the user to lose focus on the game and their following key-presses to go unregistered. This will pose a problem for non-technical users who do not know where the setting to turn this off is, and in turn they will probably blame it on the content itself rather than it being the browser. Other than creating a input off the page that the user is force-focused to, is there a way of disabling this while FireFox users are visiting my page?
After your event is handled just terminate it.
Example:
function handleDirectionalKeys(ev) {
// .. Your WASD code
ev.preventDefault();
ev.stopPropagation(); // May not be needed, test it yourself
return false;
}
Optionally you can cancel the event when it reaches the top level of the DOM hierachy:
$(window).keypress(function(e)
{
// At this point you need to make sure that the key press
// was already handled by your code
e.preventDefault();
}

Categories

Resources