Safari in ios8 is scrolling screen when fixed elements get focus - javascript

In IOS8 Safari there is a new bug with position fixed.
If you focus a textarea that is in a fixed panel, safari will scroll you to the bottom of the page.
This makes all sorts of UIs impossible to work with, since you have no way of entering text into textareas without scrolling your page all the way down and losing your place.
Is there any way to workaround this bug cleanly?
#a {
height: 10000px;
background: linear-gradient(red, blue);
}
#b {
position: fixed;
bottom: 20px;
left: 10%;
width: 100%;
height: 300px;
}
textarea {
width: 80%;
height: 300px;
}
<html>
<body>
<div id="a"></div>
<div id="b"><textarea></textarea></div>
</body>
</html>

Based on this good analysis of this issue, I've used this in html and body elements in css:
html,body{
-webkit-overflow-scrolling : touch !important;
overflow: auto !important;
height: 100% !important;
}
I think it's working great for me.

The best solution I could come up with is to switch to using position: absolute; on focus and calculating the position it was at when it was using position: fixed;. The trick is that the focus event fires too late, so touchstart must be used.
The solution in this answer mimics the correct behavior we had in iOS 7 very closely.
Requirements:
The body element must have positioning in order to ensure proper positioning when the element switches to absolute positioning.
body {
position: relative;
}
The Code (Live Example):
The following code is a basic example for the provided test-case, and can be adapted for your specific use-case.
//Get the fixed element, and the input element it contains.
var fixed_el = document.getElementById('b');
var input_el = document.querySelector('textarea');
//Listen for touchstart, focus will fire too late.
input_el.addEventListener('touchstart', function() {
//If using a non-px value, you will have to get clever, or just use 0 and live with the temporary jump.
var bottom = parseFloat(window.getComputedStyle(fixed_el).bottom);
//Switch to position absolute.
fixed_el.style.position = 'absolute';
fixed_el.style.bottom = (document.height - (window.scrollY + window.innerHeight) + bottom) + 'px';
//Switch back when focus is lost.
function blured() {
fixed_el.style.position = '';
fixed_el.style.bottom = '';
input_el.removeEventListener('blur', blured);
}
input_el.addEventListener('blur', blured);
});
Here is the same code without the hack for comparison.
Caveat:
If the position: fixed; element has any other parent elements with positioning besides body, switching to position: absolute; may have unexpected behavior. Due to the nature of position: fixed; this is probably not a major issue, since nesting such elements is not common.
Recommendations:
While the use of the touchstart event will filter out most desktop environments, you will probably want to use user-agent sniffing so that this code will only run for the broken iOS 8, and not other devices such as Android and older iOS versions. Unfortunately, we don't yet know when Apple will fix this issue in iOS, but I would be surprised if it is not fixed in the next major version.

