Constantly running javascript? - javascript

How can I have my javascript code constantly run? The situation is that I want some page elements to be resized when the page resizes. I'm thinking that the way to do this would be to have some javascript code that constantly runs, and whenever the page size changes, it resizes that element.
I tried doing this with setTimeout() and a really small value, but it didn't seem to work.

JavaScript is an Event based language, that is you add event listeners to things and then a function is called when that event occurs. This saves you from having a loop run continuously to to check the state of an item.
The window supports onResize in JavaScript, so for example:
window.addEventListener("resize", function(event){
alert("you just resized the window. If you inspect the event variable you will find some usefull details");
}, false);

http://www.quirksmode.org/dom/events/index.html#t020
You should hook your script to the resize event

I would look at a framework like jquery where you can register a function with a page event.
$('body').resize(function() { ... });
By running the javascript all the time, you run the risk of really bogging down a cpu (especially on single core systems) and really slowing down the browser.

Related

How can I temporarily disable a javascript event listener I didn't add?

I'm using Adobe Animate to create an HTML5 menu.
When you export a project, it adds a bunch of javascript to the resulting HTML file based on the settings you chose in Animate.
For my project, I need it to be responsive, so I check the Responsive setting in Adobe Animate. This adds code that looks like this to my resulting HTML file:
AdobeAn.makeResponsive(true,'both',false,1,[canvas,anim_container,dom_overlay_container]);
...
an.makeResponsive = function(isResp, respDim, isScale, scaleType, domContainers) {
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
function resizeCanvas() {
// Code to resize the canvas
}
...
}
So it's basically adding an event listener to the window object for the 'resize' event.
What I want to do is have the ability to disable the responsiveness at runtime.
It seems like that would be easy to do with something like:
window.removeEventListener('resize', resizeCanvas);
and re-add it with:
window.addEventListener('resize', resizeCanvas);
but the problem is that my code, which follows all the adobe code, doesn't have a reference to the resizeCanvas function. Apparently, without a reference to it, it's not possible to remove the event listener from window, or to even list the event listeners currently attached to window.
I could manually modify the code that Adobe generates, and add a global variable with a reference to resizeCanvas that I can use, but if I do that, then every single time I make a change to my Adobe Animate project, and publish (generate the output html), I'll need to go in and modify that code, by hand, in the resulting file, which is impractical. Even if I make a script that does this, Adobe Animate doesn't have a way to run a script on Publish, so I'll have to remember to run it every single time I publish.
Is there any way for me to either remove the resize listener from window without having a reference to resizeCanvas, or to somehow list the event listeners attached to window so I can get a reference to resizeCanvas?
Failing that, are there any other JS tricks I can use to make this work?
I can add JS code before Adobe's code, or after, (because I can modify the HTML template that's used to generate the resulting file) but not modify their code directly.
The problem is you do not have a reference to the resizeCanvas function, it is defined inside the closure of the makeResponsive function.
This answer here How to find event listeners on a DOM node when debugging or from the JavaScript code? does give a away of hacking into the add addEventListener method that creates a way of access the events.
Smells a bit funky to me but might give you what you want.

Avoiding a freeze when executing all javascript functions onDomReady / onDomLoaded

