How do I prevent auto-scrolling to the top in jQuery? - javascript

This works in all other browsers and I have no idea what the problem is. I'm kind of in a hurry so I thought I'd ask you guys in case I missed anything obvious. I have a link you click on which initiate a popup, and in Firefox (and possibly opera) the page auto scrolls back to the top.
$('[class*=popup-link]').click(function(e) {
/* Prevent default actions */
e.preventDefault();
e.stopPropagation();
/* Get the id (the number appended to the end of the classes) */
var name = $(this).attr('class');
var id = name[name.length - 1];
/* Show the correct popup box, show the blackout and disable scrolling */
$('#popup-box-'+id).show();
$('#blackout').show();
$("html,body").css("overflow","hidden");
});
I need both preventDefault and stopPropagation to stop some other stuff happening. Can you see any errors or a way to stop this auto scrolling to the top? Thanks!
Quick Edit:
I'm also running a function which centers the box using
$(window).scroll(centerBox);
I'm unsure if this would affect scrolling in some odd way in firefox. The contents of this function are just adding CSS, so I doubt they would have any effect on it.
Another Edit:
A link to try it out. Not working in Firefox for me.
http://inserthtml.com/demo/internal-popup/

first, i see nothing wrong in the script. it should be preventing the "top jump" even only with e.preventDefault(). try stripping it down to this. it should tell if this handler is causing it or not
$('[class*=popup-link]').click(function(e) {
e.preventDefault(); //prevent the click from jumping esp on hashes
e.stopPropagation(); //prevent from any parent click handlers that didn't prevent the jump
//no code here for now
return false; //the natural way to prevent the jump
});
if this code prevents the jump, then there is something in the rest of your code that causes it especially broken scripts. check the console for errors also

e.preventDefault();
e.stopPropagation();
is equivalent to
return false;
Change them, and you will be fine

Related

Why does modal pop up pressing space bar press? How do I prevent it?

I have an action planned on a space bar click. It does happen.
// when space bar is pressed
do-something; // Applied on the $(document).keypress..
But, when I press space bar, along with the event/action that has to be triggered, modal load/shows up again. Why is it so? I have tried to prevent modal from loading again :
$('#goal').on('hidden.bs.modal',function() {
$(document).focus(); // Get the button that triggered modal
// out of focus
});
But the document, doesn't get focus and the button that triggered modal-load remains in focus until I click on the screen to bring the document back to focus. How could I prevent modal from loading again on space bar press?
I also tried the blur() function on button that triggers modal. But it doesn't help?
Using $(document).focus(); will have no effect, because document is not a focusable element, it's actually not an element at all. Try using document.activeElement to get the active element and blur it.
document.activeElement.blur();
To do this, you will need to listen for the event when the modal is closed, hidden.bs.modal, since Bootstrap will automatically return the focus to the button on close.
Example (Live):
$(document).on('hidden.bs.modal', function() {
document.activeElement.blur();
});
Alternately, you could set the focus to a focusable element in the model itself if one exists. This would probably give the most-pleasant user experience.
It might be due to default focus on an element which might be causing this. Tried event.preventDefault(); ?
// when space bar is pressed
event.preventDefault();
do-something; // Applied on the $(document).keypress..
This is a bit hard to answer without seeing more of your code or, even better, a jsfiddle that demonstrates your problem.
But in general, you can prevent the space bar keypress from having any side effects by returning false from the jquery event handler function to indicate that you've consumed the event.
So (guessing what your event handler looks like)
$('...').keypress( function(event) {
if ( event.which == 32 ) {
doSomething();
return false;
}
});
Hope this helps. If not, please give a bit more details.
You can avoid the button gaining focus this way:
$('#yourButtonId').focus(function(){
$(this).blur();
});
I tried this in the jsFiddle you posted and it works, the space bar doesn't open the modal anymore.

Prevent scrolling on mobile browser, without preventing input focusing

