I'm trying to set the scroll position on a page so the scroller is scrolled all the way to the top.
I think I need something like this but it's not working:
(function () { alert('hello'); document.body.scrollTop = 0; } ());
Any ideas?
You can use window.scrollTo(), like this:
window.scrollTo(0, 0); // values are x,y-offset
Also worth noting window.scrollBy(dx,dy) (ref)
Note that if you want to scroll an element instead of the full window, elements don't have the scrollTo and scrollBy methods. You should:
var el = document.getElementById("myel"); // Or whatever method to get the element
// To set the scroll
el.scrollTop = 0;
el.scrollLeft = 0;
// To increment the scroll
el.scrollTop += 100;
el.scrollLeft += 100;
You can also mimic the window.scrollTo and window.scrollBy functions to all the existant HTML elements in the webpage on browsers that don't support it natively:
Object.defineProperty(HTMLElement.prototype, "scrollTo", {
value: function(x, y) {
el.scrollTop = y;
el.scrollLeft = x;
},
enumerable: false
});
Object.defineProperty(HTMLElement.prototype, "scrollBy", {
value: function(x, y) {
el.scrollTop += y;
el.scrollLeft += x;
},
enumerable: false
});
so you can do:
var el = document.getElementById("myel"); // Or whatever method to get the element, again
// To set the scroll
el.scrollTo(0, 0);
// To increment the scroll
el.scrollBy(100, 100);
NOTE: Object.defineProperty is encouraged, as directly adding properties to the prototype is a breaking bad habit (When you see it :-).
... Or just replace body by documentElement:
document.documentElement.scrollTop = 0;
If you want to set the scroll position of document.body, you can scroll the entire window altogether using window.scrollTo(); it takes either a pair of coordinates (x,y) or an options object – if you just want to scroll nicely to the top, try window.scrollTo({top:0,behavior:'smooth'});.
However, in some instances, you have an element to scroll (and not the entire document). For that case, elements also provide a scrollTo() method using the same arguments.
document.querySelector('ul#list').scrollTo(0,0);
Related
I would like to trigger something once (and only once) a user has scrolled down 100 pixels from the top.
In the past I was given this code, but it doesn't seem to be working?
window.onscroll = function() {
var scrollLimit = 100;
var scrollValue = document.body.scrollTop;
if (scrollValue >= scrollLimit) {
alert("x")
}
};
You are using the wrong property here.
Instead of scrollTop property you need to use the Window.scrollY property.
This is how should be your code:
window.onscroll = function() {
var scrollLimit = 100;
if (window.scrollY >= scrollLimit) {
alert("x")
}
};
Note:
window.scrollY compatibility issues with IE:
Unfortunately window.scrollY doesn't work with IE browsers, for IE you can use window.pageYOffsetas a replacement, but it always gives hundreds rounded values (100, 200, 300, ...).
Otherwise you can check the accepted answer here it uses document.documentElement.scrollTop as a workaround.
Try this:
var scrollValue = window.scrollY;
scrollTop will give you the offset between the top of the element and the top of the document. Since the body of a html document by default starts at the top of the document, body.scrollTop always stays 0 unless you specifically used css to make the body not start at the top.
So you have to use scrollY instead of scrollTop. If the browser you use does not support scrollY ( eg. IE ) you can try pageYOffset.
So I am trying to show a tooltip like box as I scroll my webpage and I would like it to follow the scrollbar along the right side of the page.
I looked around and found something to attempt to accomplish that as shown below:
function returnPercentHeight(){
var a = document.getElementById('rightPanel').scrollTop;
var b = document.getElementById('rightPanel').scrollHeight - document.getElementById('rightPanel').clientHeight;
return ((a/b) * 100);
}
I then append a % to the end and set the top margin of the tooltip to that returned value. This works pretty well (sort of) I have to adjust the return((a/b) * x) part (x) to make it follow the scrollbar based on the size of the browser window. Is there a better way to accomplish what I am trying to do? (NOTE: I can only use javascript, no JQuery please.)
EDIT:
Only the div given an ID of 'RightPanel' is scrolling, I am not using the scrollbar on the browser, but a scrollbar on an inner div.
There are three ways to do so:
First:
is to use the fixed position as following;
Position: Fixed;
Second:
With jQuery;
$(function(){
$(window).on('scroll', function() {
var scrollPOS = $(document).scrollTop();
$('.scroll').css({
top: scrollPOS
});
}).scroll();
});
Third:
Same as the previous, only animated;
$(window).on('scroll', function() {
$("#div").stop().animate({
"marginTop": ($(window).scrollTop()) + "px",
"marginLeft":($(window).scrollLeft()) + "px"}, "slow" );
});
Although IE doesn't support, this is the coolest I've seen:
// get
var x = window.scrollX,
y = window.scrollY;
// set
window.scrollTo(1, 2);
I've looked everywhere and so far have not found a non-jQuery js to handle this. I would like to avoid using a library for just this one simple task.
I would like to fix three navigation divs ("#header", "#tabs" and "#footer") to viewport left (or alternatively, to the x position of a div "#helper" with "position: fixed; left: 0; top: 0;") -- but not fix y. They can not be vertically fixed.
I've created a working js that forces the divs to reposition based on scrolling, but it's not smooth in the real page (too many dynamic and graphic elements) - I'd like it to either animate smoothly, or mimic fixed-left and not appear to reposition at all.
Anyone who can give pointers or a quick script, or review and modify the script I have made? I've noticed people tend to ask why an obvious solution is not used instead of answering the question... I will be glad to answer, but would prefer help with the actual problem.
Here is a jsFiddle with the problem: http://jsfiddle.net/BMZvt/6/
Thank you for any help!
Smooth animation example:
var box = document.getElementById('box');
var moveTo = function(obj, target) {
// start position
// you should obtain it from obj.style
var cpos = {
x: 0,
y: 0
}
var iv = setInterval(function(){
cpos.x += (target.x - cpos.x) * 0.3; // 0.3 is speed
cpos.y += (target.y - cpos.y) * 0.3; // 0.3 is speed
obj.style.left = Math.floor(cpos.x) + 'px';
obj.style.top = Math.floor(cpos.y) + 'px';
var dist = Math.abs(cpos.y - target.y); // distance (x+y) from destination
dist += Math.abs(cpos.x - target.x); // < 1 = object reached the destination
if(dist < 1) { // here we are checking is box get to the destination
clearInterval(iv);
}
}, 30); // this is also the speed
}
box.onclick = function(){
moveTo(box, {x: 90, y: 75}); // fire this function to move box to specified point
}
Demonstration: http://jsfiddle.net/Qwqf6/5/
Your script is your job, but this is a quick start how to solve animation problem
You can also do some fancy stuff with speed for example use sin(x) to set the speed
Demonstration #2 http://jsfiddle.net/Qwqf6/6/ (very smooth)
Full script here https://gist.github.com/3419179
I don't think there's a straight way to do this...
But here's a way.
First, You need to be able to detect the direction of the scrolling when window.onscroll event happens. You would do this by comparing the current page offsets with the newly acquired page offsets whenever the scroll event happens. (http://stackoverflow.com/questions/1222915/can-one-use-window-onscroll-method-to-include-detection-of-scroll-direction)
Now suppose you know the direction of the scroll, you want to change the styling for the divs depending on the direction of the scroll.
Let FixAtX be the value of the x coordinate that you want to fix your divs at.
Let OriginalY be the y coordinate of the divs.
Also whenever scrolling happens, despite of the direction, you want to remember the pageoffset X and Y. Let's call them OldX and OldY
If scrolling vertically:
Set position value for divs' style to be absolute.
Set top value for divs' style to be OriginalY
Set left value for divs' style to be OldX + FixAtX
If scrolling horizontally:
Set position value for divs' style to be fixed.
set top value for divs' style to be OriginalY - OldY (<- this may be different depending on how the browser computes pageOffset value,)
Set Left value for divs' style to be FixAtX
I think this should work...
Since you are just using browser's rendering for positioning, it should be very smooth!
hope I understood the question correctly.
This is for people who view this post - I wound up going with the solution I initially put together in the jsFiddle that used a simple javascript to mimic fixed x.
The javascript in the first answer was hefty and wound up buggy, and the second answer sounded good but did not work in practice. So, I'm recommending the javascript from the jsFiddle (below) as the best answer to fixed x and fluid y without a javascript library. It's not perfect and has a minimal delay but is the best answer I've found.
function fixLeft() {
function getScrollX() {
var x = 0, y = 0;
if( typeof( window.pageYOffset ) == 'number' ) {
x = window.pageXOffset;
} else if( document.body && ( document.body.scrollLeft) ) {
x = document.body.scrollLeft;
} else if( document.documentElement && ( document.documentElement.scrollLeft) ) {
x = document.documentElement.scrollLeft;
}
return [x];
}
var x = getScrollX();
var x = x[0];
// have to get and add horizontal scroll position px
document.getElementById('header').style.left = x + "px";
document.getElementById('tabs').style.left = x + "px";
document.getElementById('footer').style.left = x + "px";
}
window.onscroll = fixLeft;
What is the best way to restore the scroll position in an HTML document after the screen has been rotated? (This is in a Cocoa Touch UIWebView, but I think it's a problem everywhere.) The default behavior seems to restore the y-offset in pixels, but since the text has been reflowed this is now a different position in the document.
My initial thought is to:
Pepper the document with invisible, uniquely-id'ed elements.
Before rotation, search for the element e whose y-offset is closest to the scroll offset.
After rotation, update the scroll offset to e's new y-offset.
Even if that works, I'd prefer not to insert a bunch of crud into the document. Is there a better way?
Here's a diagram to clarify the problem. Restoring the original y-offset does not produce the intended result because more text fits on a line in landscape mode.
Not pretty but it works. This requires there to be span tags throughout the document text.
// Return the locator ID closest to this height in pixels.
function findClosestLocator(height) {
var allSpans = document.getElementsByTagName("span");
var closestIdx = 0;
var closestDistance = 999999;
for(var i = 0; i < allSpans.length; i++) {
var span = allSpans[i];
var distance = Math.abs(span.offsetTop - height);
if(distance < closestDistance) {
closestIdx = i;
closestDistance = distance;
}
}
return allSpans[closestIdx].id;
}
After rotation, document.getElementById(spanId).offsetTop is the new y-offset, where spanId is the result of findClosestLocator() before rotation.
Conceptually the problem isn't so hard to think about. You have scroll events, rotation events, and variables. I would track the scrollTop position on the document.body DOM node on the scroll event. Reapply it with the orientation event fires.
Something like this perhaps.
// Track position
var pos;
// On scroll update position
document.body.addEventListener("scroll", function() {
pos = document.body.scrollTop;
}, true);
// On rotation apply the scroll position
window.addEventListener("orientationchange", function() {
document.body.scrollTop = pos;
}, true);
Tracing this jquery autocomplete function, can someone explain in detail what is going on here?
function showResults() {
// get the position of the input field right now (in case the DOM is shifted)
var pos = findPos(input);
// either use the specified width, or autocalculate based on form element
var iWidth = (options.width > 0) ? options.width : $input.width();
// reposition
$results.css({
width: parseInt(iWidth) + "px",
top: (pos.y + input.offsetHeight) + "px",
left: pos.x + "px"
}).show();
};
It uses this function:
function findPos(obj) {
var curleft = obj.offsetLeft || 0;
var curtop = obj.offsetTop || 0;
while (obj = obj.offsetParent) {
curleft += obj.offsetLeft
curtop += obj.offsetTop
}
return {x:curleft,y:curtop};
}
Reference: http://www.pengoworks.com/workshop/jquery/lib/jquery.autocomplete.js
offsetLeft and offsetTop are properties that describe how many pixels obj is offset from it's containing element. What this function does is:
Compute the offset of obj from its parent element and save these values in variables
Set obj to be the parent element of the item last computed from
Goto 1. Repeat until you have reached the top level of the DOM.
This calculates how many pixels that obj is from the top and left sides of the rendered page.
Basically, it's figuring out the X and Y coordinates (left and top in CSS terms) of the input field you're using autocomplete on and setting the top and left CSS attributes of the autocomplete HTML to have it appear there. In other words, it's matching up the corners of the input Element and autocomplete layer so they appear at the same place (it's doing the same with widths and heights, too).
In the findPos function, we're basically walking back up the DOM tree getting the offsets (see Mozilla's dev center) of each Element from their parent (and eventually the body tag) to get the precise x and y coordinates of that input so that we can position the autocomplete layer at it's coordinates. We sum these, and wind up with the x and y values we pass back up to use in setting the left and top positions in CSS.
It's essentially copying the x and y position, height, and width of your input and applying them to the autocomplete layer so that they match up visually.