I found a method that works without the need to change to position absolute!
Full uncommented code
var scrollPos = $(document).scrollTop();
$(window).scroll(function(){
scrollPos = $(document).scrollTop();
});
var savedScrollPos = scrollPos;
function is_iOS() {
var iDevices = [
'iPad Simulator',
'iPhone Simulator',
'iPod Simulator',
'iPad',
'iPhone',
'iPod'
];
while (iDevices.length) {
if (navigator.platform === iDevices.pop()){ return true; }
}
return false;
}
$('input[type=text]').on('touchstart', function(){
if (is_iOS()){
savedScrollPos = scrollPos;
$('body').css({
position: 'relative',
top: -scrollPos
});
$('html').css('overflow','hidden');
}
})
.blur(function(){
if (is_iOS()){
$('body, html').removeAttr('style');
$(document).scrollTop(savedScrollPos);
}
});
Breaking it down
First you need to have the fixed input field toward the top of the page in the HTML (it's a fixed element so it should semantically make sense to have it near the top anyway):
<!DOCTYPE HTML>
<html>
<head>
<title>Untitled</title>
</head>
<body>
<form class="fixed-element">
<input class="thing-causing-the-issue" type="text" />
</form>
<div class="everything-else">(content)</div>
</body>
</html>
Then you need to save the current scroll position into global variables:
//Always know the current scroll position
var scrollPos = $(document).scrollTop();
$(window).scroll(function(){
scrollPos = $(document).scrollTop();
});
//need to be able to save current scroll pos while keeping actual scroll pos up to date
var savedScrollPos = scrollPos;
Then you need a way to detect iOS devices so it doesn't affect things that don't need the fix (function taken from https://stackoverflow.com/a/9039885/1611058)
//function for testing if it is an iOS device
function is_iOS() {
var iDevices = [
'iPad Simulator',
'iPhone Simulator',
'iPod Simulator',
'iPad',
'iPhone',
'iPod'
];
while (iDevices.length) {
if (navigator.platform === iDevices.pop()){ return true; }
}
return false;
}
Now that we have everything we need, here is the fix :)
//when user touches the input
$('input[type=text]').on('touchstart', function(){
//only fire code if it's an iOS device
if (is_iOS()){
//set savedScrollPos to the current scroll position
savedScrollPos = scrollPos;
//shift the body up a number of pixels equal to the current scroll position
$('body').css({
position: 'relative',
top: -scrollPos
});
//Hide all content outside of the top of the visible area
//this essentially chops off the body at the position you are scrolled to so the browser can't scroll up any higher
$('html').css('overflow','hidden');
}
})
//when the user is done and removes focus from the input field
.blur(function(){
//checks if it is an iOS device
if (is_iOS()){
//Removes the custom styling from the body and html attribute
$('body, html').removeAttr('style');
//instantly scrolls the page back down to where you were when you clicked on input field
$(document).scrollTop(savedScrollPos);
}
});

I was able to fix this for select inputs by adding an event listener to the necessary select elements, then scrolling by an offset of one pixel when the select in question gains focus.
This isn't necessarily a good solution, but it's much simpler and more reliable than the other answers I've seen here. The browser seems to re-render/re-calculate the position: fixed; attribute based on the offset supplied in the window.scrollBy() function.
document.querySelector(".someSelect select").on("focus", function() {window.scrollBy(0, 1)});

Much like Mark Ryan Sallee suggested, I found that dynamically changing the height and overflow of my background element is the key - this gives Safari nothing to scroll to.
So after the modal's opening animation finishes, change the background's styling:
$('body > #your-background-element').css({
'overflow': 'hidden',
'height': 0
});
When you close the modal change it back:
$('body > #your-background-element').css({
'overflow': 'auto',
'height': 'auto'
});
While other answers are useful in simpler contexts, my DOM was too complicated (thanks SharePoint) to use the absolute/fixed position swap.

Cleanly? no.
I recently had this problem myself with a fixed search field in a sticky header, the best you can do at the moment is keep the scroll position in a variable at all times and upon selection make the fixed element's position absolute instead of fixed with a top position based on the document's scroll position.
This is however very ugly and still results in some strange back and forth scrolling before landing on the right place, but it is the closest I could get.
Any other solution would involve overriding the default scroll mechanics of the browser.

Haven't dealt with this particular bug, but maybe put an overflow: hidden; on the body when the text area is visible (or just active, depending on your design). This may have the effect of not giving the browser anywhere "down" to scroll to.

A possible solution would be to replace the input field.
Monitor click events on a div
focus a hidden input field to render the keyboard
replicate the content of the hidden input field into the fake input field
function focus() {
$('#hiddeninput').focus();
}
$(document.body).load(focus);
$('.fakeinput').bind("click",function() {
focus();
});
$("#hiddeninput").bind("keyup blur", function (){
$('.fakeinput .placeholder').html(this.value);
});
#hiddeninput {
position:fixed;
top:0;left:-100vw;
opacity:0;
height:0px;
width:0;
}
#hiddeninput:focus{
outline:none;
}
.fakeinput {
width:80vw;
margin:15px auto;
height:38px;
border:1px solid #000;
color:#000;
font-size:18px;
padding:12px 15px 10px;
display:block;
overflow:hidden;
}
.placeholder {
opacity:0.6;
vertical-align:middle;
}
<input type="text" id="hiddeninput"></input>
<div class="fakeinput">
<span class="placeholder">First Name</span>
</div>
codepen

