$(window).scrollTop tied to $(window).scroll() event acting oddly - javascript

I'm trying to trigger a function when the window is scrolled more than a certain number of pixels.
Here's my code:
$(window).scroll(function(){
if( $(this).scrollTop() >= 100 ) {
someFunction();
} else {
someOtherFunction();
}
});
It kinda works, but there's either a delay of around 2-4 seconds after scrolling before the function(s) are fired or else the functions aren't triggered at all.
Tried it out in Safari / Chrome. Don't know if that helps or not!

The code looks fine and works for me.
As Wolfram says, it's rarely a good idea to attach handlers directly to the scroll event, as this fires a lot and can bring the user's system to a crawl.
I'd recommend using Ben Alman's jquery throttle/debounce plugin.

It works using jQuery 1.6.1 + mousewheel / scrollbar in Chrome15/Safari5.1/FF7 on OSX. What are you doing in those two functions? For testing, I put a simple alert() in someFunction and nothing in someOtherFunction.
Remember that one of those functions is executed every time the scroll-event fires unless you stop it once it was called... e.g. someFunction is called a lot after you scrolled below the 100px line.
John Resig: It's a very, very, bad idea to attach handlers to the window scroll event.

If you're scolling by holding in the click-button instead of using the scroll wheel, I believe the event won't fire until you release the click-button.
Have you considered running a loop that checks the scrollTop instead?
EDIT:
I just check an old project of mine using window scroll event, and it runs perfect with the same event.
I asume you have this script of yours wrapped inside:
$(function() {
// code
});

Related

Javascript stop scrolling on touchmove after scrolling has already started

I have a simple example where a user starts to scroll on a touch screen, and then after one second, I want to disable scrolling. I thought event.preventDefault() would stop the scrolling but it doesn't seem to work after scrolling has already started
Here is an example: https://jsfiddle.net/7s5m8c6L/30/
let allowScroll=true;
function TS(e){//touchstart handler
setTimeout(function(){
allowScroll=false;
},1000)
}
function TM(e){//touchmove handler
if(!allowScroll){
e.preventDefault();
}
}
In this example, you can start scrolling, and after a second, I want the scrolling to stop, but it does not. I know there are ways that I can get this to work with CSS (adding overflow:hidden), but I would particularly like to know why preventDefault doesn't work.
If you are using chrome, there is a hint in the console:
[Intervention] Ignored attempt to cancel a touchmove event with cancelable=false, for example because scrolling is in progress and cannot be interrupted.
The problem is exactly that Event.cancelable. Unfortunately for you this property is read-only and it is not safe to call preventDefault for a not cancelable event. If you print e.cancelable in the TM function you can observe that throughout the scrolling e.cancelable is false.

how to avoid windows resize triggering multiple times which is triggered by other events

I Found resize code in my page is triggeing more than once during orientation change in devices. Suspecting this is due to other events like page scroll happening during page mode change from Landscape to Portrait and vice versa. I need to write logic in window resize but its calling more than once. Is there any way we can avoid other events impacting window resize
Window resize event fires multiple times during each window resize. As Rory McCrossan points out above, the event fires once for each pixel it changes.
An option is to use a debounce function, such as that described by David Walsh:
https://davidwalsh.name/javascript-debounce-function
Here is another useful article, describing the difference between throttling and debouncing:
https://css-tricks.com/the-difference-between-throttling-and-debouncing/
Finally, you can use the less elegant (but equally effective) method of using a global variable to keep track of when you wish to allow the resize event to fire.
var ok_to_resize=true;
$(function(){
$(window).resize(function(){
if (ok_to_resize){
//run your resize code
ok_to_resize = false;
setTimeout(function(){
ok_to_resize = true;
},500);
}
}); //END window.resize
}); //END document.ready

Is it possible to intercept/override all click events in the page?