I use preventDefault() on touchstart on the document to prevent scrolling on a page. Unfortunately this prevents too much. The user can no longer give focus to an input (and open the soft keyboard). Using jQuery focus(), I can give the focus to the input on a touchstart. This opens the soft keyboard on iOS (most of the time), but never on Android.
Background:
I have a webpage that I want to make as much like a mobile app as possible. I'm only really concerned with Android and iOS, but any form factor. I start by making the content in the page exactly the same size as the screen size. This is nice until the user puts their finger on the page. I need to prevent user scrolling. The following code accomplishes this, but in slightly different ways on the two operating systems.
$(document).on('touchstart', function(e) {
e.preventDefault();
});
On iOS, this prevents the elastic scrolling: where a user can reveal a texture behind the webpage by attempting to scroll off the page. The feature is nice for a regular webpage, but in my case it detracts from the UX.
On Android, prevents the revelation of a handy hack that I use to hide the address bar. Android browsers start with the address bar visible, but as the user scrolls down the page, it disappears. To programmatically force the browser hide the address bar, simply add this line of code to your function called at load.
$('html, body').scrollTop(1);
This is a hacky (but also the only) way to tell the android browser that we have scrolled, and the address bar is no longer necessary.
Without the preventDefault on the document, the Android browser will allow scrolling and the address bar can be revealed.
So, both OS's have a good reason to have this preventDefault() called on every touchstart on the document, but it prevents too much. Tapping on an input field does nothing. Using a call to jQuery focus() can help, but only opens the soft keyboard on iOS, not Android.
$('input').on('touchstart', function() {
$(this).focus();
});
How can I prevent the page from scrolling, but use the browser native functionality for giving focus to input fields?
Note:
This code
$(document).on('touchstart', function(e) {
if (e.target.nodeName !== 'INPUT') {
e.preventDefault();
}
});
is flawed because the user can still scroll the page as long as the initial touch originates from within the input field.
I actually solved this problem on another project, forgot about it, and remembered it most of the way through typing this up.
They key is to just do it on touchmove.
$(document).on('touchmove', function(e) {
e.preventDefault();
});
However, preventDefault on touchstart does all kinds of nice things like preventing the image save menu on a gesture enabled slideshow. My projects also include this.
$(document).on('touchstart', function(e) {
if (e.target.nodeName !== 'INPUT') {
e.preventDefault();
}
});
If anyone has some suggestions on additional content or how to reformat this so that it can reach a greater audience that would be great. I haven't ever seen the content I have here all in one place, so I felt that it needed to be on SO.
Combine the two!
// prevent scrolling from outside of input field
$(document).on('touchstart', function(e) {
if (e.target.nodeName !== 'INPUT') {
e.preventDefault();
}
});
// prevent scrolling from within input field
$(document).on('touchmove', function(e) {
if (e.target.nodeName == 'INPUT') {
e.preventDefault();
}
});
This probably isn't perfect either, and I am especially worried that the first function will prevent following links, but I'll leave it to others to do extensive tests.
The simple answer to your question is don't use "preventDefault" instead use pointer-events css property to disable the scrolling on the element that scrolls.
CSS for your inputs:
input {
pointer-events: auto !important;
}
touchstart event listener:
document.body.addEventListener('touchstart', function(e) {
if (e.target.nodeName === 'INPUT') {
this.style.pointerEvents = 'none';
}
});
You will need to reset the pointer-events when you blur the input.
document.body.pointerEvents = 'auto';
+1 Good Question

auto scroll: stop jumps back to top of page