None of these solutions worked for me because my DOM is complicated and I have dynamic infinite scroll pages, so I had to create my own.
Background: I am using a fixed header and an element further down that sticks below it once the user scrolls that far down. This element has a search input field. In addition, I have dynamic pages added during forward and backwards scroll.
Problem: In iOS, anytime the user clicked on the input in the fixed element, the browser would scroll all the way to the top of the page. This not only caused undesired behavior, it also triggered my dynamic page add at the top of the page.
Expected Solution: No scroll in iOS (none at all) when the user clicks on the input in the sticky element.
Solution:
/*Returns a function, that, as long as it continues to be invoked, will not
be triggered. The function will be called after it stops being called for
N milliseconds. If `immediate` is passed, trigger the function on the
leading edge, instead of the trailing.*/
function debounce(func, wait, immediate) {
var timeout;
return function () {
var context = this, args = arguments;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
function is_iOS() {
var iDevices = [
'iPad Simulator',
'iPhone Simulator',
'iPod Simulator',
'iPad',
'iPhone',
'iPod'
];
while (iDevices.length) {
if (navigator.platform === iDevices.pop()) { return true; }
}
return false;
}
$(document).on("scrollstop", debounce(function () {
//console.log("Stopped scrolling!");
if (is_iOS()) {
var yScrollPos = $(document).scrollTop();
if (yScrollPos > 200) { //200 here to offset my fixed header (50px) and top banner (150px)
$('#searchBarDiv').css('position', 'absolute');
$('#searchBarDiv').css('top', yScrollPos + 50 + 'px'); //50 for fixed header
}
else {
$('#searchBarDiv').css('position', 'inherit');
}
}
},250,true));
$(document).on("scrollstart", debounce(function () {
//console.log("Started scrolling!");
if (is_iOS()) {
var yScrollPos = $(document).scrollTop();
if (yScrollPos > 200) { //200 here to offset my fixed header (50px) and top banner (150px)
$('#searchBarDiv').css('position', 'fixed');
$('#searchBarDiv').css('width', '100%');
$('#searchBarDiv').css('top', '50px'); //50 for fixed header
}
}
},250,true));
Requirements: JQuery mobile is required for the startsroll and stopscroll functions to work.
Debounce is included to smooth out any lag created by the sticky element.
Tested in iOS10.

I just jumped over something like this yesterday by setting height of #a to max visible height (body height was in my case) when #b is visible
ex:
<script>
document.querySelector('#b').addEventListener('focus', function () {
document.querySelector('#a').style.height = document.body.clientHeight;
})
</script>
ps: sorry for late example, just noticed it was needed.

This is now fixed in iOS 10.3!
Hacks should no longer be needed.

I had the issue, below lines of code resolved it for me -
html{
overflow: scroll;
-webkit-overflow-scrolling: touch;
}

Related

Stop element from being fixed once scrolled past value

I have a fixed .widget element that remains visible at all times. Currently however, it scrolls over the footer area. My goal is to stop the widget before it hits the footer.
CSS
.widget {
position:fixed;
height:450px;
width:300px;
}
footer {
height:450px;
width:100%;
}
My route I'm taking is currently:
jQuery
var $bodyheight = $('body').height();
var $footerheight = $('footer').height();
var $widgetheight = $('.game_widget').height();
var $pageheight = $bodyheight - $footerheight - $widgetheight;
$(window).on('scroll', function() {
console.log($(this).scrollTop())
});
My next step would be to loop through to see if scrollTop > $pageheight then update some CSS.
Is this the best way of going about this? Is there a cleaner/simpler way to achieve the same result?
I have managed to solve this quite simply. Inside the scroll function I set 2 variables, one for the position of the fixed element, the other for the position of the footer. These return the exact value from how far the top of the element is from the top of the page. For the fixed element I need to know the distance to the bottom of this element so I also include the height.
var $fixedpos = $(".game_widget").offset().top + $('.game_widget').height();
var $footerpos = $("footer").offset().top - 25; // 25 accounts for margin
Using a simple if/else the CSS is updated to display none/initial depending on whether $fixedpos > $footerpos (i.e. the fixed element is overlapping the footer).
if ($fixedpos > $footerpos) {
$('.game_widget').css('display','none');
} else {
$('.game_widget').css('display','initial');
}
This works, however there is a 'flicking' effect as the fixed element overlaps the footer. This is due to the function executing extremely rapidly. The solution to the flicker is to use this simple 'throttling' plugin that adds a short delay (of your choice) between each execution of a function - http://benalman.com/projects/jquery-throttle-debounce-plugin/
You then just need to bind the on scroll function to the throttle:
function scrolling() {
console.log($(".game_widget").offset().top + $('.game_widget').height());
console.log($("footer").offset().top - 25);
var $fixedpos = $(".game_widget").offset().top + $('.game_widget').height();
var $footerpos = $("footer").offset().top - 25;
if ($fixedpos > $footerpos) {
$('.game_widget').css('display', 'none');
} else {
$('.game_widget').css('display', 'initial');
}
};
$(window).on('scroll', $.throttle(250, scrolling)); // 250ms between executing the function
});
This 250ms delay stops the function from executing so rapidly that the flickering effect occurs.
Hope this helps others trying to solve this problem.

