I wanted to add the resize event to an element (I know you can't add resize to a specific element, but it would be fine if the JS-function would be triggered on a resize of any kind - not the specific element).
I was thinking about this:
<div onresize="wrapperResize();"></div>
This somehow doesn't work (Safari user here). This however works:
<div onclick="wrapperResize();"></div>
Currently wrapperResize() only holds a simple console.log(). What could I do about this?
PS: This works great (traditional checked), what do I even do different?
EXTRA: The div has a fixed height and 33% of the body element wide. Even though the event should fire, when the window is resized I thought this may be the cause.
I think you should set onresize handler on window and do it in javascript, not inline html.. Like so
window.onresize = yourFunction
You cannot attach a onresize event on a <div> container. It is only available for window for most of the browsers.
Related
Consider the following Web page:
<html>
<body onscroll="alert('body scroll event')">
<div style='width:200px;height:200px;overflow:auto' onscroll="alert('div scroll event')">
<div style='height:400px'>
</div>
</div>
</body>
</html>
This html creates a div with a scrollbar. If you move the scrollbar, the onscroll event on the div element is triggered. However, the onscroll event on the body is NOT fired. This is expected, since the W3C states that element onscroll events do not "bubble".
However, I'm developing a client-side web framework that needs to know any time a scroll bar on ANY element of the page is scrolled. This would be easy to do if onscroll bubbled, but unfortunately it does not. Is there any other way to detect onscroll events across an entire page? (Right now I'm focusing mainly on Webkit, so a Webkit-specific solution would be fine...)
Here are some things I've tried:
Capturing DOMAttrModified (doesn't seem to fire for moving scrollbars.)
Using DOM Observers (also don't seem to fire for scrollbars)
Changing the onscroll event type to bubble (seems to not be possible)
It seems the ONLY way to capture onscroll events globally is to attach an onscroll event to EVERY element that may scroll, which is very ugly and is going to hurt the performance of my framework.
Anyone know a better way?
The simplest way to detect all scroll events in modern browser would be using 'capturing' rather than 'bubbling' when attaching the event:
window.addEventListener('scroll', function(){ code goes here }, true)
Unfortunately as I am aware there is no equivalent in older browser such as <= IE8
I had this same issue.
The easiest way of course is to use jQuery. Be aware that this method could potentially slow down your page significantly. Also it will not account for any new elements that are added after the event is bound.
$("*").scroll(function(e) {
// Handle scroll event
});
In vanilla JavaScript, you can set the useCapture boolean to true on your addEventListener call, and it will fire on all elements, including those added dynamically.
document.addEventListener('scroll', function(e) {
// Handle scroll event
}, true);
Note though that this will fire before the scroll event actually happens. As I understand it, there's two phases events go through. The capture phase happens first, and starts from the page root (ownerDocument?) and traverses down to the element where the event happened. After this comes the bubbling phase, which traverses from the element back up to the root.
Some quick testing too showed that this may be how jQuery handles it (for tracking scrolls on all page elements at least), but I'm not 100% sure.
Here's a JSFiddle showing the vanilla JavaScript method http://jsfiddle.net/0qpq8pcf/
*...crickets chirping... *
OK, I guess this question isn't going to get any stackoverflow love, so I might as well answer my own question as to the best solution I've found so far, in case another user stumbles across this question:
The best solution I've come up with is to capture "onmousedown" and "onkeydown" for the BODY element: These events bubble, and so if a user tries to move a scrollbar on the page these global functions will fire as a by-product. Then, in these functions, simply look up event.target and attach a temporary "onscroll" event to those objects until the mouse/key is "up" again. Using that method, you can avoid "handler bloat" and still globally capture all "onscroll" events. (I think this will work for "mouse wheel" scrolling as well, but my research on that final wrinkle is still pending.)
The following works fine when you want to i.e. close a dialog after anything in the background is scrolled:
var scrollListener = function(e) {
// TODO: hide dialog
document.removeEventListener('scroll', scrollListener, true);
};
document.addEventListener('scroll', scrollListener, true);
I needed to handle scrolling in any context in a complex of custom elements with scroll events in shadowRoots. This covers at least part of the problem in my scenario and generally borrows from the answers and comments here in the context of these newer web component APIs. Attaching and detaching the listener in the appropriate lifecycle callbacks works well so-far (once might not fit your use-case).
self.addEventListener('mousewheel', handler, {capture: true, once: true});
self.addEventListener('keydown', handler, {capture: true, once: true});
Note too the event.composedPath() provides the entire event path through all the shadowRoots with all the nodes if specifics about the scrolling context are needed. If this is the case it might make sense to use this approach and attach a new handler for that specific scenario--to the node of interest.
Like drcode said, capture on body tag is the trick. I just add touchmove to work on mobile.
document
.querySelector("body")
.addEventListener("mousewheel", e => {
console.log("scroll");
});
document
.querySelector("body")
.addEventListener("touchmove", e => {
console.log("scroll");
});
Regards,
I would like to design something similar to what can be seen on http://www.thedana.com/ by the "Check availability" button - I've used the jquery.js file from w3school.com and got the following so far: http://quaaoutlodge.com/drupal-7.14/ (Book Now tab). Now as you realize, it is very touchy and fades out sometimes when it shouldn't (when the cursor is still in the middle of the field) how can I make this nicer, more user friendly?
Thanks!
Ron
Update:
I tried to implement that but it doesn't quite work as I would like to show my "fade" div upon hovering over "book" and keep it up as the cursor moves down, over "fade" how do I accomplish this?
Url:http://quaaoutlodge.com/drupal-7.14/
Put the div#fade inside of the div#book, that will solve half of your problems. You will have to adapt the CSS as well for this change.
Another very important point to learners is that jQuery provides unobtrusive cross-browser event listeners attaching. That means, inline JS in the html as onmouseenter="handler()" is not just unnecessary and technically ugly - mixed structure with behavior -, it also pollutes the global scope with function names.
That's one of the reasons people advertise against W3School.
But back on topic here's a solution using the DOM Ready handler and a hover one:
Fiddle
HTML
<div id="book">
Book Now
<div id="fade">TEST</div>
</div>
JS
$(function() {
var fade = $('#fade');
$('#book').hover(function() {
fade.fadeIn();
}, function() {
fade.fadeOut();
});
});
Again, you will have to rework the CSS removing the position:absolute and margins from #fade.
Can you try with jquery's .mouseleave instead of the generic onmouseout?
http://api.jquery.com/mouseleave/
"The mouseleave event differs from mouseout in the way it handles event bubbling. If mouseout were used in this example, then when the mouse pointer moved out of the Inner element, the handler would be triggered. This is usually undesirable behavior. The mouseleave event, on the other hand, only triggers its handler when the mouse leaves the element it is bound to, not a descendant. So in this example, the handler is triggered when the mouse leaves the Outer element, but not the Inner element."
I have a tree that expands and collapses, whenever the container div changes sizes i want to do some other stuff, however the .resize() doesn't seem to be working as i wish.
I have the code posted on jsfiddle below:
http://jsfiddle.net/2nXtu/
Thanks
resize() is an event for the resizing of the browser window.
Just put the status updater inside the duplication click event:
$('.dup').live('click', function(){
var clone = $(this).clone();
$(this).parent().append( clone );
$('.height').html( $('.content-body').height() );
$('.status').html('Resizing');
});
Here it is in action.
One way I did this is using a dirty-checking technique.
Basically you check the size of the div you want to monitor the first time, then register a function that runs on a specified interval (say 500ms) and checks for the div size again. If the size has changed from the one you had before you trig some event or run some function and store the new size. It works well if you create efficient closures around your variables.
I have a silly (and hopefully easily fixed) problem, which I will now attempt to describe.
The scenario-> I am trying to create a context menu using HTML / CSS / JS. Just a DIV with a high z-order that appears where a user right-clicks. Simple, and that portion works. The portion which does not is my attempt to make the menu disappear if the user clicks somewhere where a context menu is not supported; I am attempting to achieve this end with a general function in the BODY tag that fires onclick. Since the BODY tag is given a z-order of -1, and any other tags which might trigger the context menu to appear are given a higher z-order value, my hope was that if I right-clicked an element with a z-order of, say, 3, then it would fire the showMenu() function; instead, it appears that it does this, as well as passes the event to the underlying BODY tag, which causes the menu to become hidden again.
As you might imagine, it is incredibly frustrating. Does anyone know how to make prevent events from being passed down? (The INPUT button is what you may want to look at, the A anchor is something similar, but not coded to work just yet).
Here's the HTML code:
http://pastebin.com/YeTxdHYq
And here's my CSS file:
http://pastebin.com/5hNjF99p
This appears to be a problem with IE, Firefox, and Chrome.
A lot of DOM events "bubble" from the bottom object up through container objects, which means they'll eventually reach the body. But you can stop this - try adding the following code to the click handler on your element:
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
...where e is the variable you already have in your function representing the event object.
event.stopPropagation(); should work in modern browsers, but the old IE way was event.cancelBubble = true; - to be safe you can just do both (but as shown above check that .stopPropagation is defined before trying to call it).
With the above code added, if you click on the element your function will stop container objects (include the body) from seeing the click. If you click somewhere else your function isn't called so then the body will process the click.
There's more info about this at MDN and QuirksMode.org.
Note: I've ignored the z-order issue because in this case I think it is a non-issue - all elements are descendents of the body so (unless you stop it) I would expect events to bubble to the body regardless of z-order.
function appFocus() {
write("FOCUSED"); // write on the screen
}
appWin.addEventListener("focus", appFocus, false);
// appWin is my window
This same code works well with other windows
other listeners works well with this window
so, why specifically the focus event does not work with just this window? Please, share your thoughts.
Found it:
I have a window with an "onload" that focus the browser within the window. By removing this onload I get the "onfocus" event to work.