I am doing some experimentation with JavaScript and I have a list of 4 items displayed horizontally, with each list item having an onmouseover and onmouseout event assigned.
The onmouseover event for each item executes a function which increases the height of the item over time using an interval.
the outmouseover event for each item executes a function which then reduces the height of the item to its default value over time using another interval.
It is working in the following scenario:
When I trigger the onmouseover for a list item the height increases as expected, and when I take the mouse off the list item the height then decreases as expected.
The problem is however, it doesn't seem to work in the following scenario:
When I trigger the onmouseover for a list item the height increases as expected, however if I trigger another onmouseover event for another list item before the item has returned to its original size, the onmouseout function for the previous list item does not finish executing.
Sorry if I am lacking any detail, evidently I am incredibly bad at explaining things.... So I have a link to the source code and a site where you can test the code to see what is happening.
Maybe I do not have as much of a knowledge of javascript as I thought, so while a solution or fix would be amazing, I am also happy to accept any advice or some kind of explanation as to why this could be happening.
I thought initially that multiple interval timers could not execute simultaneously, until after some research I found they can. So now I am thinking if it is a conflict between the onmouseover and onmouseout events.
Any advice, guidance or a solution would be extremely appreciated!
Source:
https://docs.google.com/open?id=0B6XLOOGyKVdWVkpSUklmMVI5QUk
Testing Site:
http://www.play-hookey.com/htmltest/
(just copy the contents of that google document and paste into the html text area in the site to see what I am talking about)
Your code:
icon.onmouseover = function(){ enlarge(this, icon.ID); };
icon.onmouseout = function(){ reduce(this, icon.ID); };
Correct code:
icon.onmouseover = function(){ enlarge(this, this.ID); };
icon.onmouseout = function(){ reduce(this, this.ID); };
What happened: you bindded an event with a function and passed variables to it. After each for loop, you redefined that function variable (so at the end, your icon.ID=3). That means that all on event called functions where using same icon.ID=3.
I hope that make sense...
Related
Still new to the forums, so I'll try my best to get across the problem. Basically I'm developing a mobile web app, and have several ontap functions for reloading the webpage after buttons clicked. Here is the code for two of my smaller onTap functions for demonstration purposes (so you don't have to sift through hundreds of lines of code). The licenses_button ontap function works perfectly fine, with no forms of errors whatsoever, but the back_button ontap function, and all other buttons that aren't created on the initial main page of the app won't act as button's and I have no idea why. Any advice? (I know the back_button has little to no content, I just removed a lot of it for debugging purposes and even this fails to work). Thanks for any advice!
$("#licenses_button").onTap(function(event){
$("#play_button").remove();
$("#banner").remove();
$("#licenses_button").remove();
$(".cloud").remove();
$(".cloudalternate").remove();
$("body").append("<div id='back_button'>Back</div");
});
$('#back_button').onTap(function(event) {
$('#back_button').remove();
});
$(selector).onTap(callback); attaches the handler to the selected elements at the moment it is called. Elements that are not yet created at this time cannot be selected (obviously since they do not exist yet) and thus, won't get the handler.
You need to attach the handler after you added an element.
For example:
$("#licenses_button").onTap(function(event){
$("#play_button").remove();
$("#banner").remove();
$("#licenses_button").remove();
$(".cloud").remove();
$(".cloudalternate").remove();
// Create the button.
var backButton = $("<div id='back_button'>Back</div");
// Append it to the body.
$("body").append(backButton);
// Attach the handler to the new button.
backButton.onTap(function(event) {
backButton.remove();
});
});
You mentioned the back_button and other buttons that aren't working are not created in the main page. Since these are created at a later time, you have to wait to set up the onTap event for those buttons AFTER you create the buttons. If you try to set the event handler up before they're created, they won't work.
I have a weird problem that I am not able to debug.
I have a script with the following relevant functions:
a function events() that has a jQuery.on('click', callback(event)) event binder inside it. That function gets called every time I add or remove anchors with AJAX, but that's irrelevant for this problem.
a function get_passwords() which gets jQuery.attr("href") from anchor $("a.active") and makes a $.post to the server with a callback that inserts values into a table upon receiving the data
The function get_passwords() is called synchronously in the callback(event) function like this:
event.preventDefault(); //prevents a browser navigation
$("a.active").removeClass("active"); //removes active class from all other anchors
$(this).addClass("active"); //adds a class "active" to the anchor that was clicked
get_passwords(); <---- the function in question <--BREAKPOINT #1
The function get_passwords() contains the following relevant lines:
$.post("url", postData, function(data) { //put received data into table }); <--BREAKPOINT #2
Now, the weird bug is that the get_passwords() function is called multiple times by the same event listener, and only stops calling that function after an arbitrary, but constant amount of times, every time the click is made on an anchor with the event listener.
I've set the breakpoint in FireBug on the above indicated line, and as I execute the script step by step, all it does is jump between the two breakpoints set above (the part where it calls get_passwords() and where it executes $.post, 4 times (always the same amount), up until the 4th time when it actually proceeds with the callback in the $.post function.
Realizing that there is no way I can ask anyone to read through all the code that I've written, does anyone have any suggestions as to where this bug could be coming from?
Thank you in advance.
EDIT: http://jsfiddle.net/nt3A4/
Are you looking for event.stopImmediatePropagation()?
#epascarello, #nbrooks,
You were both right. I was attaching multiple event listeners, somehow, to the same anchor. Probably got lost due to my poor coding planning (I was making up website features as I went along).
Anyway, I fixed it by pre-pending $("a").off() in the events() function, as to remove any other event listeners that may have been set before. Should of done that from the beginning :/
Thank you all for your answers and your time.
I have two div's in my html page
<div id="box1">
</div>
<div id="box2">
</div>
Both of them are absolutely positioned at different positions.
#box1,#box2 {
height: 100px;
width: 100px;
background-color: red;
position: absolute;
}
#box2 {
top :200px;
}
In my Javascript I am animating these two div's as shown below
$(document).ready(function() {
function animateBoxes() {
$("#box1").animate({left : "500px"},5000);
$("#box2").animate({left : "500px"},3000);
}
animateBoxes();
});
When my page loads both the div's start moving at the same time.
My question is if javascript is single threaded how can both the div's move at the same time.
Because the movement of the div's is handled by javascript by two animate functions, one on box1 and other on box2.
How both the animate functions got executed at the same time?
Javascript is single threaded meaning something if is stuck the whole script is stuck...and only way overcome this is spawn worker. To answer your question, Do You Know how animate function of jquery works...it sets timer to call function that updates div's position. So both div get positioned a little bit toward their goal. Timer is provided by javascript and is handled like an event. Javascript has event loop..which is reiterated by browser. Meaning as soon as js is done browser goes through all events and check if they have been fired and then run the function that is associated with them. Here animate function associate itself to timer event and gradually updates div's position, thus looking like it animated. And since it happens in steps the whole js doesn't have to wait for this animation to end to continue executing.
This is how events basically work in js:
browser starts executing the code..
every next action waits till last action is done.
when javascript reaches the code that is attaching function to event, js registers the event, let's say click event. Now it know that button has click event and it has this function.
Now after all code below has been executed browser starts new routine. To check for any event that have been fired.
...looping but no events..
you click button ...it adds that click event has fired to event loop check list.
browser again checks the event loop...it sees the event.
it runs the code for that event and clear it...
suppose you clicked two times...then the code of second event won't start executing till the first is done.
Timer is same but it fires every x amount of time has passed. But as you can see event loops gets stucked executing the function related to the event...the timer is not perfect.
let's say you set timer for 10 ms. And as 9ms had passed you clicked the button starting another event. So your button event starts executing..but it did something really long that took 5 ms.
so your timer actually fires at 14ms.
Take a look at this example: http://jsfiddle.net/82zLC/6/
This will give you idea that animation is divided into chunks which are update step by step...try changing t to 60.
JavaScript can act asynchronous in many situations. .animate() is an example of this. It pretty much has to act asynchronous, in order to not interrupt other page processes. If you are looking for the events to happen one-after-the-other, try looking into callbacks:
$("#box1").animate({left: "500px"},5000, function(){
$("#box2").animate({left: "500px"},5000);
});
When we pass the function to .animate(), it calls the function after it is done with the animation.
I'm having an issue where when I try to zoom in on a certain area of my graph that is continuously updating the plotselected event fires off numerous times instead of just once. I've slowed down the update rate in the attached jsfiddle significantly so that you aren't overwhelmed with alert messages to show the multiple plotselected events fired off. With a quicker refresh rate you could be stuck with 50+ of those messages. Anyways, is there a way to only fire off that event handler for the last event in the chain that's created after selecting the area? Suspect code in question (this works fine in static mode):
$("#overview").on("plotselected", function (event, ranges) {
alert(ranges.xaxis.from+','+ranges.xaxis.to);
plot.setSelection({
xaxis: {from:ranges.xaxis.from,to:ranges.xaxis.to}
});
});
full jsfiddle example: http://jsfiddle.net/grkblood13/6TG5a/
You are attaching the plotselected event handler to your plot div every time you call plotData. These are cumulative!
So, simply remove the $("#overview").on("plotselected" call outside that function.
Updated fiddle.
I'm testing a ratings module I'm working on, had an idea for a fairly simple construction that'd allow for smooth ajax based voting, but found something odd..
The contruction is two divs, one nested in the other to show the stars, mousing over sets the width, which would be translated into a percent as a vote later on.
In testing this, I found that everything worked, but when I clicked, it sometimes made the width of the inner DIV reset, which is what it would do if I moused out, I'm not sure I understand why just yet. I'm including a working example of this.
http://www.nogumallowed.com/test.php
Here is the fixed code:
$(".ratingsBlock").mousemove(function(e){
$(".ratingsScale").width(e.offsetX);
});
$(".ratingsBlock").click(function(e){
$(this).attr("score",e.offsetX);
});
$(".ratingsBlock").mouseleave(function(e){
$(".ratingsScale").width($(this).attr('score'));
//$(".ratingsScale").animate({width:$(this).attr('score')+'px'}, 500);
});
I changed the mouseOut function to mouseLeave, and made the rating's score update when .ratingsBlock is clicked.
mouseOut is weird sometimes...