Better way to get the viewport of a scrollable DIV in RTL mode?

I need a better way to calculate a scrollable div's viewport.
Under normal circumstances, I would use the following attributes: (scrollLeft, scrollTop, clientWidth, clientHeight)
Using these numbers I can accurately determine which part of a scrollable DOM element's viewport is currently visible, I use this information to asynchronously load things that are visible to the user on demand when scrolling to the content horizontally or vertically. When the content of the DIV is massive, this will avoid an embarassing browser crashing bug because of too many DOM elements being loaded.
My component has worked for a while now with no issues, this build we are introducing RTL support. Now everything is thrown off because of browser inconsistencies.
To demonstrate, I have created a simple example which will output the scrollLeft attribute of a scrollable element in a JSFiddle.
The behavior of the scrollLeft attribute on this simple scrollable element is not consistent from one browser to the next. The 3 major browsers I've tried all behaved differently.
FF-latest scrollLeft starts at 0 and goes negative when scrolling left
IE 9 scrollLeft starts at 0 and goes positive when scrolling left
Chrome-latest scrollLeft starts at a higher number and goes to 0 when scrolling left
I want to avoid having code like if(ie){...}else if(ff){...}else if (chrome){...} that would be horrible, and not maintainable in the long run in case browsers change behavior.
Is there a better way to figure out precisely which part of the DIV is currently visible?
Perhaps there is some other reliable DOM attribute other than scrollLeft?
Maybe there is a jQuery plugin that will do it for me, keeping in mind which browser version it is?
Maybe there is a technique I can use to figure out which of the cases it is at runtime without relying on some unreliable browser detection (i.e. userAgent)
Fiddle Example (code copied below)
HTML
<div id="box"><div id="content">scroll me</div></div>
<div id="output">Scroll Left: <span id="scrollLeft"></span></div>
CSS
#box {
width: 100px; height: 100px;
overflow: auto;
direction: rtl;
}
#content { width: 300px; height: 300px; }
JS
function updateScroll() {
$('#scrollLeft').text(box.scrollLeft());
}
var box = $('#box').scroll(updateScroll);
updateScroll();
Here's a jQuery plugin which does not use browser detection: https://github.com/othree/jquery.rtl-scroll-type
Using this plugin you could replace jQuery's scrollLeft function with your own predictable version, like this:
var origScrollLeft = jQuery.fn.scrollLeft;
jQuery.fn.scrollLeft = function(i) {
var value = origScrollLeft.apply(this, arguments);
if (i === undefined) {
switch(jQuery.support.rtlScrollType) {
case "negative":
return value + this[0].scrollWidth - this[0].clientWidth;
case "reverse":
return this[0].scrollWidth - value - this[0].clientWidth;
}
}
return value;
};
I didn't include the code for setting the scroll offset, but you get the idea.
Here's the fiddle: http://jsfiddle.net/scA63/
Also, this lib may be of interest too.
You can try this:-
var initialScrollLeft = $('#box').scrollLeft(), negativeToZero, startFromZero;
if(initialScrollLeft === 0){
startFromZero = true;
} else if(initialScrollLeft < 0){
negativeToZero = true;
}
var box = $('#box').scroll(function(){
if(startFromZero){
if(box.scrollLeft()>0){
$('#scrollLeft').text(- (box.scrollLeft()));
}else {
$('#scrollLeft').text(box.scrollLeft());
}
} else if(negativeToZero){
$('#scrollLeft').text(box.scrollLeft()+(box[0].scrollWidth - box[0].clientWidth));
} else{
$('#scrollLeft').text(box.scrollLeft()-(box[0].scrollWidth - box[0].clientWidth));
}
});
Problem: (Ex. Scroll Width = 100)
Chrome - Most Right: 100 Most Left: 0.
IE- Most Right: 0 Most Left: 100.
Firefox - Most Right: 0 Most Left: -100.
Solution #1
As mentioned by #Lucas Trzesniewski.
You could use this Jquery plugin:
https://github.com/othree/jquery.rtl-scroll-type
The plugin is used to detect which type is the browser are using.
Assign the result to jQuery's support object named 'rtlScrollType'.
You will need the scrollWidth of the element to transform between
these three types of value
Solution #2
Credits: jQuery.scrollLeft() when direction is rtl - different values in different browsers
I know you didn't want to include browser detection individually for each browser. With this example, only 2 extra lines of code are added for Safari and Chrome and it works like a charm!
Modified it to demonstrate it better for you.
$('div.Container').scroll(function () {
st = $("div.Container").scrollLeft() + ' ' + GetScrollLeft($("div.Container"));
$('#scrollLeft').html(st);
});
function GetScrollLeft(elem) {
var scrollLeft = elem.scrollLeft();
if ($("body").css("direction").toLowerCase() == "rtl") {
// Absolute value - gets IE and FF to return the same values
var scrollLeft = Math.abs(scrollLeft);
// Get Chrome and Safari to return the same value as well
if ($.browser.webkit) {
scrollLeft = elem[0].scrollWidth - elem[0].clientWidth - scrollLeft;
}
}
return scrollLeft;
}
JSFiddle:
http://jsfiddle.net/SSZRd/1/
The value on the left should be the same for all browser while the value on the right is the older value which is different on all browser. (Tested on Firefox, Safari, Chrome, IE9).
1. FF-latest scrollLeft starts at 0 and goes negative when scrolling left
2. IE 9 scrollLeft starts at 0 and goes positive when scrolling left
3. Chrome-latest scrollLeft starts at a higher number and goes to when scrolling left
I want to avoid having code like if(ie){...}else if(ff){...}else if(chrome){...}
that would be horrible, and not maintainable in the long run in case browsers change behavior
FYI:
Chrome 85 (final shipping Aug. 2020) fixed this bug and aligns behaviour with Firefox and Safari and the spec.
See https://www.chromestatus.com/feature/5759578031521792
Is there a feature detection available for this?
Yes, e.g. use one of two scrips (from Frédéric Wang) available here:
https://people.igalia.com/fwang/scrollable-elements-in-non-default-writing-modes/
either this
function scroll_coordinates_behavior_with_scrollIntoView() {
/* Append a RTL scrollable 1px square containing two 1px-wide descendants on
the same line, reveal each of them successively and compare their
scrollLeft coordinates. The scrollable square has 'position: fixed' so
that scrollIntoView() calls don't scroll the viewport. */
document.body.insertAdjacentHTML("beforeend", "<div style='direction: rtl;\
position: fixed; left: 0; top: 0; overflow: hidden; width: 1px; height: 1px;'>\
<div style='width: 2px; height: 1px;'><div style='display: inline-block;\
width: 1px;'></div><div style='display: inline-block; width: 1px;'></div>\
3</div></div>");
var scroller = document.body.lastElementChild;
scroller.firstElementChild.children[0].scrollIntoView();
var right = scroller.scrollLeft;
scroller.firstElementChild.children[1].scrollIntoView();
var left = scroller.scrollLeft;
/* Per the CSSOM specification, the standard behavior is:
- decreasing coordinates when scrolling leftward.
- nonpositive coordinates for scroller with leftward overflow. */
var result = { "decreasing": left < right, "nonpositive": left < 0 };
document.body.removeChild(scroller);
return result;
}
or that
function scroll_coordinates_behavior_by_setting_nonpositive_scrollLeft() {
/* Append a RTL scrollable 1px square containing a 2px-wide child and check
the initial scrollLeft and whether it's possible to set a negative one.*/
document.body.insertAdjacentHTML("beforeend", "<div style='direction: rtl;\
position: absolute; left: 0; top: 0; overflow: hidden; width: 1px;\
height: 1px;'><div style='width: 2px; height: 1px;'></div></div>");
var scroller = document.body.lastElementChild;
var initially_positive = scroller.scrollLeft > 0;
scroller.scrollLeft = -1;
var has_negative = scroller.scrollLeft < 0;
/* Per the CSSOM specification, the standard behavio999r is:
- decreasing coordinates when scrolling leftward.
- nonpositive coordinates for scroller with leftward overflow. */
var result = { "decreasing": has_negative ||
initially_positive, "nonpositive": has_negative };
document.body.removeChild(scroller);
return result;
}

