Windows 8 has this neat feature where you scroll through your apps by "pushing" the side of the screen.
I want to know if anyone has any ideas to accomplish this in JavaScript.
Essentially, the screen does should NOT scroll if you hover over the side of the screen, but should rather be able to detect when the user is attempting to go beyond the viewport and cannot.
Is such a thing possible?
Sure, you just need to figure out their algorithm if you want to duplicate it.
You can track the last several known locations of the pointer to determine velocity and direction and stop the scrolling as soon as the direction changes, for example.
I'm using something along the lines of:
$(window).mousemove(function (e) {
if (getIsPageEdge()) {
if (lastX == e.pageX) {
console.debug('pushing the page');
}
var now = new Date().getTime();
if (lastUpdate == null || now - lastUpdate > 500) {
lastUpdate = now;
lastX = e.pageX;
}
}
});
Essentially, onmousemove, if the cursor is at the edge of the viewport, and the X value is not changing (with a time delay added to compensate for the event processing delay), then change the scroll position of the containing div.
Related
My team and me are developing a web application which bears a fixed header, that doesn't scroll.
In order to handle overscrolling on iOS, we need to detect scrolling in negative direction and reposition the fixed header as static again to make it scroll along with the rest of the page.We do this by binding a jQuery scroll handler to window:
$(window).scroll(function() {
if ($(window).scrollTop() < 0) {
// position static header postioning in order
// let the header behave correctly when overscrolling
}
});
This works well, when the page is manually pulled (dragged) down.
But as every iOS user knows, when scrolling the page from a downwards position with speed up again, it bounces (overscrolls), once it reaches its top.
In this case, our scroll handling doesn't work.
At the moment I can imagine two reasons, why this different behaviour occurs:
Rapid scrolling upwards, and making a page bounce, is too fast for Safari's JS engine to ensure a fluid handling
Is bouncing when scrolling upwards technically the same as manually pulling down a webpage? In respect to $(window).scrollTop() ?
Has anybody some hints how to make my scroll handling work in both cases?
If position:fixed in CSS isn't working for you, then you should try to make a draw loop, and every single time that loop runs, you place a horizontal offset that is equal to how far your user has scrolled.
Basically, your JS should look like this if CSS doesn't work:
var head = document.getElementById("header");
//head now has our header
head.style.position = "relative";
//and now, we can manipulate it's position
function draw(){
head.style.top = window.pageYOffset;
//all that's left to do is do this each and every frame.
}
And if you don't know how to make a draw loop, here's the code:
var frameRate = 60;
var frameCounter = (function(){
var counter = 0;
return function(){
counter ++;
if(counter > frameRate/1000){
counter -= frameRate/1000;
draw();
}
}
})();
setInterval(frameCounter, 1);
This has been resolved in iOS 9.3 New meta tag option
<meta name="viewport"content="width=device-width,shrink-to-fit=no">
Example http://jsfiddle.net/5MsUd/
I am having issues with this code for the scroll up and down effect. The key issue is this:
//create the event listener of the users choice.
window.addEventListener(this.trigger,function(){
//get the current position of scroll and add it to the object
self.scrollPos= this.scrollY || this.pageYoffset;
//get the current position of the element
newPos = getPosition(self.target,self.dir);
//HERE IS THE BIG ISSUE!!!!!!!
//adjust the current position depending on the scroll direction
if(scrollex.direction == "down"){
self.target.style[self.dir]= newPos + (self.scrollPos * self.offset)+"px";
}else{
self.target.style[self.dir]= newPos - (this.scrollY * self.offset)+"px";
}
//run callback if there is one
if(callback !== null && typeof callback=='function'){
callback.call(self);
}
}, false);
I'm not getting the correct PXs to go back to the correct position. I added the fiddle as that has all the major code with notes. As well as extra functions that I've added to help assist this scrollex function
Can anyone suggestion a better mathematical equation to get the correct pxs back and forth. Try it out and play with it, let me know of any good suggestions. I've gone pretty deep with this and have more to add but as of now the scroll down and up part system is majorly buggy. You can see once you start scrolling back and forth it does move back and forth but moving up gives less pixels than what down did.
I've been struggling with this for a while, and I'm surprised that doing this isn't more straightforward...
I need to detect when the user scrolls a page, either with the mouse, scrollbar or by touch on mobile devices. jQuery has their scroll() function which works alright, but it requires that the page is actually scrolling. I want to detect the scrolling wether the page is scrolling or not (say I reach the end of the page, and there is nowhere left to scroll too.. I still want to know if the user is trying to scroll)
I found another question that had asked something similar, along the lines of detecting scroll input even when the page isn't scrolling, and I got this chunk of code:
if (document.addEventListener) {
document.addEventListener("mousewheel", MouseWheelHandler(), false);
document.addEventListener("DOMMouseScroll", MouseWheelHandler(), false);
} else {
sq.attachEvent("onmousewheel", MouseWheelHandler());
}
function MouseWheelHandler() {
return function (e) {
var e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
if (delta < 0) {
// increase scroll amount
} else {
// decrease scroll amount
}
}
return false;
}
At first, this seemed to do the trick, but I'm finding it doesn't really return balanced results with different types of mice, and didn't work too smoothly with touch events, which is the core aspect of this question.
I'm using this in a project that does a lot of fancy events on scroll, with the actual page not actually scrolling at all... But I'm running into the problem of it being incredibly slow with all my standard mice, but incredibly fast on my Apple Magic Mouse. I know that there will naturally be some difference here, as the magic mice do scroll quicker, but the difference is far more off balance than it is between the mice normally.
I'm hoping there is a way to improve upon this to get a more reliable result, with all sorts of different inputs. Any suggestions?
Edit:
To clarify, in order for an answer to work for me, it needs to work on an element which is not scrollable. I have a page which does not scroll at all, but which has other events that fire when the user scrolls. This means that I cannot use properties that are based on the window's scroll position (such as scrollTop()).
You should use window.onscroll most usage and then create a new listener to deal specifically with top and bottom scroll conditions I would suggest using a mousewheel event for desktop browsers and a specifically coded touch responder like below to detect if they are trying to scroll, what direction and if that is possible at the current window.scrollY value.
var isOverScroll = function isOverScroll ( touchStartY, touchEndY ) {
if ( Math.abs( touchStartY - touchEndY ) < 5 ) &&
( ( window.scrollY = window.innerHeight && touchStartY - touchEndY > 0 ) ||
( window.scrollY = 0 && touchStartY - touchEndY < 0 ) ) ) {
return false;
}
return true;
}
There is no way to detect scrollbar events, combine this with your current code and only trigger mouse wheel and touch events if the scrollY position is at either 0 or max.
On a side note if you are trying to get rid of the scroll bar completely that is a very bad idea as it is both a wonderful tool for users as well as something that is a standard part of the ui. If you trying to do a scrollable fullpage app and don't want a scroll bar try using slides. Either way don't continue setting the scroll value thats slow instead just move the whole body using css:
transition: transform3d( 0, YOURSCROLLVALUE , 0);
One possible solution is using a plugin for scrolling like
ISCROLL
in this example here :
Example
they use the feature pull to refresh , which will fire upon reaching the maximum scroll available , here by you can use any custom function (even if your item is not scrollable ).
I am currently developing a webpage for an iPhone which contains a DIV element that the user can touch and drag around. In addition, when the user drags the element to the top or bottom of the device's screen, I want to automatically scroll the page up or down.
The problem I am having is trying to determine a reliable formula to get the coordinates in the onTouchMove event that coorespond with the user's finger reaching the top or the bottom of the device viewport. My current formula seems tedious and I feel there may be an easier way to do this.
My current formula to determine if the touch event has reached the bottom of the screen:
function onTouchMoveHandler(e)
{
var orientation=parent.window.orientation;
var landscape=(orientation==0 || orientation==180)?true:false;
var touchoffsety=(!landscape?screen.height - (screen.height - screen.availHeight):screen.width - (screen.width - screen.availWidth)) - e.touches[0].screenY + (window.pageYOffset * .8);
if(touchoffsety < 40) alert('finger is heading off the bottom of the screen');
}
I have done a bit of Javascript reflection on objects such as the window, document, body, e.touches to see if I could find a set of numbers that would always add up to equal the top or bottom of the screen, but without reliable success. Help with this would be greatly appreciated.
Assuming the screenY field of a touch holds the y coordinate relative to the screen-top regardless of current scroll position, your current calculation does not make a whole lot of sense to me. I hope I did not misunderstand what your trying to do.
To find out if a touch is close to the top or the bottom of the device, I would first check if screenY is close to top (top being 0), since you can work with that value directly. Then, if it's not close to top, calculate how close it is to the bottom and check that.
var touch = e.touches[0];
if (touch.screenY < 50)
{
alert("Closing in on Top");
}
else //Only do bottom calculations if needed
{
var orientation=parent.window.orientation;
var landscape=(orientation==0 || orientation==180)?true:false;
//height - (height - availHeight) is the same as just using availHeight, so just get the screen height like this
var screenHeight = !landscape ? screen.availHeight : screen.availWidth;
var bottomOffset = screenHeight - touch.screenY; //Get the distance of the touch from the bottom
if (bottomOffset < 50)
alert("Closing in on Bottom");
}
That's actually not bad. You could also use Zepto.js and its built-in touch events and .offset() method to get it a little easier:
http://zeptojs.com/#touch
http://zeptojs.com/#offset
However, I'm interested to know whether or not you actually manage to get it scrolling at the bottom, and if the performance is smooth enough to make the effect worthwhile. (frequently scrolling in iOS interrupts JavaScript really hard)
in javascript can I make sure that my large div scroll vertically
only in chunks of (let's say) 16 pixels
In java, those are called 'units of increment'.
I can't find anything similar in javascript:
I want to ensure that a certain area (div) when partially scrolled is always a multiple of 16 the view.
That allows me to do tricks with background images and others.
thanks
var lastScroll = 0;
$('div').scroll(function(){
var el = $(this),
scroll = el.scrollTop(),
round = lastScroll < scroll ? Math.ceil : Math.floor;
lastScroll = round(scroll/16) * 16;
el.scrollTop(lastScroll);
});
http://jsfiddle.net/m9DQR/2/
Ensures scrolls are done in multiples of 16 pixels. You can easily extend this to be a plugin that allows for a variable amount (not a fixed, magical 16).
Yes, this is possible, but it will require using javascript to capture the scroll event and then manipulate it. This script (sorry jQuery is what I had) and overrides the scroll event. It then replaces it with the exact same scroll distance. You could perform your own math to adjust the value of scrollTo. We have to check both mousewheel and DOMMouseScroll events because the first is not supported by FF. This doesn't seem to apply in your case, but a user may have the number of lines to scroll set to something other than the default three. So the if statement calculates the distance. I left it in there though in case other people stumble on this question and it is important to them though.
$('body').bind('mousewheel DOMMouseScroll', function(e) {
var scrollTo = null;
if (e.type == 'mousewheel') {
scrollTo = (e.wheelDelta * -1);
}
else if (e.type == 'DOMMouseScroll') {
scrollTo = 40 * e.detail;
}
//adjust value of scrollTo here if you like.
scrollTo = 16;
if (scrollTo) {
e.preventDefault();
$(this).scrollTop(scrollTo + $(this).scrollTop());
}
});
Coming from another programming language I also found JavaScript difficult when dealing with UI. In your case I would just set a handler to the event onscroll and query the position of the div relative to the scroll position. Return false whenever position of div is not divisible by 16px and create a counter to allow reposition after another 16px is scrolled.