From: ISHIKAWA Mutsumi Date: Thu, 3 Jun 2010 16:55:56 +0000 (+0900) Subject: update iscroll.js to 3.2.1 X-Git-Url: http://git.osdn.net/view?p=keitairc%2Fkeitairc.git;a=commitdiff_plain;h=5c938107b8cee08017e7c559497ace446cfd3c3c update iscroll.js to 3.2.1 --- diff --git a/data/public/iscroll/iscroll.js b/data/public/iscroll/iscroll.js index 5cb2e99..14c97ee 100644 --- a/data/public/iscroll/iscroll.js +++ b/data/public/iscroll/iscroll.js @@ -7,16 +7,16 @@ * Released under MIT license * http://cubiq.org/dropbox/mit-license.txt * - * Version 3.1beta1 - Last updated: 2010.05.06 + * Version 3.2.1 - Last updated: 2010.06.03 * */ +(function(){ + function iScroll (el, options) { this.element = typeof el == 'object' ? el : document.getElementById(el); this.wrapper = this.element.parentNode; - this.wrapper.style.overflow = 'hidden'; - this.wrapper.style.position = 'relative'; this.element.style.webkitTransitionProperty = '-webkit-transform'; this.element.style.webkitTransitionTimingFunction = 'cubic-bezier(0,0,0.25,1)'; this.element.style.webkitTransitionDuration = '0'; @@ -25,6 +25,8 @@ function iScroll (el, options) { // Get options this.options = { bounce: true, + checkDOMChanges: true, + topOnDOMChanges: false, hScrollBar: true, vScrollBar: true }; @@ -40,13 +42,16 @@ function iScroll (el, options) { this.element.addEventListener('touchstart', this); this.element.addEventListener('touchmove', this); this.element.addEventListener('touchend', this); - this.element.addEventListener('DOMSubtreeModified', this); window.addEventListener('orientationchange', this); + + if (this.options.checkDOMChanges) { + this.element.addEventListener('DOMSubtreeModified', this); + } } iScroll.prototype = { - _x: 0, - _y: 0, + x: 0, + y: 0, handleEvent: function (e) { switch (e.type) { @@ -54,34 +59,50 @@ iScroll.prototype = { case 'touchmove': this.onTouchMove(e); break; case 'touchend': this.onTouchEnd(e); break; case 'webkitTransitionEnd': this.onTransitionEnd(e); break; - case 'orientationchange': this.refresh(); /*this.scrollTo(0,0,'0');*/ break; - case 'DOMSubtreeModified': this.refresh(); break; + case 'orientationchange': this.refresh(); break; + case 'DOMSubtreeModified': this.onDOMModified(e); break; + } + }, + + onDOMModified: function (e) { + this.refresh(); + + if (this.options.topOnDOMChanges && (this.x!=0 || this.y!=0)) { + this.scrollTo(0,0,'0'); } }, refresh: function () { - this.element.style.webkitTransitionDuration = '0'; this.scrollWidth = this.wrapper.clientWidth; this.scrollHeight = this.wrapper.clientHeight; this.maxScrollX = this.scrollWidth - this.element.offsetWidth; this.maxScrollY = this.scrollHeight - this.element.offsetHeight; - + var resetX = this.x, resetY = this.y; - if (this.scrollX && this.x < this.maxScrollX) { - resetX = this.maxScrollX; + if (this.scrollX) { + if (this.maxScrollX >= 0) { + resetX = 0; + } else if (this.x < this.maxScrollX) { + resetX = this.maxScrollX; + } } - if (this.scrollY && this.y < this.maxScrollY) { - resetY = this.maxScrollY; + if (this.scrollY) { + if (this.maxScrollY >= 0) { + resetY = 0; + } else if (this.y < this.maxScrollY) { + resetY = this.maxScrollY; + } + } + if (resetX!=this.x || resetY!=this.y) { + this.scrollTo(resetX,resetY,'0'); } - // If content width/lenght has been modified, reset scroller position - this.scrollTo(resetX,resetY,'0'); this.scrollX = this.element.offsetWidth > this.scrollWidth ? true : false; this.scrollY = this.element.offsetHeight > this.scrollHeight ? true : false; // Update horizontal scrollbar if (this.options.hScrollBar && this.scrollX) { - this.scrollBarX = new scrollbar('horizontal', this.wrapper); + this.scrollBarX = (this.scrollBarX instanceof scrollbar) ? this.scrollBarX : new scrollbar('horizontal', this.wrapper); this.scrollBarX.init(this.scrollWidth, this.element.offsetWidth); } else if (this.scrollBarX) { this.scrollBarX = this.scrollBarX.remove(); @@ -89,33 +110,25 @@ iScroll.prototype = { // Update vertical scrollbar if (this.options.vScrollBar && this.scrollY) { - this.scrollBarY = new scrollbar('vertical', this.wrapper); + this.scrollBarY = (this.scrollBarY instanceof scrollbar) ? this.scrollBarY : new scrollbar('vertical', this.wrapper); this.scrollBarY.init(this.scrollHeight, this.element.offsetHeight); } else if (this.scrollBarY) { this.scrollBarY = this.scrollBarY.remove(); } }, - get x() { - return this._x; - }, - - get y() { - return this._y; - }, - setPosition: function (x, y) { - this._x = x !== null ? x : this._x; - this._y = y !== null ? y : this._y; + this.x = x !== null ? x : this.x; + this.y = y !== null ? y : this.y; - this.element.style.webkitTransform = 'translate3d(' + this._x + 'px,' + this._y + 'px,0)'; + this.element.style.webkitTransform = 'translate3d(' + this.x + 'px,' + this.y + 'px,0)'; // Move the scrollbars if (this.scrollBarX) { - this.scrollBarX.setPosition(this.scrollBarX.maxScroll / this.maxScrollX * this._x); + this.scrollBarX.setPosition(this.scrollBarX.maxScroll / this.maxScrollX * this.x); } if (this.scrollBarY) { - this.scrollBarY.setPosition(this.scrollBarY.maxScroll / this.maxScrollY * this._y); + this.scrollBarY.setPosition(this.scrollBarY.maxScroll / this.maxScrollY * this.y); } }, @@ -145,7 +158,7 @@ iScroll.prototype = { this.scrollStartX = this.x; this.touchStartY = e.touches[0].pageY; - this.scrollStartY = this.y; + this.scrollStartY = this.y; this.scrollStartTime = e.timeStamp; this.moved = false; @@ -155,16 +168,20 @@ iScroll.prototype = { if (e.targetTouches.length != 1) { return false; } + e.preventDefault(); - var leftDelta = this.scrollX === true ? e.touches[0].pageX - this.touchStartX : 0; - var topDelta = this.scrollY === true ? e.touches[0].pageY - this.touchStartY : 0; - if (this.x > 0 || this.x < this.maxScrollX) { - leftDelta = Math.round(leftDelta / 4); // Slow down if outside of the boundaries - } + var leftDelta = this.scrollX === true ? e.touches[0].pageX - this.touchStartX : 0, + topDelta = this.scrollY === true ? e.touches[0].pageY - this.touchStartY : 0, + newX = this.x + leftDelta, + newY = this.y + topDelta; - if (this.y > 0 || this.y < this.maxScrollY) { - topDelta = Math.round(topDelta / 4); // Slow down if outside of the boundaries + // Slow down if outside of the boundaries + if (newX > 0 || newX < this.maxScrollX) { + newX = this.options.bounce ? Math.round(this.x + leftDelta / 4) : this.x; + } + if (newY > 0 || newY < this.maxScrollY) { + newY = this.options.bounce ? Math.round(this.y + topDelta / 4) : this.y; } if (this.scrollBarX && !this.scrollBarX.visible) { @@ -174,7 +191,7 @@ iScroll.prototype = { this.scrollBarY.show(); } - this.setPosition(this.x + leftDelta, this.y + topDelta); + this.setPosition(newX, newY); this.touchStartX = e.touches[0].pageX; this.touchStartY = e.touches[0].pageY; @@ -194,9 +211,18 @@ iScroll.prototype = { } if (!this.moved) { + // Find the last touched element + var theTarget = e.changedTouches[0].target; + if (theTarget.nodeType == 3) { + theTarget = theTarget.parentNode; + } + // Create the fake event var theEvent = document.createEvent('MouseEvents'); - theEvent.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, null); - e.changedTouches[0].target.dispatchEvent(theEvent); + theEvent.initMouseEvent("click", true, true, document.defaultView, + e.detail, e.screenX, e.screenY, e.clientX, e.clientY, + e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, + e.button, e.relatedTarget); + theTarget.dispatchEvent(theEvent); return false; } @@ -205,23 +231,23 @@ iScroll.prototype = { var momentumX = this.scrollX === true ? this.momentum(this.x - this.scrollStartX, time, - -this.x + 50, - this.x + this.element.offsetWidth - this.scrollWidth + 50) + this.options.bounce ? -this.x + this.scrollWidth/4 : -this.x, + this.options.bounce ? this.x + this.element.offsetWidth - this.scrollWidth + this.scrollWidth/4 : this.x + this.element.offsetWidth - this.scrollWidth) : { dist: 0, time: 0 }; var momentumY = this.scrollY === true ? this.momentum(this.y - this.scrollStartY, time, - -this.y + /*this.scrollHeight/3*/ 50, - this.y + this.element.offsetHeight - this.scrollHeight + /*this.scrollHeight/3*/ 50) + this.options.bounce ? -this.y + this.scrollHeight/4 : -this.y, + this.options.bounce ? this.y + this.element.offsetHeight - this.scrollHeight + this.scrollHeight/4 : this.y + this.element.offsetHeight - this.scrollHeight) : { dist: 0, time: 0 }; if (!momentumX.dist && !momentumY.dist) { - this.onTransitionEnd(); // I know, I know... This is lame + this.resetPosition(); return false; } - var newDuration = Math.max(momentumX.time, momentumY.time); + var newDuration = Math.max(Math.max(momentumX.time, momentumY.time), 1); // The minimum animation length must be 1ms var newPositionX = this.x + momentumX.dist; var newPositionY = this.y + momentumY.dist; @@ -241,36 +267,42 @@ iScroll.prototype = { onTransitionEnd: function () { this.element.removeEventListener('webkitTransitionEnd', this); this.resetPosition(); - - // Hide the scrollbars - if (this.scrollBarX) { - this.scrollBarX.hide(); - } - if (this.scrollBarY) { - this.scrollBarY.hide(); - } }, resetPosition: function () { - var resetX = resetY = null; - if (this.x > 0 || this.x < this.maxScrollX) { - resetX = this.x >= 0 ? 0 : this.maxScrollX; + var resetX = this.x, + resetY = this.y; + + if (this.x >= 0) { + resetX = 0; + } else if (this.x < this.maxScrollX) { + resetX = this.maxScrollX; } - if (this.y > 0 || this.y < this.maxScrollY) { - resetY = this.y >= 0 ? 0 : this.maxScrollY; + if (this.y >= 0) { + resetY = 0; + } else if (this.y < this.maxScrollY) { + resetY = this.maxScrollY; } - if (resetX !== null || resetY !== null) { + if (resetX != this.x || resetY != this.y) { this.scrollTo(resetX, resetY, '500ms'); - if (this.scrollBarX) { - this.scrollBarX.scrollTo(this.scrollBarX.maxScroll / this.maxScrollX * (resetX || this.x), '500ms'); + if (this.scrollBarX && resetX != this.x) { + this.scrollBarX.scrollTo(this.scrollBarX.maxScroll / this.maxScrollX * resetX, '500ms'); } - if (this.scrollBarY) { - this.scrollBarY.scrollTo(this.scrollBarY.maxScroll / this.maxScrollY * (resetY || this.y), '500ms'); + if (this.scrollBarY && resetY != this.y) { + this.scrollBarY.scrollTo(this.scrollBarY.maxScroll / this.maxScrollY * resetY, '500ms'); } } + + // Hide the scrollbars + if (this.scrollBarX) { + this.scrollBarX.hide(); + } + if (this.scrollBarY) { + this.scrollBarY.hide(); + } }, scrollTo: function (destX, destY, runtime) { @@ -278,29 +310,25 @@ iScroll.prototype = { this.setPosition(destX, destY); }, - momentum: function (dist, time, maxDist1, maxDist2) { - friction = 0.1; - deceleration = 1.5; - - var speed = Math.abs(dist) / time * 1000; - var newDist = speed * speed / (20 * friction) / 1000; + momentum: function (dist, time, maxDistUpper, maxDistLower) { + var friction = 0.1, + deceleration = 1.5, + speed = Math.abs(dist) / time * 1000, + newDist = speed * speed / (20 * friction) / 1000; // Proportinally reduce speed if we are outside of the boundaries - if (dist > 0 && maxDist1 !== undefined && newDist > maxDist1) { - speed = speed * maxDist1 / newDist; - newDist = maxDist1; + if (dist > 0 && newDist > maxDistUpper) { + speed = speed * maxDistUpper / newDist; + newDist = maxDistUpper; } - if (dist < 0 && maxDist2 !== undefined && newDist > maxDist2) { - speed = speed * maxDist2 / newDist; - newDist = maxDist2; + if (dist < 0 && newDist > maxDistLower) { + speed = speed * maxDistLower / newDist; + newDist = maxDistLower; } newDist = newDist * (dist < 0 ? -1 : 1); - var newTime = -speed / -deceleration; - if (newTime < 1) { // We can't go back in time - newTime = 1; - } + var newTime = speed / deceleration; return { dist: Math.round(newDist), time: Math.round(newTime) }; } @@ -313,7 +341,7 @@ var scrollbar = function (dir, wrapper) { this.bar.style.webkitTransitionTimingFunction = 'cubic-bezier(0,0,0.25,1)'; this.bar.style.webkitTransform = 'translate3d(0,0,0)'; this.bar.style.webkitTransitionProperty = '-webkit-transform,opacity'; - this.bar.style.webkitTransitionDuration = '0,250ms'; + this.bar.style.webkitTransitionDuration = '0,300ms'; this.bar.style.pointerEvents = 'none'; this.bar.style.opacity = '0'; @@ -346,7 +374,7 @@ scrollbar.prototype = { }, scrollTo: function (pos, runtime) { - this.bar.style.webkitTransitionDuration = (runtime || '400ms') + ',250ms'; + this.bar.style.webkitTransitionDuration = (runtime || '400ms') + ',300ms'; this.setPosition(pos); }, @@ -365,3 +393,7 @@ scrollbar.prototype = { return null; } }; + +// Expose iScroll to the world +window.iScroll = iScroll; +})();