jQuery - have popup box appear on screen regardless of how low they scroll

I'm trying to create a popup box on a list of items that goes very much to the bottom of the browser.
I want the POPUP to be in the center of the page where the user is at regardless of how low they scrolled
i have to use POSITION ABSOLUTE not FIXED
but when i use POSITION ABSOLUTE the popup always appears on top and i know its due to my top: 0
.lightbox-container{
border: solid red 1px;
width: 100px;
height: 40px;
background: yellow;
position: absolute;
top: 0;
}
I want to use something like scrollTop or one of those to get the popup to always stay in the users viewpoint regardless of how low they scrolled
$('a').on('click', function(e){
var lightBox = $('<div class="lightbox-container"> <p>click to remove</p>');
lightBox.appendTo('body');
$('.lightbox-container').on('click', function(e){
$(this).remove();
});
});
here is the fiddle im working on http://jsfiddle.net/2RNAN/1/
I know there are other posts about this but im very new to jquery and cant seem to get it working.
This works working fiddle here
$('a').on('click', function (e) {
e.preventDefault();
var lightBox = $('<div class="lightbox-container"> <p>click to remove</p>');
lightBox.appendTo('body');
$('.lightbox-container').css('top', $(document).scrollTop() + 'px');
$('.lightbox-container').on('click', function (e) {
$(this).remove();
});
});
$(document).on('scroll', function () {
$('.lightbox-container').css('top', $(document).scrollTop() + 'px');
});
Edit: I think its a bit unclean and also unnecessary to center the pop-up box via jQuery. You can easily do this with CSS. Check out my updated JsFiddle: http://jsfiddle.net/kCC8p/9/ Edit End
I set the overflow to hidden on the body and included the pop-up outside the scrollable element. This way the scroll position of the user doesn't matter anymore.
JS
var lightbox = $('.lightbox-container');
$('a').click(function(e) {
e.preventDefault();
lightbox.show();
lightbox.addClass('open');
lightbox.append('<p>Click to remove</p>');
});
lightbox.click(function(e) {
lightbox.removeClass('open');
lightbox.find('p').remove();
$(this).hide();
});
See rest on jFiddle...
I may be a little late but I think this might be closer to what you were after:
Working Example
$(function () {
var lightbox = $('.lightbox-container'),
center = function () {
var T = $(window).height() / 2 - lightbox.height() / 2 + $(window).scrollTop(),
L = $(window).width() / 2 - lightbox.width() / 2;
lightbox.css({
top: T,
left: L
}).click(function () {
$(this).hide();
});
};
$('a').click(function (e) {
e.preventDefault();
lightbox.show().text('Click to remove');
center();
});
$(window).scroll(center);
$(window).resize(center);
});
Note that this method centers the popup and keeps it centered regardless of scrolling or re-sizing.
Are you avoiding the use of position fixed due to IE9 compatibility or some other reason? Using position fixed is probably the simplest answer and then address whatever compatibility issue you're having with specific browsers, such as with this answer for IE9 regarding quirks mode.