I have a page in which the user clicks one link to start scrolling down the page automatically for ease in reading. There is another link the user clicks to stop the scrolling. The former works perfectly, but the latter makes the page jump back to the top when clicked instead of stopping the scrolling at the that place on the page. Any ideas?
function pageScroll() {
window.scrollBy(0,1); // horizontal and vertical scroll increments
scrolldelay = setTimeout('pageScroll()',50); // scrolls every 100 milliseconds
}
function stopScroll() {
clearTimeout(scrolldelay);
}
I tried to add return false; to the second function from something I read on another post, but it didn't help. I don't fully understand the use of return anyhow. Thanks for any help.
I assume that you're doing something like this:
start
stop
The quickest fix is to return false from the onclick event handlers, like this:
start
stop
The idea is to stop the browser from doing the default action of the event (in this case, going to #, which scrolls to the top of the page). Nowadays, the more modern way is to bind an event handler function, then use e.preventDefault() in it, but return false; still works for old-style event attributes.

Preventing cursor change on link click in Chrome

Clicking on a link in Chrome (not Safari or Firefox) changes the cursor from pointer to arrow. Can this behavior be prevented? I.e., is it possible to still have the pointer after clicking, but while the cursor is still hovering over the link?
EDIT: Okay so I've done a little more testing. First of all, the only reason anyone would want the cursor to remain as a pointer after clicking on a link is if the link does not actually load another page but rather fires a JS event instead.
Test
// JQuery
$("a").click(function(event) { event.preventDefault(); }
With the above code, event.preventDefault (or returning false) will allow the cursor to remain a pointer after click. This will suffice for most uses, namely triggering a DOM manipulation and/or AJAX request.
The problem is with history.pushState():
Test
// JQuery
$("a").click(function(event) {
history.pushState(arg1, arg2, url);
event.preventDefault(); return false;
}
Here the pointer DOES change to an arrow. Any ideas on how to stop that from happening?
This sounds like a CSS issue. Look for code like the following:
::-webkit-any-link:hover,
::-webkit-any-link:active { cursor: pointer; }
This will affect all links (like a[href]) but only in WebKit. Perhaps something else is preventing Safari from doing this.
UPDATE GIVEN EXPANDED QUESTION:
Now that we know more about the problem, namely that the cursor changes back to a pointer after clicking on an element fires off a javascript, I would say that this is a Chrome bug.
Please file a report at http://bugs.chromium.org/
You could explicitly set your target element's CSS to include --
#element {
cursor: pointer;
}
See http://www.quirksmode.org/css/cursor.html#note if you have to support IE 5.5.
In the meantime I'm thinking this desperate workaround:
Browser detect Chrome
Apply this tutorial

jQuery - click-event is called twice on iPad

I have a problem with my web application which is designed for iPad.
I use jQuery and jQuery UI for dragging elements on the screen. Because on iPad, the element can not be dragged by default, I added this library:
http://code.google.com/p/jquery-ui-for-ipad-and-iphone/
Including it, I can drag and drop elements on iPad, but also a problem occurs. I have on the draggable element also a div are with an image, which should be clickable.
So I integrate these lines:
$(document).ready(function() {
$(".note").draggable();
$('.closebutton').click(function() {
alert("test");
});
});
​
The problem is, including the drag-library, the alert message test pops up twice or the screen is frozen.
I created a full working demo here:
http://jsbin.com/oliwo/2/
On normal desktop browsers, like Firefox 4 Beta and Safari, it works, only one test message appears by clicking with the mouse on the x - delete image. On iPad, I get the message twice or the screen froze.
Does anyone can help me? Thank you a lot in advance & Best Regards.
This is not really a response, as i don't known why you have it twice. But you can try a workaround if you're sure your click event is the only click event behavior that should be attached to this button; Make an unbind() just before you're bind, this will remove any previous click binding (so if this is run several times, you'll get only one event):
$('.closebutton').unbind().click(function() { ...
or better:
$('.closebutton').unbind('click').click(function() { ...
I've found that events get fired twice when showing an alert box on a click. I've managed to overcome this problem by using a setTimeout to show the alert box...
$("#myButton").unbind("click").click(function () {
// Have to use a setTimeout else on iPhone the alert may appear twice in certain scenarios
setTimeout(function () { alert('The message'); }, 300);
return false; // Return false to prevent href being followed
});
I do not know why, but if I do not use alert messages, it will work. I create new elements and then it is only called once, on iPad and Desktop Safari.
I'm seeing this issue only on iPad, perhaps some version of webkit related. The unbind worked for me, and I also read this only exists if jquery code is in the body html tag, if its in head it is not an issue.
just simply avoid the propagation of the click
$("tr").live('click',function() {
...
$( event.toElement ).one('click', function(e){ e.stopImmediatePropagation(); } );
});

Categories

Resources