So I want to migrate all my javascript functions to requireJS and will try to use as much as possible the ondomready event. BUT:
this will freeze the browser, since all javascript is synchronously. This is bad. I mean wow the user sees the browser content a bit faster, but is going to try to click somewhere just to realize the browser was frozen, and has to click again. This is very bad. Is there a way around this?
Patient: It hurts when I do this.
Doctor: Then don't do that.
If you see freezing on the dom ready event then perhaps you are trying to do too much. Executing javascript is quick. Doing a page redraw is slow.
Rather than lots of small events that each make changes to the dom and each cause a page redraw you should have one function that processes a list of changes that need to be made. This is what the domReady plugin does before the ready event. After the ready event it just runs them as it receives it which could cause multiple redraws.
I learnt this while writing my own animation library. I was using individual setInterval()'s to change a single property. When doing more that four a once the animation was no longer smooth. A better way to do this is a single interval that processes a list of changes that need to be made.
Edit:
Instead of using domReady as a plugin require(["domReady!"], use it as a module so that you can run initialisation code straight away then make changes to the dom later.
require(["domReady"], function(domReady) {
var element = document.createElement('table');
//more setup code
domReady(function(){
document.body.appendChild(element);
});
});

Detect JavaScript initiated change on a JavaScript created object

I have a TEXTAREA that is created through an external JavaScript. I am writing new script to detect when the contents are changed. DOM events like "change" and "blur" do not work, since the change is initiated by the other script. I do not have the ability to read/modify the external script.
Any ideas?
If you want full cross-browser support, you will simply have to set up a polling interval and compare the contents each time to what you saw the last time. DOM mutation events aren't going to cut it.
Have fun.

Unbind inline javascript events from HTML elements in memory

How do I completely unbind inline javascript events from their HTML elements?
I've tried:
undelegating the event from the body element
unbinding the event from the element
and even removing the event attribute from the HTML element
To my surprise at least, only removing the onchange attribute (.removeAttr('onchange')) was able to prevent the event from firing again.
<input type="text" onchange="validateString(this)"></input>
I know this is possible with delegates and that's probably the best way to go, but just play along here. This example is purely hypothetical just for the sake of proposing the question.
So the hypothetical situation is this:
I'm writing a javascript validation library that has javascript events tied to input fields via inline HTML attributes like so:
<input type="text" onchange="validateString(this)"></input>
But, I'd like to make the library a little better by unbinding my events, so that people working with this library in a single-page application don't have to manage my event handlers and so that they don't have to clutter their code at all by wiring up input events to functions in my hypothetical validation library... whatever. None of that's true, but it seems like a decent usecase.
Here's the "sample" code of Hypothetical Validation Library.js:
http://jsfiddle.net/CoryDanielson/jwTTf/
To test, just type in the textbox and then click elsewhere to fire the change event. Do this with the web inspector open and recording on the Timeline tab. Highlight the region of the timeline that correlates to when you've fired the change event (fire the change event multiple times) and you'll see the event listeners (in the window below) increase by 100 on each change event. If managed & removed properly, each event listener would be properly removed before rendering a new input, but I have not found a way to properly do that with inline javascript events.
What that code does is this:
onChange, the input element triggers a validation function
That function validates the input and colors the border if successful
Then after 1 second (to demonstrate the memory leak) the input element is replaced with identical HTML 100 times in a row without unbinding the change event (because I don't know how to do that.. that's the problem here). This simulates changing the view within a single-page app. This creates 100 new eventListeners in the DOM, which is visible through the web inspector.
Interesting Note. $('input').removeAttr('onchange'); will actually prevent the onchange event from being fired in the future, but does not garbage collect the eventListener/DOM stuff that is visible in the web inspector.
This screenshot is after change event fires 3 times. Each time, 100 new DOM nodes are rendered with identical HTML and I've attempted to unbind the onchange event from each node before replacing the HTML.
Update: I came back to this question and just did a quick little test using the JSFiddle to make sure that the answer was valid. I ran the 'test' dozens of times and then waited -- sure enough, the GC came through and took care of business.
I don't think you have anything to worry about. Although the memory can no longer be referenced and will eventually be garbage collected, it still shows up in the Web Inspector memory window. The memory will be garbage collected when the GC decides to garbage collect it (e.g., when the browser is low on memory or after some fixed time). The details are up to the GC implementer. You can verify this by just clicking the "Collect Garbage" button at the bottom of the Web Insepctor window. I'm running Chrome 23 and after I enter text in your validation box about 5 or 6 times, the memory usage comes crashing down, apparently due to garbage collection.
This phenomenon is not specific to inline events. I saw a similar pattern just by repeatedly allocating a large array and then overwriting the reference to that large array, leaving lots of orphaned memory for GC. Memory ramps up for a while, then the GC kicks in and does its job.
My first sggestion would have been to use off('change') but it seems you've already tried that. It's possible that the reason it's not working is because the handler wasn't attached with .on('change'). I don't know too much about how jQuery handles listener like this internally, but try attaching with .on('change', function ()... or .bind('change', function ()... instead.

Cannot listen document resize event

I want to listen the event whenever the document(body) size changed
which would caused by anything inside
(but you are assumed do not know what element caused the resize)
as the code below:
http://jsfiddle.net/marstone/7zaRT/8/
you can click the green area to change the div size, then the document.body resized.
however, the onresize event won't be fired.
I found that it only works when the window resizes, such as drag/maximum the browser window
any workaround? any help appreciated.
Resize events are available only on windows objects, as you said. You can use the jquery-resize plugin to add resize events on DOM elements, but be advice that they implement polling mechanisms to keep track of element's sizes. Due to that, you must always bind the event to the element you want to watch (delegate does not work as no real event is bubbled on the DOM).
So far I've used that plugin a couple of times, without any glitch. I'm not aware if other plugins implement this very same mechanism, but I'm somewhat sure that they all rely on a polling mechanism as this one.
This should do the trick:
$(document).bind('DOMSubtreeModified', function(e) {
alert("Bazinga!");
console.log(e);
​});​
Note however, that it tends to fire excessively, but I'll leave it to you to figure the how this could fit into your app.
http://jsfiddle.net/pratik136/7zaRT/12/

Categories

Resources