I've written an html5 application which is supposed to work on mobile devices. 90% of the time it works fine however in certain devices (mostly androids 4.0+) the click events fire twice.
I know why that happens, I'm using iScroll 4 to simulate native scrolling and it handles the events that happen inside the scroll.(line 533 dispatches the event if you're interested) Most of the time it works fine but in certain devices both the iScroll dispatched event and the original onClick event attached to the element are fired, so the click happens twice. I can't find a pattern on which devices this happen so I'm looking for alternatives to prevent double clicks.
I already came up with an ugly fix that solves the problem. I've wrapped all the clicks in a "handleClick" method, that is not allowed to run more often than 200ms. That became really tough to maintain. If I have dynamically generated content it becomes a huge mess and it gets worse when I try to pass objects as parameters.
var preventClick = false;
function handleClick(myFunction){
if (preventClick)
return;
setTimeout(function(){preventClick = true;},200);
myFunction.call():
}
function myFunction(){
...
}
<div onclick='handleClick(myfunction)'> click me </div>
I've been trying to find a way to intercept all click events in the whole page, and there somehow work out if the event should be fired or not. Is it possible to do something like that?
Set myFunction on click but before it's called, trigger handleClick()? I'm playing with custom events at the moment, it's looking promising but I'd like to not have to change every event in the whole application.
<div onclick='myfunction()'> click me </div>
You can do that with the following ( i wouldn't recommend it though):
$('body').on('click', function(event){
event.preventDefault();
// your code to handle the clicks
});
This will prevent the default functionality of clicks in your browser, if you want to know the target of the click just use event.target.
Refer to this answer for an idea on how to add a click check before the preventDefault();
I don't like events on attributes, but that's just me.
Thinking jquery: $(selector).click(function(){ <your handler code> } you could do something like:
$(selector).click(function(event){
handleClick(window[$(this).attr("onclick")]);
};
of course, there wouldn't be any parameters...

Triggering Jquery at certain length of page

I'm trying to figure how to trigger an jquery animation when the user scrolls to the middle of the page. Is there a way to set a listener to see if the person scrolls halfway down the page it activates the jquery code?
Using jQuery, you can attach an event handler to the scroll event, which will let you listen to whenever the window is scrolled and determine whether the user has scrolled the appropriate amount.
$(window).scroll(function () {
if (($(window).scrollTop()) > ($(document).height() / 2)) {
// Run animation here
}
});
http://jsfiddle.net/ult_combo/XdqPJ/1/
Think so.. you can look at checking parts of the page using;
setInterval(name_Of_Function,1000);
runs every second, then run a check on there is;
window.pageYOffset // Gives you current horizontal window scroll position for the page.
Firebug is helpful to get more information on these functions. Remember to check in all major browsers as the implementation or values returned may be slightly different between different browsers.
Good reference page I found;
http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html
Is there a way to set a listener to see if the person scrolls halfway
down the page it activates the jquery code?
You can get the amount that the user has scrolled with the following:
$("html,body").scrollTop();
so, to trigger an event halfway down the page:
if (($("html,body").scrollTop()) > ($("html,body").height() / 2))
{
// Code that will be triggered
}
You would need a timer to constantly be checking this. You can use setInterval() in Javascript to repeatedly execute a function to check this.
http://api.jquery.com/scrollTop/

Opera ignoring .live() event handler

I have the following jQuery which works in all major browsers except Opera:
jQuery(document).ready(function () {
jQuery("#GetResults").live("click", function(e){
e.preventDefault(); //Opera doesn't execute anything here
});
};
Which is supposed to fire when clicking the following link:
<a id="GetResults" href="Folder/File/javascript:void(0);">Get Results</a>
Only Opera ignores this. Any ideas?
Edit:
I've just discovered that if I substitute out .live() for .bind() everything functions as expected. I can't find any documentation relating to .live() bugs in Opera though, and it does work in jsFiddle which would point at something environmental. What could be causing this behavour?
This needs clarification. The answers above are correct, but nobody clearly explained where your problem comes from.
In fact I think that you could probably reproduce the problem in other browsers too.
That's because of how .live works:
It binds to the event on document and waits for a particular event to bubble up to there. Then it checks if the event.target is what you wanted to handle. *
If you click on a link element it's quite possible that the browser goes to the new page before the event bubbles high enough to trigger your code. In an app with lots of HTML and event handlers all the browsers should have problems. Opera just starts displaying the new page and destroys the previous quicker in this case. It really depends on a particular situation more than on the browser. For example: you probably won't see this happen if you had a high network latency while connecting to the site.
To prevent default action on a a element you have to use .bind like in the old days ;) when a eveloper had to be aware of what he loads with AJAX and bind new events to that in a callback.
* There is more to that and .live is more complicated. I just described what is needed here.
What happens when you attach the handler using:
$ (something).bind ("click", function (e) {
// do something
})
You can also try to attach the handler using .click() method.
The following code works as expected in Opera 11.50.
<!doctype html>
<title></title>
<a id="GetResults" href="http://google.com">Get Results</a>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
jQuery(document).ready(function () {
jQuery("#GetResults").live("click", function(e){
alert('doing something');
e.preventDefault(); //Opera doesn't execute anything here
});
});
</script>
Either it is a corrected bug, or something more subtle.
Can you check whether the above works on your version of Opera / jQuery?
Read this article: http://jupiterjs.com/news/why-you-should-never-use-jquery-live
try use delegate instead
Not sure if you want to do it, or if it will work for you. I had similar issues with Opera 9.5 and e.preventDefault() not working, the only solution I found was to just return false...
jQuery(document).ready(function () {
jQuery("#GetResults").live("click", function(e){
e.preventDefault();
return false;
});
};
There are two aspects of an event bubbling worth considering in this case: propagation and the default action.
Propagation refers to the event bubbling. First the anchor tag gets the click event, then its parent element, then its parent's parent, and so forth, up to the document element. You can stop an event from propagating at any time by calling e.stopPropagation().
The default action is what the browser will do if nothing is done to prevent it. The most well-known case is when an anchor with an href is clicked, the browser will try to navigate there. There are other examples too, though, for example when you click and drag an image, many browsers will create a ghost image you can drop on another application. In both cases, you can stop the browser from doing the default action at any time by calling e.preventDefault()
As mentioned in other answers to this question, jQuery's .live() feature sets a handler at a high level element (like document) and takes action after events have propagated up. If a handler in between the anchor and the document calls e.stopPropagaiton() without calling e.preventDefault() it would stop the live handler from responding, while still allowing the browser to navigate (the default action).
I doubt this is what's happening, since it would affect all browsers, but it's one possible explanation.
Ensure that document.ready event happens before you click on link.
Try to put all lives in the top of the document.ready wrapper. It may help, if you have a lot of javascript code.

Categories

Resources