Fixed position scrolling and fastclick button elements inside scroller - javascript

I'm making a little webapp for the iPad as a personal project. It has two iScroll (http://cubiq.org/iscroll-4) scrollers and a lists of divs inside it.
I initially used a single ontouchstart listener to select the rows but that would select the row even when swiping to scroll. So later I added in ontouchmove (sets a flag to stop event firing in ontouchend) and ontouchend. But I still have to outstanding issues:
Tapping to stop the momentum scrolling will select the row,
Implementing 'fastClick' (https://github.com/alexblack/google-fastbutton) on the row element inside the scroller disables the scrolling.
Any help on where to look to implement/fix these would be great.
Thanks in advance.
EDIT: I'm also trying to figure out how to stop fastClick from triggering the event when a touchstart event is triggered before touchmove. This means that the event fires even though the final touch coords where way outside the area of the 'button'.

Related

Javascript/jQuery/CSS. How do I maintain drag events outside the target div?

I am implementing a scrollbar using jQuery/Javascript/CSS. The usual. Everything is going according to plan except for the following use case:
The user mouses down in the scrollbar div hosting mousedown/mousemove/mouseup event handlers. The user initiates a drag gesture - mousemove starts firing - that soon moves the cursor outside the bounds of the scrollbar div and onto the surrounding div real estate on the web page. The moment this happens, mousemove - as expected - stops firing events.
How do I continue to have mousemove fire events without resorting to just attaching a mousemove handler to the root div? How do I maintain scrollbar dragger translation even though the cursor has wandered off the scrollbar?
Thanks,
Doug
Instead of using onmousemove on the element, use it on the document.

Preventing iPad top page drag

I'm trying for numerous days to solve the following issue.
I have a menu located on the top of the page which needed to be open using swipedown event (I'm using Hammer.js jQuery version).
Problem is, every time I try to interact using swipes I either scroll the page (swipeup) or pulling the page down same as described in the following question.
Here is what I've tried so far:
overflow: hidden; on the body element with an inner container with overflow: auto, swipe on top element still triggered document scroll.
Setting preventDefault on the document also disabled lower elements events in the DOM hierarchy and by that I had no swipe events working in the page.
Also tried using stopPropagation on the actual element when the event occurs, to prevent the bubbling up the chain for the event, the result cause the object to not respond to the events (swipes) and document scroll worked with no problems.
Any ideas how can I still keep page scroll but also when using common gestures, such as swipedown/swipeup, on specific elements that the element only will be affected?
Here is an example using JSFiddle, to better demonstrate the issue.
Would appreciate ideas/thoughts
I don't know if this will help, but I've always liked to use drag more than swipe. Using Hammer on my projects, swipes were a bit finicky. And from a UX standpoint, drag feels instantaneous vs a swipe. Much like, mousedown vs mouseup/click. So in instances where it's appropriate, and I believe in the case of showing swipey menu it is, I'd opt for drag.
Replacing your example with drag rather than swipe, and also using CSS transition, -webkit-transition, rather than jQuery's animate (drag will trigger like a mousemove, vs a click or a mouseup) seemed to make it work.
Hammer('.nav').on('dragdown', function(e){
e.gesture.preventDefault()
$(".blue").html("down")
$('.nav').css({"top":"0px"});
})
.on('dragup', function(e){
e.gesture.preventDefault()
$(".blue").html("dragup")
$('.nav').css({"top":"-150px"});
});
//Added in CSS, for .nav
.nav {-webkit-transition:0.5s top;}
Example
This does still have the page overscroll. A preventDefault() on document.ontouchstart would could fix that but that breaks scrolling. You might be able to do a selective preventDefault() by checking the scrollOffset perhaps. But I guess in the long run, I'd recommend something like iScroll.
Example
Also maybe tweak the hitbox for the drag to be a bit larger. Which I did in the last example. I attached the dragdown event on the document instead of the "menu" so the menu doesn't have to be visibly bigger.
Hammer(document).on("dragdown",function(e){
//calculate ratio of first touch from top
var pos=e.gesture.startEvent.center.pageY/window.innerHeight
if(pos<0.2){ //drag occurs in the first 20% of the screen
menu.style.marginTop="0px" //or animate here
e.gesture.preventDefault()
e.gesture.stopPropagation();
}
})
You should use the preventDefault function of the orginal gesture, to stop the browsers default behaviour, see here: https://github.com/EightMedia/hammer.js/wiki/Event-delegation-and-how-to-stopPropagation---preventDefaults
When you have a div element, on which you want to register swipe events, you would do the following:
$('#swipeDiv').hammer().on("swipe", function(ev) { ev.gesture.preventDefault(); });
That should prevent the scrolling of the page, but only if the swipe happens on the div element.

Knockout Click Binding Except When Dragging

I have sliders on my site that allow the user to select via dragging, or clicking on an item. When they drag, the item closest to the vertical center of the parent is chosen.
CodePen Demo
The problem is that the Knockout click binding is being bound before the jQuery UI draggable option (implemented in a custom binding).
To reproduce, try clicking and dragging on the bottom number, and move it up a little (but not in the center). Try doing that a few times, as it seems to work correctly on the first drag... sometimes.
The binding basically calls .draggable, and updates an observable when dragging stops.
The HTML is set up like this.
<ul data-bind="slideSelect: thing, foreach: nums">
<li data-bind="click: $root.thing.set($data), text: $data">1</li>
</ul>
Is there any way to make the draggable element stop the lis click events from firing? I'd like to do it in the cleanest fashion possible.
did you try event.preventDefault(); in on drag event handler? the idea is if you detect drag event then stop the event bubbling. if click happens before drag then i think you might have to wait to see if drag happens then complete the action.

Prevent touchmove event only for x axis and let page scroll for y axis in Safari Mobile and Android

I want to build a classical gallery where with the finger is possible to move the photo to left or right to see the next or previous photo.
I use jQuery binding the event touchstart, touchmove, touchend for calculate the positions of photos using the property event.pageX.
The problem is when moving finger the page begin to scroll. Immediatly the listener of touchmove stop to be invoked.
To fix the problem I had put in the touchmove listener the call event.preventDefault() and the listener was invoked regulary and the page stopped to scroll.
I want that the finger can move the photo and at the same time can scroll the page.
I see in the apple website this happen regulary (see this page http://www.apple.com/osx/)
and even this script do the same http://iosscripts.com/iosslider-jquery-horizontal-slider-for-iphone-ipad-safari/
I want to know the concept behind the scene. I can't understand what I have to do to fix that.
I even try to use preventDefault and set the $(window).scrollTop by hand calculated by the pageY but the effects was very ugly.

JavaScript pass mouseenter event to element that is underneath another element

I'm trying to build a little calendar app sort of like Google Calendar. I'm trying to create events with a click and drag functionality so that the events align to a grid. I'm trying to
tie the dragging to TD elements below the event DIV element, which works when moving downwards (lengthening the event), but it doesn't work moving upwards (shrinking the event).
What occurs is that the mouseenter event is fired for the event DIV element, but it is never fired for the underlying TD. If you try to resize the DIV by moving upwards on the side, it works because the TDs actually receive the mouseenter event.
Google Calendar and jQuery Week Calendar use the mousemove event, but the mousemove event is fired for every pixel, which seems a waste. Is there a way to write this without using the mousemove event?
Is it possible to put the DIV element behind the table and the TDs? If the table is somewhat transparent, the user would still be able to see the DIV, but would actually be firing events on the TDs. I tried to do this with z-index, but it didn't seem to actually work.
jsFiddle example code: http://jsfiddle.net/rockymeza/8SHpA/
It sounds like you're having a similar kind of issue that I had:
you want to fire event behind an element? The answer is CSS. Set pointer-events:none; to the parent.
I had made a test where I tried to (unsuccessfully) implement the same behavior on touch devices. You can check that at: http://www.hakoniemi.net/misc/pointer-events.html if it'd help you with your issue.

Categories

Resources