Customizing cursor images in scrolling div

I have a div that scrolls content when the cursor is either at the top or bottom (scrolling up or down). I have two customized cursor images- one is supposed to show when the div content is scrolling up and the other when the div content is scrolling down. The script below was written by a stackoverflow member and works only when using standard cursor styles such as wait, pointer, etc. I want to use images, but cannot get it to work correctly. I also do not need the timer in the script below.
<script type='text/javascript' >
var top=0, timer;
$('#repertoirescroll').on('scroll', function() {
clearTimeout(timer);
var scrollTop = $(this).scrollTop(),
cursor = scrollTop > top ? 'pointer' : 'wait';
$('body').css('cursor', cursor);
top = scrollTop;
timer = setTimeout(function() {
$('body').css('cursor', 'default');
}, 500);
});​
</script>
The image names I am using are
url(../images/arrowup.png)
url(../images/arrowdown.png)
*HTML/CSS**
.cursorup {
cursor: url(../images/arrowup.png), auto;
position:relative;
}
.cursordown {
cursor: url(../images/arrowdown.png), auto;
position:relative;
}
scrolling content
Thanks for any help in advance.
To use custom cursors, you use CSS styling:
.curarrowup {
cursor: url(../images/arrowup.png), auto;
}
Then to apply, use jQuery to apply the style:
$(myElement).addClass("curarrowup");
When you want to go back to a normal cursor:
$(myElement).removeClass("curarrowup");
Using $('body') (myElement === 'body') as in your example is fine.
One caveat: in Firefox, the new cursor often will not appear until you actually move the mouse. This is a known bug and I cannot find any workarounds.
Edit: Modifying your code:
var top=0, timer;
$('#repertoirescroll').on('scroll', function() {
var scrollTop, cursor;
clearTimeout(timer);
scrollTop = $(this).scrollTop();
cursor = scrollTop > top ? 'curarrowup' : 'curarrowdown';
$('body').addClass(cursor);
top = scrollTop;
timer = setTimeout(function() {
$('body').removeclass(cursor);
}, 500);
});​

