TouchController = function(element,parent,options) { var it = this; this.element = element; this.parent = parent; this.children = []; this.hbar = null; this.vbar = null; /* * Constructor parameters: absolute translate3d, forceLayout, debug, useParent */ options = options || {}; options.absolute ? this.element.style.position = 'absolute' : this.element.style.position = 'relative'; this.useParent = options.useParent ? this.observer = parent : this.observer = element; this.translate3d = options.translate3d !== false ? true : false; this.forceLayout = options.forceLayout !== true ? false : true; this.use2Fingers = options.use2Fingers !== true ? false : true; this.fit = options.fit; if(options.debug){ parent.style.border = 'solid 1px #f00'; element.style.border = 'solid 1px #00f'; console.info('Px: ' + parent.clientWidth + ', Ex: ' + element.clientWidth + 'Dx: ' + (parent.clientWidth - element.clientWidth)); console.info('Py: ' + parent.clientHeight + ', Ey: ' + element.clientHeight + 'Dy: ' + (parent.clientHeight - element.clientHeight)); } if(this.translate3d && !options.noInit3d) { var pos = jQuery(element).position(); element.style.webkitTransform = 'translate3d('+pos.left+'px,'+pos.top+'px,0)'; element.style.top = ''; element.style.left = ''; } if(options.scrollbars === true) { var hbar = jQuery('
').appendTo(parent); var vbar = jQuery('
').appendTo(parent); this.hbar = hbar.children().eq(0); this.vbar = vbar.children().eq(0); } this.computeBoundaries(); this.dragging = false; this.drag_sensitivity = 20; this.scale = 1.0; this.element.style.top = 0; this.element.style.left = 0; this.maxX = 0; this.maxY = 0; this.startTouchY = 0; this.startTouchX = 0; this.contentOffsetX = 0; this.contentOffsetY = 0; this.observer.addEventListener('touchstart', this, false); this.observer.addEventListener('touchmove', this, false); this.observer.addEventListener('touchend', this, false); } TouchController.prototype.handleEvent = function(e) { switch (e.type) { case 'touchstart': this.onTouchStart(e); break; case 'touchmove': this.onTouchMove(e); break; case 'touchend': this.onTouchEnd(e); break; } } TouchController.prototype.computeBoundaries = function() { this.maxX = this.parent.clientWidth - this.element.clientWidth; this.maxY = this.parent.clientHeight - this.element.clientHeight; this.maxX = this.maxX < 0 ? this.maxX : 0; this.maxY = this.maxY < 0 ? this.maxY : 0; if(this.hbar && this.maxX !== 0) { this.hratio = this.parent.clientWidth / this.element.clientWidth; this.hbar.width(this.hratio * this.parent.clientWidth); this.hbar.show(); } else { this.hbar && this.hbar.hide(); } if(this.vbar && this.maxY !== 0) { this.vratio = this.parent.clientHeight / this.element.clientHeight; this.vbar.height(this.vratio * this.parent.clientHeight); this.vbar.show(); } else { this.vbar && this.vbar.hide(); } if(this.maxX === 0 && this.maxY === 0) { this.element.style.minWidth = this.parent.clientWidth + 'px'; this.element.style.minHeight = this.parent.clientHeight + 'px'; } } TouchController.prototype.onTouchStart = function(e) { this.scale_pre = false; this.computeBoundaries(); this.startTouchX = e.touches[0].clientX; this.startTouchY = e.touches[0].clientY; this.contentStartOffsetX = this.contentOffsetX; this.contentStartOffsetY = this.contentOffsetY; } TouchController.prototype.onTouchMove = function(e) { var cy = e.touches[0].clientY; var cx = e.touches[0].clientX; if(!this.use2Fingers || (this.use2Fingers && e.touches.length == 2)) { if(this.dragging) { this.animateTo(cx,cy); } else { if (this.isDragging(e)) { TouchController.element_scrolled = true; if(this.forceLayout){ this.element.style.top = 0; this.element.style.webkitTransform = 'translate3d(0,'+this.contentOffsetY+'px,0)'; } this.animateTo(cx,cy); } } } } TouchController.prototype.onTouchEnd = function(e) { if (this.dragging) { if(this.forceLayout){ this.element.style.webkitTransform = 'translate3d(0,0,0)'; this.element.style.top = this.contentOffsetY + 'px'; } this.hbar && this.hbar.hide(); this.vbar && this.vbar.hide(); e.preventDefault(); if (this.shouldStartMomentum()) { //this.doMomentum(); } else { //this.snapToBounds(); } } this.dragging = false; } TouchController.prototype.animateTo = function(cX,cY) { var deltaX = cX - this.startTouchX; var deltaY = cY - this.startTouchY; var offsetX = deltaX + this.contentStartOffsetX; var offsetY = deltaY + this.contentStartOffsetY; var pos = jQuery(this.element).position(); if(this.translate3d) { if(offsetX > 0) offsetX = 0; if(offsetY > 0) offsetY = 0; if(offsetX < this.maxX) offsetX = this.maxX; if(offsetY < this.maxY) offsetY = this.maxY; } else { if(offsetX + pos.left > 0) offsetX = -1*pos.left; if(offsetY + pos.top > 0) offsetY = -1*pos.top; if(pos.left + offsetX < this.maxX) offsetX = this.maxX - pos.left; if(pos.top + offsetY < this.maxY) offsetY = this.maxY - pos.top; } this.contentOffsetX = offsetX; this.contentOffsetY = offsetY; if(this.translate3d || this.use2Fingers) { this.element.style.webkitTransform = 'scale('+this.scale+') translate3d('+ offsetX + 'px,' + offsetY + 'px, 0)'; } else { this.element.style.top = pos.top + offsetY + 'px'; this.element.style.left = pos.left + offsetX + 'px'; } this.hbar && this.hbar.css('left',-1*offsetX*this.hratio+'px'); this.vbar && this.vbar.css('top',-1*offsetY*this.vratio+'px'); } TouchController.prototype.isDragging = function(e) { var dx = e.touches[0].clientX - this.startTouchX; var dy = e.touches[0].clientY - this.startTouchY; var adx = Math.abs(dx); var ady = Math.abs(dy); this.dragging = (adx > this.drag_sensitivity || ady > this.drag_sensitivity) ? true : false; return this.dragging; } TouchController.prototype.shouldStartMomentum = function() { return false; } TouchController.prototype.reset = function() { offsetX = this.contentOffsetX; offsetY = this.contentOffsetY; this.maxX = this.parent.clientWidth - this.element.clientWidth; this.maxY = this.parent.clientHeight - this.element.clientHeight; if(this.translate3d) { this.element.style.webkitTransform = 'scale('+this.scale+') translate3d('+ offsetX + 'px,' + offsetY + 'px, 0)'; this.element.style.webkitTransform = 'scale('+this.scale+') translate3d(0,0,0)'; this.contentOffsetX = 0; this.contentOffsetY = 0; } else { this.element.style.top = 0; this.element.style.left = 0; } } TouchController.prototype.forceRefresh = function() { //this.element.style.webkitTransform = 'scale('+this.scale+') translate3d(0,100px, 0)'; //this.element.style.webkitTransform = 'scale('+this.scale+') translate3d(0,0,0)'; } TouchController.prototype.isBottom = function() { if(this.maxY >= 0) { return false } else { return (this.contentOffsetY - this.maxY) < 10; } } TouchController.prototype.addPadding = function(id,padding) { var w = jQuery('#'+id).width() + padding.right; var h = jQuery('#'+id).height() + padding.bottom; this.element.style.width = w +'px'; this.element.style.height = h +'px'; }