Is there a way to detect when the appearance of the document has changed? For example:
$(document).on('change??', function () {
console.log('My aspect has changed');
});
// changes the appearance of a particular div
$('#my-div').css({width: 320, height: 240});
Also, is there a kind of 'render' event? This event would be fired every time the browser redraws the page. For example:
$(document).on('render', function () {
console.log('The page has been redrawn');
});
Don't know of any event like that, but if you are in control of all the changes you can easily cause your own events.
Here is a simple JQuery based example to illustrate the idea.
$( "#test" ).on( "mysitechanged", function( event, param1, param2 ) {
alert( 'changed' );
});
$( "#test").trigger( "mysitechanged", [ "Custom", "Event" ] );
http://api.jquery.com/trigger/
Here is info on how to do it in pure JavaScript
How to trigger event in JavaScript?
Since i think you're trying to detect whether the aspect has changed or not, this is what you're looking for.
window.onresize = function(){
// your code goes here;
}
Here is a good example of how the window.resize event is handled: http://jsfiddle.net/CoryDanielson/LAF4G/
I am on the lookout for that too. Apparently not. However it should be possible to implement one.
As far as I know, for the document to change appearance, one of the following is true:
The DOM has changed
The viewport changed (resize, orientation change, media changed, etc.)
You can detect changes to the DOM using MutationObserver, and detect viewport changes using native JavaScript events (onresize, etc.).
I am not sure whether this is necessary or useful (events should cover all realistic cases), but window.matchMedia(media).addListener() will also notify you about media changes to the viewport.
A DOM or viewport change does not necessarily imply a change of appearance, so then you should do some measurements on the page to verify whether anything changed.
More realistically and pragmatically, assuming that you build the page or app, you should be able to predict what would cause a change of appearance (ex: new content loaded through ajax, the user typed something in or clicked a button, new message received, page resized, etc.) and watch for these actions instead.
Related
Background:
I'm writing a component that opens up a sub-menu on click. I can't know where this component will be placed on the page or how far it will be nested in areas that may have the overflow property set.
Given that the overflow may clip the sub-menu I am instead making the sub-menu itself be attached to the body giving it an absolute position and linking it via code to the original component. This takes care of the overflow issue.
Problem:
However if a user scrolls the sub-menu remains in place, rather than moving with its linked component, so I need to be able to listen to any and all scroll events that occur on the page so I can reposition the sub-menu appropriately.
If there's an easy way to listen to all scroll events or if there's another better way to do this component I would appreciate any input.
I've played around with JSFiddle and set up a sandbox but I haven't had any success nor have I found an answer on this site or anywhere else for that matter; though perhaps I was using the wrong search terms, I can't imagine that I'm the first to have this question.
EDIT
To address the close vote, I'm not asking help to debug an issue without providing code nor am I asking something that won't help anyone in the future. I'm asking how I would go about listening to all event of a certain type not matter where the may occur, which I find globally applicable, though perhaps that's subjective.
EDIT
$(window).on('scroll', function(){ /**/ });
is not an option as it only listens to the window scroll, not any nested scrolls.
$('#ex1 #ex2').on('scroll', function(){ /**/ }); is not an option as it requires the person who is implementing the code to be aware of any current or possible future areas on the page that may scroll.
You should be able to attach a document-level listener with a third parameter of true to capture the scroll events on all elements. Here's what that looks like:
document.addEventListener('scroll', function(e){ }, true);
The true at the end is the important part, it tells the browser to capture the event on dispatch, even if that event does not normally bubble, like change, focus, and scroll.
Here's an example: http://jsbin.com/sayejefobe/1/edit?html,js,console,output
You need to see whether scroll is happening to window level or to an element level. Usually in your case '*' should suffice.
$('*').scroll(function() {
alert('scroll');
});
Here is updated link: http://jsfiddle.net/wAadt/1
How about listing on all elements and the window?
$('*').add(window).scroll(function() {
console.log('scroll');
});
The best way to do it would be to find out which elements are scrollable, then attach listeners to them. You could run this function on any page change to make sure you've always got all the scrollables.
This is a benefit over using listeners on every element (as the other solutions would do) in terms of performance: every time the page updates so do the listeners. With lots, this quickly affects performance and memory use.
The updated fiddle: http://jsfiddle.net/ArtOfCode/wAadt/8/
The code:
$("*").each(function() {
if($(this).css("overflow") == "auto" || $(this).css("overflow") == "scroll") {
$(this).scroll(function() {
console.log("scroll");
});
}
});
(thanks to #pebbl for the help)
You could then wrap this in a function and run it on change:
function addListeners() {
$("*").each(function() {
if($(this).css("overflow") == "auto" || $(this).css("overflow") == "scroll") {
$(this).css('border', '1px solid red').scroll(function() {
console.log("scroll");
});
}
});
}
$("body").on("change",function()
addListeners();
}
Admittedly it is a bit convoluted but it addresses the issue with as few event listeners as possible.
im seeing $( window ).on( 'orientationchange') firing on desktop on Chrome , is that expected behaviour or does that mean some other part of the code im working with is actually dispatching this event?
As far as I can tell the javascript is only detecting when the height grows greater than the width and vice versa. So when you change your browser size to a height > width it will launch the event. This seems to be the expected behavior of the function, I am not sure how to circumvent that for your use.
EDIT: I found that when you check the window.orientation property when the event is fired you can see that it is still set to landscape. Maybe try filtering your landscape only code by putting it inside an if statement? See http://jsfiddle.net/sJ9Hx/2/
$(window).on('orientationchange', function (e) {
if(window.orientation == 0){
alert("Portrait");
}
else{
alert("Landscape");
}
});
The orientation changes when the height and width values are altered!
Lets say when 840x600 becomes 600x840 you can say that the device's orientation has changed. That way the OS would detect and would execute the co-responding function. But wait, there are many other methods of detecting that, using sensors too!
If you're getting that this event is getting executed, then of-course there is some sort of JS file there! Which is causing this event. For this, you need to check the JavaScript code and see how it detects the orientation change and then do what so ever action regarding that!
So I used this totally awesome tool called Visual Event, which shows all the event handlers bound to an object - and I noticed that every time I clicked or played around with my object and checked the list of event handlers bound to it, there were and more every time. My problem is this one: console.trace or stack trace to pinpiont the source of a bug in javascript? After using Visual Event and someone else's suggestion, I'm thinking my problem is that I'm probably binding the same handlers to the same events over and over again. Is there a way to unbind things regularly?
My application has a bunch of plugins connect to dynamically created divs. These divs can be resized and moved around the place. The application is a kind of editor, so users arrange these divs (which contain either images or text) in any design they like. If the user clicks on a div, it becomes "activated", while all other divs on the page get "deactivated". I have a bunch of related plugins, like activateTextBox, initTextBox, deactivateTextBox, readyTextBox, and so on. Whenever a div is first created, the init plugin is called once, just the first time after creation, like so:
$(mydiv).initTextBox();
But readyTextBox and activateTextBox and deactivateTextBox are called often, depending on other user events.
In init, I first use bind things like resizable() and draggable(), then I make the box "ready" for use
$.fn.extend({
initTextBox: function(){
return this.each(function() {
// lots of code that's irrelevant to this question
$this.mouseenter(function(){
if(!$this.hasClass('activated'))
$this.readyTextBox();
}
$this.mouseleave(function(){
if($this.hasClass('ready')){
$this.deactivateTextBox();
$this.click(function(e){
e.preventDefault();
});
}
});
});
});
Here's a simplified summary version of the readyTextBox plugin:
(function($){
$.fn.extend({
readyTextBox: function(){
return this.each(function() {
// lots of code that's irrelevant to this question
$this.resizable({ handles: 'all', alsoResize: img_id});
$this.draggable('enable');
$this.on( "dragstop", function( event, ui )
{/* some function */ });
$this.on("resizestop", function( event, ui ){ /* another function */ });
// and so on
});
Then there's activateTextBox():
$.fn.extend({
activateTextBox: function(){
return this.each(function() {
// lots of code that's irrelevant to this question
$this.resizable('option','disabled',true); //switch of resize & drag
$this.draggable('option', 'disabled', true);
});
Then deactivate, where I turn on draggable and resizable again, using the code:
$this.draggable('enable'); $this.resizable('option','disabled',false);
These divs, or "textboxes" are contained within a bigger div called content, and this is the click code I have in content:
$content.click(function(e){
//some irrelevant code
if( /* condition to decide if a textbox is clicked */)
{ $(".textbox").each(function(){ //deactivate all except this
if($(this).attr('id') != $eparent.attr('id'))
$(this).deactivateTextBox();
});
// now activate this particular textbox
$eparent.activateTextBox();
}
});
This is pretty much the relevant code related to text boxes. Why is it that whenever I drag something around and then check Visual Event, there are more clicks and dragstops and mouseovers than before? Also, the more user interacts with the page, the longer the events take to complete. For example, I mouseout from a div, but the move cursor takes a loooong time to get back to default. I quit dragging, but everything gets stuck for a while before getting ready to take more user clicks, etc. So I'm guessing the problem has to be that I'm binding too many things to the same events need to be unbinding at some point? It gets so bad that draggable eventually stops working at some point. The textboxes just get stuck - they're still able to be resized, but dragging stops working.
Am I binding events over and over
Yes. Have a look at your code:
$this.mouseenter(function(){
…
$this.mouseleave(function(){
…
$this.click(function(e){
…
});
});
});
That means every time you mouseover the element, you add another leave handler. And when you leave the element, every of those handlers adds another click event.
I'm not sure what you want to do, but there are several options:
bind the event handlers only once, and keep track of the current state with boolean variables etc.
before binding, remove all other event handlers that are already bound. jQuery's event namespacing can help you to remove only those which your own plugin added.
use the one() method that automatically unbinds a listener after firing it.
This question already has answers here:
How to detect DIV's dimension changed?
(28 answers)
Closed 7 years ago.
I have a very simple question, or at least it seems that way.
I have a DIV element which will be resized at one moment. I want to be able to capture the resizing moment.
Something like this:
function myFunction(){
alert('The DIV was resized');
}
divElement.addEventListener("resize", myFunction, false);
Does anyone know the answer?
Thanks
As of December 2011, there's no built-in event to detect when a div resizes, just when a window resizes.
Check out this related question: Detecting when a div's height changes using jQuery, and this plugin from the solution to that question: http://benalman.com/projects/jquery-resize-plugin/
With jQuery resize event, you can now bind resize event handlers to
elements other than window, for super-awesome-resizing-greatness!
Why is a plugin needed for the resize event?
Long ago, the powers-that-be decided that the resize event would only
fire on the browser’s window object. Unfortunately, that means that if
you want to know when another element has resized, you need to
manually test its width and height, periodically, for changes. While
this plugin doesn’t do anything fancy internally to obviate that
approach, the interface it provides for binding the event is exactly
the same as what’s already there for window.
For all elements, an internal polling loop is started which
periodically checks for element size changes and triggers the event
when appropriate. The polling loop runs only once the event is
actually bound somewhere, and is stopped when all resize events are
unbound.
Sample Code
// You know this one already, right?
$(window).resize(function(e){
// do something when the window resizes
});
// Well, try this on for size!
$("#unicorns").resize(function(e){
// do something when #unicorns element resizes
});
// And of course, you can still use .bind with namespaces!
$("span.rainbows").bind( "resize.rainbows", function(e){
// do something when any span.rainbows element resizes
});
You can try this plugin - http://benalman.com/code/projects/jquery-resize/examples/resize/
There are various examples. Try resizing your window and see how elements inside container elements adjusted.
Example with js fiddle
In that resize() event is bound to an elements having class "test" and also to the window object and in resize callback of window object $('.test').resize() is called.
e.g.
$('#test_div').bind('resize', function(){
console.log('resized');
});
$(window).resize(function(){
$('#test_div').resize();
});
See this
My first thought is to use a custom event system. You can find a pure javascript one here ( http://www.nczonline.net/blog/2010/03/09/custom-events-in-javascript/ )
After including his code, you can do something like this:
function myFunction(){
alert('The DIV was resized');
}
div_elm = document.getElmentById('div-to-resize');
EventTarget.call(div_elm);
div_elm.addListener("resize", myFunction);
Then later, just add one line to wherever you are resizing the div.
div_elm.width += 100 //or however you are resizing your div
div_elm.fire("resize");
I think that should work for you.
EDIT:
If you are not the one coding the resizing, then my first thought is something like this:
var resizeScannerInterval_id = (function(div) {
var width = div.offsetWidth;
var height = div.offsetHeight;
var interval_id = setInterval(function() {
if( div.offsetWidth != width || div.offsetHeight != height )
width = div.offsetWidth;
height = div.offsetHeight;
div.fire();
}
},250);
})(document.getElementById('div-id'))
There is a very efficient method to determine if a element's size has been changed.
http://marcj.github.io/css-element-queries/
This library has a class ResizeSensor which can be used for resize detection. It uses a event-based approach, so it's damn fast and doesn't waste CPU time.
Please do not use the jQuery onresize plugin as it uses setTimeout() loop to check for changes. THIS IS INCREDIBLY SLOW AND NOT ACCURATE.
I would like to know if there is a jQuery event that I can use to determine when a particular DIV's top property has changed.
For instance, I have invisible content above a DIV. When that content becomes visible, the DIV is shifted down. I would like to capture that event and then use the offset() function to get the X/Y coordinates.
The easy answer is that there are no events in the DOM for detecting layout updates.
You have a couple options the way I see it:
Poll, nasty but it may work depending on your update frequency requirements.
Tap into whatever event causes the invisible DIV to change size and do whatever you need to do in that handler
I shall correct myself.
I took a look at the DOM and noticed the DOMAttrModified event and found this JQuery Plug-In that you might be able to leverage to do what you want.
As the article mentions, it works great in IE and Firefox but seems to have problems in WebKit.
I thiiink you should be able to do:
$(document).ready( function (){
$("#mydiv").bind("movestart", function (){ ...remember start position... });
$("#mydiv").bind("moveend", function (){ ...calculate offsets etc... });
});
$("#someId").resize(function () {
// your code
});