diff --git a/layout-iscroll2.html b/layout-iscroll2.html index d450001..f33b5e8 100755 --- a/layout-iscroll2.html +++ b/layout-iscroll2.html @@ -117,7 +117,10 @@ $(document).ready(function(){ window.MagazineScroller = makeScrollHandler($('.viewer'), { hScroll: true, vScroll: false, - callback: function(speed, distance){ + callback: function(speed, distance, touches){ + if(touches > 0){ + return true + } // XXX this is not too correct... // ...make this mode specific... if(getMagazineScale() >= 1){ diff --git a/layout.js b/layout.js index bcf972b..f790eac 100755 --- a/layout.js +++ b/layout.js @@ -74,196 +74,6 @@ var togglePageView = createCSSClassToggler( /************************************************** event handlers ***/ -// XXX make this more universal... -// - h/v scroll -// - general configuration -// - optional events... -// XXX should we use a callback or an event??? -// XXX make this get the scrolled item automatically... -// ...now $('.magazine') is hardcoded... -function makeScrollHandler(root, config){ - root = $(root) - - // local data... - var scrolled - var scrolling = false - var touch = false - var touches = 0 - var start_x - var start_y - var prev_x - var prev_y - var prev_t - var bounds - var shift - var scale - var x - var y - var t - var dx - var dy - var dt - - function startMoveHandler(evt, callback){ - prev_t = event.timeStamp || Date.now(); - if(scroller.options.autoCancelEvents){ - bounds = { - left: scroller.options.eventBounds, - right: root.width() - scroller.options.eventBounds, - top: scroller.options.eventBounds, - bottom: root.height() - scroller.options.eventBounds - } - } - scrolled = $(root.children()[0]) - setTransitionDuration(scrolled, 0) - if(event.touches != null){ - touch = true - } - scrolling = true - scroller.state = 'scrolling' - scroller.options.enabelStartEvent && root.trigger('userScrollStart') - //togglePageDragging('on') - shift = getElementShift(scrolled) - scale = getElementScale(scrolled) - // get the user coords... - prev_x = touch ? event.touches[0].pageX : evt.clientX - start_x = prev_x - prev_y = touch ? event.touches[0].pageY : evt.clientY - start_y = prev_y - - return false - } - // XXX add limits to this... - // XXX slow down drag when at limit... - // XXX try and make this adaptive to stay ahead of the lags... - function moveHandler(evt){ - evt.preventDefault() - t = event.timeStamp || Date.now(); - // get the user coords... - x = touch ? event.touches[0].pageX : evt.clientX - y = touch ? event.touches[0].pageY : evt.clientY - touches = touch ? event.touches.length : 0 - - // XXX needs testing... - // check scroll bounds... - if(bounds != null){ - if(scroller.options.hScroll && (x <= bounds.left || x >= bounds.right) - || scroller.options.vScroll && (y <= bounds.top || y >= bounds.bottom)){ - // XXX cancel the touch event and trigger the end handler... - return endMoveHandler(evt) - } - } - - // do the actual scroll... - if(scrolling){ - if(scroller.options.hScroll){ - shift.left += x - prev_x - } - if(scroller.options.vScroll){ - shift.top += y - prev_y - } - setElementTransform(scrolled, shift, scale) - - // XXX these should be done every time the event is caught or - // just while scrolling? - dx = x - prev_x - dy = y - prev_y - dt = t - prev_t - prev_x = x - prev_y = y - prev_t = t - - scroller.options.enableUserScrollEvent && root.trigger('userScroll') - } - return false - } - function endMoveHandler(evt){ - // XXX get real transition duration... - setTransitionDuration($('.magazine'), 200) - x = touch ? event.changedTouches[0].pageX : evt.clientX - y = touch ? event.changedTouches[0].pageY : evt.clientY - touch = false - scrolling = false - scroller.state = 'waiting' - touches = 0 - bounds = null - //togglePageDragging('off') - scroller.options.enableEndEvent && root.trigger('userScrollEnd', dx, dy, dt, start_x, start_y) - scroller.options.callback && scroller.options.callback(dx/dt, start_x-x) - - return false - } - - var scroller = { - options: { - hScroll: true, - vScroll: true, - - enabelStartEvent: false, - enableUserScrollEvent: false, - enableEndEvent: false, - - autoCancelEvents: false, - eventBounds: 5, - - callback: null - }, - - start: function(){ - this.state = 'waiting' - // XXX STUB: this makes starting the scroll a bit sluggish, - // find a faster way... - //togglePageDragging('on') - - // NOTE: if we bind both touch and mouse events, on touch devices they - // might start interfering with each other... - if('ontouchmove' in window){ - root - .on('touchstart', startMoveHandler) - .on('touchmove', moveHandler) - .on('touchend', endMoveHandler) - .on('touchcancel', endMoveHandler) - } else { - root - .on('mousedown', startMoveHandler) - .on('mousemove', moveHandler) - .on('mouseup', endMoveHandler) - } - return this - }, - stop: function(){ - this.state = 'stopped' - if('ontouchmove' in window){ - root - .off('touchstart', startMoveHandler) - .off('touchmove', moveHandler) - .off('touchend', endMoveHandler) - } else { - root - .off('mousedown', startMoveHandler) - .off('mousemove', moveHandler) - .off('mouseup', endMoveHandler) - } - return this - }, - // XXX check... - setCallback: function(func){ - this.callback = func - }, - // NOTE: this is updated live but not used by the system in any way... - state: 'stopped' - } - - // merge the config with the defaults... - if(config != null){ - $.extend(scroller.options, config) - } - - return scroller -} - - - /********************************************************* helpers ***/ // XXX make this more acurate... diff --git a/lib/jli.js b/lib/jli.js index 888faab..293c18d 100755 --- a/lib/jli.js +++ b/lib/jli.js @@ -488,6 +488,201 @@ function makeKeyboardHandler(keybindings, unhandled){ +// XXX handle multiple fingers... +// XXX setup basic styles for the contained element... +// XXX revise... +// XXX test on other devices... +function makeScrollHandler(root, config){ + root = $(root) + + // local data... + var scrolled + var scrolling = false + var touch = false + var touches = 0 + var start_x + var start_y + var prev_x + var prev_y + var prev_t + var bounds + var shift + var scale + var x + var y + var t + var dx + var dy + var dt + + function startMoveHandler(evt, callback){ + prev_t = event.timeStamp || Date.now(); + if(scroller.options.autoCancelEvents){ + bounds = { + left: scroller.options.eventBounds, + right: root.width() - scroller.options.eventBounds, + top: scroller.options.eventBounds, + bottom: root.height() - scroller.options.eventBounds + } + } + scrolled = $(root.children()[0]) + setTransitionDuration(scrolled, 0) + if(event.touches != null){ + touch = true + } + scrolling = true + scroller.state = 'scrolling' + scroller.options.enabelStartEvent && root.trigger('userScrollStart') + //togglePageDragging('on') + shift = getElementShift(scrolled) + scale = getElementScale(scrolled) + // get the user coords... + prev_x = touch ? event.touches[0].pageX : evt.clientX + start_x = prev_x + prev_y = touch ? event.touches[0].pageY : evt.clientY + start_y = prev_y + + return false + } + // XXX add limits to this... + // XXX slow down drag when at limit... + // XXX try and make this adaptive to stay ahead of the lags... + function moveHandler(evt){ + evt.preventDefault() + t = event.timeStamp || Date.now(); + // get the user coords... + x = touch ? event.touches[0].pageX : evt.clientX + y = touch ? event.touches[0].pageY : evt.clientY + touches = touch ? event.touches.length : 0 + + // XXX needs testing... + // check scroll bounds... + if(bounds != null){ + if(scroller.options.hScroll && (x <= bounds.left || x >= bounds.right) + || scroller.options.vScroll && (y <= bounds.top || y >= bounds.bottom)){ + // XXX cancel the touch event and trigger the end handler... + return endMoveHandler(evt) + } + } + + // do the actual scroll... + if(scrolling){ + if(scroller.options.hScroll){ + shift.left += x - prev_x + } + if(scroller.options.vScroll){ + shift.top += y - prev_y + } + setElementTransform(scrolled, shift, scale) + + // XXX these should be done every time the event is caught or + // just while scrolling? + dx = x - prev_x + dy = y - prev_y + dt = t - prev_t + prev_x = x + prev_y = y + prev_t = t + + scroller.options.enableUserScrollEvent && root.trigger('userScroll') + } + return false + } + function endMoveHandler(evt){ + // XXX get real transition duration... + setTransitionDuration($('.magazine'), 200) + x = touch ? event.changedTouches[0].pageX : evt.clientX + y = touch ? event.changedTouches[0].pageY : evt.clientY + touches = touch ? event.touches.length : 0 + + // XXX stop only if no fingers are touching or let the callback decide... + //togglePageDragging('off') + scroller.options.enableEndEvent && root.trigger('userScrollEnd', dx, dy, dt, start_x, start_y) + if(scroller.options.callback + // XXX revise this.... + && scroller.options.callback(dx/dt, start_x-x, touches) === false + || touches == 0){ + // cleanup and stop... + touch = false + scrolling = false + scroller.state = 'waiting' + bounds = null + } + + return false + } + + var scroller = { + options: { + hScroll: true, + vScroll: true, + + enabelStartEvent: false, + enableUserScrollEvent: false, + enableEndEvent: false, + + autoCancelEvents: false, + eventBounds: 5, + + // NOTE: if this returns false explicitly, this will stop scrolling. + callback: null + }, + // NOTE: this is updated live but not used by the system in any way... + state: 'stopped', + + start: function(){ + this.state = 'waiting' + // XXX STUB: this makes starting the scroll a bit sluggish, + // find a faster way... + //togglePageDragging('on') + + // NOTE: if we bind both touch and mouse events, on touch devices they + // might start interfering with each other... + if('ontouchmove' in window){ + root + .on('touchstart', startMoveHandler) + .on('touchmove', moveHandler) + .on('touchend', endMoveHandler) + .on('touchcancel', endMoveHandler) + } else { + root + .on('mousedown', startMoveHandler) + .on('mousemove', moveHandler) + .on('mouseup', endMoveHandler) + } + return this + }, + stop: function(){ + this.state = 'stopped' + if('ontouchmove' in window){ + root + .off('touchstart', startMoveHandler) + .off('touchmove', moveHandler) + .off('touchend', endMoveHandler) + } else { + root + .off('mousedown', startMoveHandler) + .off('mousemove', moveHandler) + .off('mouseup', endMoveHandler) + } + return this + }, + // XXX check... + setCallback: function(func){ + this.callback = func + } + } + + // merge the config with the defaults... + if(config != null){ + $.extend(scroller.options, config) + } + + return scroller +} + + + /************************************************ jQuery extensions **/ jQuery.fn.reverseChildren = function(){