Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
触摸滚动Jquery插件-如何为多个实例使用不同的选项初始化?_Jquery_Plugins_Scroll_Options_Instances - Fatal编程技术网

触摸滚动Jquery插件-如何为多个实例使用不同的选项初始化?

触摸滚动Jquery插件-如何为多个实例使用不同的选项初始化?,jquery,plugins,scroll,options,instances,Jquery,Plugins,Scroll,Options,Instances,如图所示-: 当前,其中一个中设置的选项将覆盖另一个。这是我针对多个实例修改的代码 (function($) { // Define default scroll settings var defaults = { y: 0, x: 0, scrollHeight: 0, scrollWidth: 0, vScroll: true, hScroll: false, elastic:

如图所示-:


当前,其中一个中设置的选项将覆盖另一个。

这是我针对多个实例修改的代码

(function($) {

// Define default scroll settings
var defaults = {
        y: 0,
        x: 0,
        scrollHeight: 0,
        scrollWidth: 0,
        vScroll: true,
        hScroll: false,
        elastic: !navigator.userAgent.match(/android/i),
        momentum: true,
        elasticDamp: 0.6,
        elasticTime: 50,
        reboundTime: 400,
        momentumDamp: 0.9,
        momentumTime: 300,
        iPadMomentumDamp: 0.95,
        iPadMomentumTime: 1200,
        touchTags: ['select', 'input', 'textarea']
};

// Define methods
var methods = {

    init: function(options) {
        return this.each(function() {

            var self = this;
            self.scrollOptions = {};
            $.extend(self.scrollOptions, defaults);
            $.extend(self.scrollOptions, options);

            // Prevent double-init, just update instead
            if (!!this._init) {
                return this.update();
            }
            this._init = true;

            // Define element variables
            var $this = $(this),
                scrollY = -self.scrollOptions.y,
                scrollX = -self.scrollOptions.x,
                touchY = 0,
                touchX = 0,
                movedY = 0,
                movedX = 0,
                pollY = 0,
                pollX = 0,
                height = 0,
                width = 0,
                maxHeight = 0,
                maxWidth = 0,
                scrollHeight = 0,
                scrollWidth = 0,
                scrolling = false,
                bouncing = false,
                moved = false,
                timeoutID,
                isiPad = !!navigator.platform.match(/ipad/i),
                hasMatrix = 'WebKitCSSMatrix' in window,
                has3d = hasMatrix && 'm11' in new WebKitCSSMatrix();

            // Keep bottom of scroll area at the bottom on resize
            var update = this.update = function() {

                if (self.scrollOptions.hScroll) {
                    self.scrollOptions.vScroll = false;
                    // width setup
                    width = $this.parent().width();
                    scrollWidth = $this.width();
                    maxWidth = width - scrollWidth;
                }

                if (self.scrollOptions.vScroll) {
                    // height setup
                    height = $this.parent().height();
                    scrollHeight = $this.height();
                    maxHeight = height - scrollHeight;
                }

                clearTimeout(timeoutID);
                clampScroll(false);
            };

            // Set up initial variables
            update();

            // Set up transform CSS
            $this.css({'-webkit-transition-property': '-webkit-transform',
                '-webkit-transition-timing-function': 'cubic-bezier(0,0,0.2,1)',
                '-webkit-transition-duration': '0',
                '-webkit-transform': cssTranslate(scrollX, scrollY)});

            // Listen for screen size change event
            window.addEventListener('onorientationchange' in window ? 'orientationchange' : 'resize', update, false);

            // Listen for touch events
            $this.bind('touchstart.touchScroll', touchStart);
            $this.bind('touchmove.touchScroll', touchMove);
            $this.bind('touchend.touchScroll touchcancel.touchScroll', touchEnd);
            $this.bind('webkitTransitionEnd.touchScroll', transitionEnd);

            // Set the position of the scroll area using transform CSS
            var setPosition = this.setPosition = function(x, y) {
                scrollX = x;
                scrollY = y;
                $this.css('-webkit-transform', cssTranslate(scrollX, scrollY));
            };

            // Transform using a 3D translate if available
            function cssTranslate(x, y) {
                return 'translate' + (has3d ? '3d(' : '(') + x + 'px,' + y + 'px' + (has3d ? ',0)' : ')');
            }

            // Set CSS transition time
            function setTransitionTime(time) {
                time = time || '0';
                $this.css('-webkit-transition-duration', time + 'ms');
            }

            // Get the actual pixel position made by transform CSS
            function getPosition() {
                if (hasMatrix) {
                    var transform = window.getComputedStyle($this[0]).webkitTransform;
                    if (!!transform && transform !== 'none') {
                        var matrix = new WebKitCSSMatrix(transform);
                        return { x: matrix.e, y: matrix.f };
                    }
                }
                return { x: scrollX, y: scrollY };
            }

            // Expose getPosition API
            this.getPosition = function() {
                return getPosition();
            };

            // Bounce back to the bounds after momentum scrolling
            function reboundScroll() {
                if (scrollX > 0 && scrollY > 0) {
                    scrollTo(0, 0, self.scrollOptions.reboundTime);
                } else if (scrollX > 0) {
                    scrollTo(0, scrollY, self.scrollOptions.reboundTime);
                } else if (scrollY > 0) {
                    scrollTo(scrollX, 0, self.scrollOptions.reboundTime);
                } else if (scrollX < maxWidth && scrollY < maxHeight) {
                    scrollTo(maxWidth, maxHeight, self.scrollOptions.reboundTime);
                } else if (scrollX < maxWidth) {
                    scrollTo(maxWidth, scrollY, self.scrollOptions.reboundTime);
                } else if (scrollY < maxHeight) {
                    scrollTo(scrollX, maxHeight, self.scrollOptions.reboundTime);
                }
            }

            // Stop everything once the CSS transition in complete
            function transitionEnd() {
                if (bouncing) {
                    bouncing = false;
                    reboundScroll();
                }

                clearTimeout(timeoutID);
            }

            // Limit the scrolling to within the bounds
            function clampScroll(poll) {
                if (!hasMatrix || bouncing) {
                    return;
                }

                var oldX = pollX;
                pollX = getPosition().x;

                var oldY = pollY;
                pollY = getPosition().y;

                if (pollX > 0 || pollY > 0) {
                    if (self.scrollOptions.elastic) {
                        // Slow down outside top bound
                        bouncing = true;
                        scrollX = (pollX > 0) ? 0 : pollX ;
                        scrollY = (pollY > 0) ? 0 : pollY ; 
                        momentumScroll(pollX - oldX, pollY - oldY, self.scrollOptions.elasticDamp, 1, width, height, self.scrollOptions.elasticTime);
                    } else {
                        // Stop outside top bound
                        var x = (pollX > 0) ? 0 : pollX ;
                        var y = (pollY > 0) ? 0 : pollY ; 
                        setTransitionTime(0);
                        setPosition(x, y);
                    }
                } else if (pollX < maxWidth || pollY < maxHeight) {
                    if (self.scrollOptions.elastic) {
                        // Slow down outside bottom bound
                        bouncing = true;
                        scrollX = (pollX > maxHeight) ? maxHeight : pollX ;
                        scrollY = (pollY > maxHeight) ? maxHeight : pollY ; 
                        momentumScroll(pollX - oldX, pollY - oldY, self.scrollOptions.elasticDamp, 1, width, height, self.scrollOptions.elasticTime);
                    } else {
                        // Stop outside bottom bound
                        var x = (pollX > maxWidth) ? maxWidth : pollX ;
                        var y = (pollY > maxHeight) ? maxHeight : pollY ; 
                        setTransitionTime(0);
                        setPosition(x, y);
                    }
                } else if (poll) {
                    // Poll the computed position to check if element is out of bounds
                    timeoutID = setTimeout(clampScroll, 20, true);
                }
            }

            // Animate to a position using CSS
            function scrollTo(destX, destY, time) {
                if (destX === scrollX && destY === scrollY) {
                    return;
                }

                moved = true;
                setTransitionTime(time);
                setPosition(destX, destY);
            }

            // Perform a momentum-based scroll using CSS
            function momentumScroll(dxin, dyin, k, minDist, maxDistX, maxDistY, t) {
                var adx = Math.abs(dxin),
                    ady = Math.abs(dyin),
                    dx = 0,
                    dy = 0;

                // Calculate the total distance
                while (adx > 0.1) {
                    adx *= k;
                    dx += adx;
                }
                while (ady > 0.1) {
                    ady *= k;
                    dy += ady;
                }

                // Limit to within min and max distances
                if (dx > maxDistX) {
                    dx = maxDistX;
                }
                if (dy > maxDistY) {
                    dy = maxDistY;
                }
                if (dx > minDist) {
                    if (dxin < 0) {
                        dx = -dx;
                    }

                    dx += scrollX;

                    // If outside the bounds, don't go too far
                    if (width > 0) {
                        if (dx > width * 2) {
                            dx = width * 2;
                        } else if (dx < maxWidth - width * 2) {
                            dx = maxWidth - width * 2;
                        }
                    }
                }
                if (dy > minDist) {
                    if (dyin < 0) {
                        dy = -dy;
                    }

                    dy += scrollY;

                    // If outside the bounds, don't go too far
                    if (height > 0) {
                        if (dy > height * 2) {
                            dy = height * 2;
                        } else if (dy < maxHeight - height * 2) {
                            dy = maxHeight - height * 2;
                        }
                    }
                }
                if (Math.abs(dx) > minDist || Math.abs(dy) > minDist) {
                    // Perform scroll
                    scrollTo(Math.round(dx), Math.round(dy), t);
                }
                clampScroll(true);
            }

            // Get the touch points from this event
            function getTouches(e) {
                if (e.originalEvent) {
                    if (e.originalEvent.touches && e.originalEvent.touches.length) {
                        return e.originalEvent.touches;
                    } else if (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length) {
                        return e.originalEvent.changedTouches;
                    }
                }
                return e.touches;
            }

            // Dispatches a fake mouse event from a touch event
            function dispatchMouseEvent(name, touch, target) {
                var e = document.createEvent('MouseEvent');
                e.initMouseEvent(name, true, true, touch.view, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
                target.dispatchEvent(e);
            }

            // Find the root node of this target
            function getRootNode(target) {
                while (target.nodeType !== 1) {
                    target = target.parentNode;
                }
                return target;
            }

            // Perform a touch start event
            function touchStart(e) {
                // Allow certain HTML tags to receive touch events
                if ($.inArray(e.target.tagName.toLowerCase(), self.scrollOptions.touchTags) !== -1) {
                    return;
                }

                // Stop the default touches
                e.preventDefault();
                e.stopPropagation();

                var touch = getTouches(e)[0];

                // Dispatch a fake mouse down event     
                dispatchMouseEvent('mousedown', touch, getRootNode(touch.target));

                scrolling = true;
                moved = false;
                movedX = 0;
                movedY = 0;

                clearTimeout(timeoutID);
                setTransitionTime(0);

                // Check scroll position
                if (self.scrollOptions.momentum) {
                    var x = getPosition().x;
                    var y = getPosition().y;
                    if (x !== scrollX || y !== scrollY) {
                        setPosition(x, y);
                        moved = true;
                    }
                }

                touchX = touch.pageX - scrollX;
                touchY = touch.pageY - scrollY;
            }

            // Perform a touch move event
            function touchMove(e) {
                if (!scrolling) {
                    return;
                }

                var dx = getTouches(e)[0].pageX - touchX;
                var dy = getTouches(e)[0].pageY - touchY;

                // Elastic-drag or stop when moving outside of boundaries
                if (dx > 0) {
                    if (self.scrollOptions.elastic) {
                        dx /= 2;
                    } else {
                        dx = 0;
                    }
                } else if (dx < maxWidth) {
                    if (self.scrollOptions.elastic) {
                        dx = (dx + maxWidth) / 2;
                    } else {
                        dx = maxWidth;
                    }
                }
                if (dy > 0) {
                    if (self.scrollOptions.elastic) {
                        dy /= 2;
                    } else {
                        dy = 0;
                    }
                } else if (dy < maxHeight) {
                    if (self.scrollOptions.elastic) {
                        dy = (dy + maxHeight) / 2;
                    } else {
                        dy = maxHeight;
                    }
                }

                if (self.scrollOptions.hScroll) {
                    movedX = dx - scrollX;
                } else {
                  dx = 0;
                }
                if (self.scrollOptions.vScroll) {
                    movedY = dy - scrollY;
                } else {
                  dy = 0;
                }

                moved = true;
                setPosition(dx, dy);
            }

            // Perform a touch end event
            function touchEnd(e) {
                if (!scrolling) {
                    return;
                }

                scrolling = false;

                if (moved) {
                    // Ease back to within boundaries
                    if ((scrollX > 0 || scrollX < maxWidth) || (scrollY > 0 || scrollY < maxHeight)) {
                        reboundScroll();
                    } else if (self.scrollOptions.momentum) {
                        // Free scroll with momentum
                        momentumScroll(movedX, movedY, isiPad ? self.scrollOptions.iPadMomentumDamp : self.scrollOptions.momentumDamp, 40, 2000, 2000, isiPad ? self.scrollOptions.iPadMomentumTime : self.scrollOptions.momentumTime);
                    }           
                } else {
                    var touch = getTouches(e)[0],
                        target = getRootNode(touch.target);

                    // Dispatch fake mouse up and click events if this touch event did not move
                    dispatchMouseEvent('mouseup', touch, target);
                    dispatchMouseEvent('click', touch, target);
                }
            }

        });
    },

    update: function() {
        return this.each(function() {
            this.update();
        });
    },

    getPosition: function() {
        var a = [];
        this.each(function() {
            a.push(-this.getPosition());
        });
        return a;
    },

    setPosition: function(x, y) {
        return this.each(function() {
            this.setPosition(-x, -y);
        });
    }

};

// Public method for touchScroll
$.fn.touchScroll = function(method) {
    if (methods[method]) {
        return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
        return methods.init.apply(this, arguments);
    } else {
        $.error('Method ' +  method + ' does not exist on jQuery.touchScroll');
    }
};

})(jQuery);
(函数($){
//定义默认滚动设置
var默认值={
y:0,
x:0,,
滚动高度:0,
滚动宽度:0,
维斯克罗尔:是的,
克罗尔:错,
弹性:!navigator.userAgent.match(/android/i),
动量:是的,
弹性阻尼:0.6,
弹性时间:50,
时间:400,,
动量阻尼:0.9,
时间:300,,
iPadMomentumDamp:0.95,
iPadMomentumTime:1200,
触摸标签:[“选择”、“输入”、“文本区域”]
};
//定义方法
var方法={
初始化:函数(选项){
返回此值。每个(函数(){
var self=这个;
self.scrollOptions={};
$.extend(self.scroll选项,默认值);
$.extend(self.scrollOptions,options);
//防止双重初始化,只需更新即可
如果(!!这个。_init){
返回此.update();
}
这是._init=true;
//定义元素变量
变量$this=$(this),
scrollY=-self.scrollOptions.y,
scrollX=-self.scrollOptions.x,
touchY=0,
touchX=0,
movedY=0,
movedX=0,
波利=0,
pollX=0,
高度=0,
宽度=0,
最大高度=0,
maxWidth=0,
滚动高度=0,
滚动宽度=0,
滚动=错误,
反弹=错误,
moved=false,
timeoutID,
isiPad=!!navigator.platform.match(/ipad/i),
hasMatrix='WebKitCSSMatrix'在窗口中,
has3d=hasMatrix&“m11”在新的WebKitCSSMatrix()中;
//调整大小时,将滚动区域的底部保持在底部
var update=this.update=function(){
if(self.scrollOptions.hScroll){
self.scrollOptions.vScroll=false;
//宽度设置
宽度=$this.parent().width();
scrollWidth=$this.width();
maxWidth=宽度-滚动宽度;
}
if(self.scrollOptions.vScroll){
//高度设置
高度=$this.parent().height();
scrollHeight=$this.height();
maxHeight=高度-滚动高度;
}
clearTimeout(timeoutID);
clampScroll(假);
};
//设置初始变量
更新();
//设置转换CSS
$this.css({'-webkit转换属性':'-webkit转换',
“-webkit转换计时函数”:“立方贝塞尔(0,0,0.2,1)”,
“-webkit转换持续时间”:“0”,
“-webkit转换”:cstranslate(scrollX,scrollY)};
//侦听屏幕大小更改事件
window.addEventListener('onorientationchange'在窗口中?'orientationchange':'resize',update,false);
//倾听触摸事件
$this.bind('touchstart.touchScroll',touchstart);
$this.bind('touchmove.touchcroll',touchmove);
$this.bind('touchend.TouchCroll touchcancel.TouchCroll',touchend);
$this.bind('webkittransionend.touchcroll',transitionnd);
//使用transform CSS设置滚动区域的位置
var setPosition=this.setPosition=function(x,y){
x=x;
卷轴=y;
$this.css('-webkit transform',cstranslate(scrollX,scrollY));
};
//使用三维平移进行变换(如果可用)
函数CST(x,y){
返回'translate'+(has3d?'3d(':'(')+x+'px',+y+'px'+(has3d?',0):');
}
//设置CSS转换时间
函数setTransitionTime(时间){
时间=时间| |“0”;
$this.css('-webkit transition duration',time+'ms');
}
//获取变换CSS生成的实际像素位置
函数getPosition(){
if(hasMatrix){
var transform=window.getComputedStyle($this[0]).WebKittTransform;
如果(!!转换和转换!=='none'){
var矩阵=新的WebKitCSSMatrix(转换);
返回{x:matrix.e,y:matrix.f};
}
}
返回{x:scrollX,y:scrollY};
}
//公开getPosition API
this.getPosition=函数(){
返回getPosition();
};
//在动量滚动后反弹到边界
函数(){
如果(scrollX>0&&scrollY>0){
scrollTo(0,0,self.scrollOptions.time);
}否则如果(scrollX>0){
scrollTo(0,scrollY,self.scrollOptions.Time);
}否则如果(滚动>0){
scrollTo(scrollX,0,self.scrollOptions.Time);
}else if(scrollX$('#selector1').touchScroll({elastic: false});
$('#selector2').touchScroll({elastic: true});
(function($) {

// Define default scroll settings
var defaults = {
        y: 0,
        x: 0,
        scrollHeight: 0,
        scrollWidth: 0,
        vScroll: true,
        hScroll: false,
        elastic: !navigator.userAgent.match(/android/i),
        momentum: true,
        elasticDamp: 0.6,
        elasticTime: 50,
        reboundTime: 400,
        momentumDamp: 0.9,
        momentumTime: 300,
        iPadMomentumDamp: 0.95,
        iPadMomentumTime: 1200,
        touchTags: ['select', 'input', 'textarea']
};

// Define methods
var methods = {

    init: function(options) {
        return this.each(function() {

            var self = this;
            self.scrollOptions = {};
            $.extend(self.scrollOptions, defaults);
            $.extend(self.scrollOptions, options);

            // Prevent double-init, just update instead
            if (!!this._init) {
                return this.update();
            }
            this._init = true;

            // Define element variables
            var $this = $(this),
                scrollY = -self.scrollOptions.y,
                scrollX = -self.scrollOptions.x,
                touchY = 0,
                touchX = 0,
                movedY = 0,
                movedX = 0,
                pollY = 0,
                pollX = 0,
                height = 0,
                width = 0,
                maxHeight = 0,
                maxWidth = 0,
                scrollHeight = 0,
                scrollWidth = 0,
                scrolling = false,
                bouncing = false,
                moved = false,
                timeoutID,
                isiPad = !!navigator.platform.match(/ipad/i),
                hasMatrix = 'WebKitCSSMatrix' in window,
                has3d = hasMatrix && 'm11' in new WebKitCSSMatrix();

            // Keep bottom of scroll area at the bottom on resize
            var update = this.update = function() {

                if (self.scrollOptions.hScroll) {
                    self.scrollOptions.vScroll = false;
                    // width setup
                    width = $this.parent().width();
                    scrollWidth = $this.width();
                    maxWidth = width - scrollWidth;
                }

                if (self.scrollOptions.vScroll) {
                    // height setup
                    height = $this.parent().height();
                    scrollHeight = $this.height();
                    maxHeight = height - scrollHeight;
                }

                clearTimeout(timeoutID);
                clampScroll(false);
            };

            // Set up initial variables
            update();

            // Set up transform CSS
            $this.css({'-webkit-transition-property': '-webkit-transform',
                '-webkit-transition-timing-function': 'cubic-bezier(0,0,0.2,1)',
                '-webkit-transition-duration': '0',
                '-webkit-transform': cssTranslate(scrollX, scrollY)});

            // Listen for screen size change event
            window.addEventListener('onorientationchange' in window ? 'orientationchange' : 'resize', update, false);

            // Listen for touch events
            $this.bind('touchstart.touchScroll', touchStart);
            $this.bind('touchmove.touchScroll', touchMove);
            $this.bind('touchend.touchScroll touchcancel.touchScroll', touchEnd);
            $this.bind('webkitTransitionEnd.touchScroll', transitionEnd);

            // Set the position of the scroll area using transform CSS
            var setPosition = this.setPosition = function(x, y) {
                scrollX = x;
                scrollY = y;
                $this.css('-webkit-transform', cssTranslate(scrollX, scrollY));
            };

            // Transform using a 3D translate if available
            function cssTranslate(x, y) {
                return 'translate' + (has3d ? '3d(' : '(') + x + 'px,' + y + 'px' + (has3d ? ',0)' : ')');
            }

            // Set CSS transition time
            function setTransitionTime(time) {
                time = time || '0';
                $this.css('-webkit-transition-duration', time + 'ms');
            }

            // Get the actual pixel position made by transform CSS
            function getPosition() {
                if (hasMatrix) {
                    var transform = window.getComputedStyle($this[0]).webkitTransform;
                    if (!!transform && transform !== 'none') {
                        var matrix = new WebKitCSSMatrix(transform);
                        return { x: matrix.e, y: matrix.f };
                    }
                }
                return { x: scrollX, y: scrollY };
            }

            // Expose getPosition API
            this.getPosition = function() {
                return getPosition();
            };

            // Bounce back to the bounds after momentum scrolling
            function reboundScroll() {
                if (scrollX > 0 && scrollY > 0) {
                    scrollTo(0, 0, self.scrollOptions.reboundTime);
                } else if (scrollX > 0) {
                    scrollTo(0, scrollY, self.scrollOptions.reboundTime);
                } else if (scrollY > 0) {
                    scrollTo(scrollX, 0, self.scrollOptions.reboundTime);
                } else if (scrollX < maxWidth && scrollY < maxHeight) {
                    scrollTo(maxWidth, maxHeight, self.scrollOptions.reboundTime);
                } else if (scrollX < maxWidth) {
                    scrollTo(maxWidth, scrollY, self.scrollOptions.reboundTime);
                } else if (scrollY < maxHeight) {
                    scrollTo(scrollX, maxHeight, self.scrollOptions.reboundTime);
                }
            }

            // Stop everything once the CSS transition in complete
            function transitionEnd() {
                if (bouncing) {
                    bouncing = false;
                    reboundScroll();
                }

                clearTimeout(timeoutID);
            }

            // Limit the scrolling to within the bounds
            function clampScroll(poll) {
                if (!hasMatrix || bouncing) {
                    return;
                }

                var oldX = pollX;
                pollX = getPosition().x;

                var oldY = pollY;
                pollY = getPosition().y;

                if (pollX > 0 || pollY > 0) {
                    if (self.scrollOptions.elastic) {
                        // Slow down outside top bound
                        bouncing = true;
                        scrollX = (pollX > 0) ? 0 : pollX ;
                        scrollY = (pollY > 0) ? 0 : pollY ; 
                        momentumScroll(pollX - oldX, pollY - oldY, self.scrollOptions.elasticDamp, 1, width, height, self.scrollOptions.elasticTime);
                    } else {
                        // Stop outside top bound
                        var x = (pollX > 0) ? 0 : pollX ;
                        var y = (pollY > 0) ? 0 : pollY ; 
                        setTransitionTime(0);
                        setPosition(x, y);
                    }
                } else if (pollX < maxWidth || pollY < maxHeight) {
                    if (self.scrollOptions.elastic) {
                        // Slow down outside bottom bound
                        bouncing = true;
                        scrollX = (pollX > maxHeight) ? maxHeight : pollX ;
                        scrollY = (pollY > maxHeight) ? maxHeight : pollY ; 
                        momentumScroll(pollX - oldX, pollY - oldY, self.scrollOptions.elasticDamp, 1, width, height, self.scrollOptions.elasticTime);
                    } else {
                        // Stop outside bottom bound
                        var x = (pollX > maxWidth) ? maxWidth : pollX ;
                        var y = (pollY > maxHeight) ? maxHeight : pollY ; 
                        setTransitionTime(0);
                        setPosition(x, y);
                    }
                } else if (poll) {
                    // Poll the computed position to check if element is out of bounds
                    timeoutID = setTimeout(clampScroll, 20, true);
                }
            }

            // Animate to a position using CSS
            function scrollTo(destX, destY, time) {
                if (destX === scrollX && destY === scrollY) {
                    return;
                }

                moved = true;
                setTransitionTime(time);
                setPosition(destX, destY);
            }

            // Perform a momentum-based scroll using CSS
            function momentumScroll(dxin, dyin, k, minDist, maxDistX, maxDistY, t) {
                var adx = Math.abs(dxin),
                    ady = Math.abs(dyin),
                    dx = 0,
                    dy = 0;

                // Calculate the total distance
                while (adx > 0.1) {
                    adx *= k;
                    dx += adx;
                }
                while (ady > 0.1) {
                    ady *= k;
                    dy += ady;
                }

                // Limit to within min and max distances
                if (dx > maxDistX) {
                    dx = maxDistX;
                }
                if (dy > maxDistY) {
                    dy = maxDistY;
                }
                if (dx > minDist) {
                    if (dxin < 0) {
                        dx = -dx;
                    }

                    dx += scrollX;

                    // If outside the bounds, don't go too far
                    if (width > 0) {
                        if (dx > width * 2) {
                            dx = width * 2;
                        } else if (dx < maxWidth - width * 2) {
                            dx = maxWidth - width * 2;
                        }
                    }
                }
                if (dy > minDist) {
                    if (dyin < 0) {
                        dy = -dy;
                    }

                    dy += scrollY;

                    // If outside the bounds, don't go too far
                    if (height > 0) {
                        if (dy > height * 2) {
                            dy = height * 2;
                        } else if (dy < maxHeight - height * 2) {
                            dy = maxHeight - height * 2;
                        }
                    }
                }
                if (Math.abs(dx) > minDist || Math.abs(dy) > minDist) {
                    // Perform scroll
                    scrollTo(Math.round(dx), Math.round(dy), t);
                }
                clampScroll(true);
            }

            // Get the touch points from this event
            function getTouches(e) {
                if (e.originalEvent) {
                    if (e.originalEvent.touches && e.originalEvent.touches.length) {
                        return e.originalEvent.touches;
                    } else if (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length) {
                        return e.originalEvent.changedTouches;
                    }
                }
                return e.touches;
            }

            // Dispatches a fake mouse event from a touch event
            function dispatchMouseEvent(name, touch, target) {
                var e = document.createEvent('MouseEvent');
                e.initMouseEvent(name, true, true, touch.view, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
                target.dispatchEvent(e);
            }

            // Find the root node of this target
            function getRootNode(target) {
                while (target.nodeType !== 1) {
                    target = target.parentNode;
                }
                return target;
            }

            // Perform a touch start event
            function touchStart(e) {
                // Allow certain HTML tags to receive touch events
                if ($.inArray(e.target.tagName.toLowerCase(), self.scrollOptions.touchTags) !== -1) {
                    return;
                }

                // Stop the default touches
                e.preventDefault();
                e.stopPropagation();

                var touch = getTouches(e)[0];

                // Dispatch a fake mouse down event     
                dispatchMouseEvent('mousedown', touch, getRootNode(touch.target));

                scrolling = true;
                moved = false;
                movedX = 0;
                movedY = 0;

                clearTimeout(timeoutID);
                setTransitionTime(0);

                // Check scroll position
                if (self.scrollOptions.momentum) {
                    var x = getPosition().x;
                    var y = getPosition().y;
                    if (x !== scrollX || y !== scrollY) {
                        setPosition(x, y);
                        moved = true;
                    }
                }

                touchX = touch.pageX - scrollX;
                touchY = touch.pageY - scrollY;
            }

            // Perform a touch move event
            function touchMove(e) {
                if (!scrolling) {
                    return;
                }

                var dx = getTouches(e)[0].pageX - touchX;
                var dy = getTouches(e)[0].pageY - touchY;

                // Elastic-drag or stop when moving outside of boundaries
                if (dx > 0) {
                    if (self.scrollOptions.elastic) {
                        dx /= 2;
                    } else {
                        dx = 0;
                    }
                } else if (dx < maxWidth) {
                    if (self.scrollOptions.elastic) {
                        dx = (dx + maxWidth) / 2;
                    } else {
                        dx = maxWidth;
                    }
                }
                if (dy > 0) {
                    if (self.scrollOptions.elastic) {
                        dy /= 2;
                    } else {
                        dy = 0;
                    }
                } else if (dy < maxHeight) {
                    if (self.scrollOptions.elastic) {
                        dy = (dy + maxHeight) / 2;
                    } else {
                        dy = maxHeight;
                    }
                }

                if (self.scrollOptions.hScroll) {
                    movedX = dx - scrollX;
                } else {
                  dx = 0;
                }
                if (self.scrollOptions.vScroll) {
                    movedY = dy - scrollY;
                } else {
                  dy = 0;
                }

                moved = true;
                setPosition(dx, dy);
            }

            // Perform a touch end event
            function touchEnd(e) {
                if (!scrolling) {
                    return;
                }

                scrolling = false;

                if (moved) {
                    // Ease back to within boundaries
                    if ((scrollX > 0 || scrollX < maxWidth) || (scrollY > 0 || scrollY < maxHeight)) {
                        reboundScroll();
                    } else if (self.scrollOptions.momentum) {
                        // Free scroll with momentum
                        momentumScroll(movedX, movedY, isiPad ? self.scrollOptions.iPadMomentumDamp : self.scrollOptions.momentumDamp, 40, 2000, 2000, isiPad ? self.scrollOptions.iPadMomentumTime : self.scrollOptions.momentumTime);
                    }           
                } else {
                    var touch = getTouches(e)[0],
                        target = getRootNode(touch.target);

                    // Dispatch fake mouse up and click events if this touch event did not move
                    dispatchMouseEvent('mouseup', touch, target);
                    dispatchMouseEvent('click', touch, target);
                }
            }

        });
    },

    update: function() {
        return this.each(function() {
            this.update();
        });
    },

    getPosition: function() {
        var a = [];
        this.each(function() {
            a.push(-this.getPosition());
        });
        return a;
    },

    setPosition: function(x, y) {
        return this.each(function() {
            this.setPosition(-x, -y);
        });
    }

};

// Public method for touchScroll
$.fn.touchScroll = function(method) {
    if (methods[method]) {
        return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
        return methods.init.apply(this, arguments);
    } else {
        $.error('Method ' +  method + ' does not exist on jQuery.touchScroll');
    }
};

})(jQuery);