Change Div Y Position with mouse wheel and sidebar

I need that when I scroll down or up with mouse wheel or sidebar my div change incrementally the Y position (for example 50px up or down ). I need this in Javascript/Jquery.
I Try this code, but only works for scrolling down(The Scrolling Down and Up Function is working well, only the animate part is working wrong):
UPDATE:
var sidebarScrollTop = 0;
$(document).ready(function() {
sidebarScrollTop = $("body").offset();
$(window).scroll(function ()
{
var docScrollTop = $('body,html').scrollTop();
if(docScrollTop > sidebarScrollTop.top)
{
$("#legend").stop().animate({ marginTop: "+=50px",}, 'slow', "easeOutCirc" );
}
else
{
$("#legend").stop().animate({ marginTop: "-=50px",}, 'slow', "easeOutCirc" );
}
});
});
$(window).resize(function()
{
sidebarScrollTop = $("#legend").offset().top;
});
$(document).resize(function()
{
sidebarScrollTop = $("#legend").offset().top;
});
Thanks
You can use
$(window).scroll(function() {
// Your scroll code here
});
to grab whenever the user is scrolling on the page.
Next you want to change the div's y-value.
If the div is positioned absolute, this is just changing its top-value.
$('my-div').top = original-top-value + $(window).pageYOffset;
I believe you need is to keep the div always showing even when user scrolls down. If that is the case then it can be done with only CSS:
div {
position: fixed;
z-index: 100;
top: 100px;
left: 100px;
}
The values of z-index, top and left are dummy values. Change em with your ones.
UPDATE:
Since CSS Solution won't work for you, here is a working example writter in JS: http://jsfiddle.net/qCtt5/

Categories