Permalink
Browse files

First take at extracting the code from Cohuman. Documentation coming

  • Loading branch information...
1 parent 6394109 commit 9d6515e50938f8bc494a6e8aed13aae5347249ea @makebbekus makebbekus committed Aug 9, 2010
Showing with 807 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +183 −0 iScroller.js
  3. +61 −0 lib/class_inheritance.js
  4. +154 −0 lib/jquery-1.4.2.min.js
  5. +95 −0 lib/jquery-ui-1.8.4.custom.min.js
  6. +302 −0 spec/i_scroller_js_spec.rb
  7. +11 −0 spec/spec_helper.js
View
@@ -0,0 +1 @@
+.DS_Store
View
@@ -0,0 +1,183 @@
+var iScroller = Class.extend({
+ init : function(dom){
+ this.dom = $(dom);
+ this.rebuildDom();
+ this.addListeners();
+ this.sensitivity = 10;
+ },
+
+ addListeners : function(){
+ var self = this;
+ this.viewContent.unbind();
+
+ this.viewContent.bind('touchstart', function(e){
+ var c = self.coordinates(e);
+ self.touchStart(c[self.axis]);
+ });
+
+ this.viewContent.bind('touchmove', function(e){
+ var c = self.coordinates(e);
+ self.scroll(c[self.axis]);
+ });
+
+ this.viewContent.bind('touchend', function(e){
+ var c = self.coordinates(e);
+ self.coast(c[self.axis]);
+ });
+
+ $(window).bind('orientationchange', function(){
+ self.calculateDimensions();
+ });
+ },
+
+ rebuildDom : function(){
+ this.dom.children().wrapAll('<div class="view_content"></div>');
+ this.viewContent = this.dom.find('.view_content');
+ this.viewContent.css('position', 'relative');
+ this.viewContent.css(this.dimension, 'auto');
+ this.calculateDimensions();
+ },
+
+ calculateDimensions : function(){
+ this.viewContentDimension = this.calcViewContentDimension();
+ this.scrollerDimension = this.calcScrollerDimension();
+ },
+
+ touchStart : function(d){
+ this.start = d;
+ this.current = this.start;
+ this.startTime = new Date().getTime();
+ },
+
+ scroll : function(d){
+ var diff = d - this.current;
+ if (Math.abs(d - this.start) < this.sensitivity){
+ return;
+ }
+ this.current += diff;
+ var direction = (diff >= 0 ? 1 : -1);
+ var desiredPosition = this.viewContentPosition() + diff;
+ var boundary = this.boundaryCheck(desiredPosition);
+
+ if (boundary != null){
+ diff = direction * 100 * (1 - Math.exp(-0.01 * Math.abs(d - this.start)));
+ this.setViewContentPosition(boundary + diff)
+ } else {
+ this.setViewContentPosition(this.viewContentPosition() + diff);
+ }
+ },
+
+ coast : function(d){
+ var diff = d - this.start;
+ if (Math.abs(diff) < this.sensitivity){
+ return;
+ }
+
+ var swipeDurationInSeconds = (new Date().getTime() - this.startTime) / 1000;
+ var coast = 2 * (diff) * Math.exp(-swipeDurationInSeconds);
+
+ var self = this;
+
+ this.viewContent.stop(false, true).animate(
+ this.animateProperties(this.viewContentPosition() + coast),
+ {
+ duration: 1000,
+ easing: 'easeOutCubic',
+ step : function(){
+ self.bounceBack();
+ }
+ }
+ );
+ },
+
+ boundaryCheck : function(viewContentPosition){
+ this.calculateDimensions();
+
+ var boundary = null;
+ var nothingToScroll = this.viewContentDimension <= this.scrollerDimension;
+ var overExtension = this.viewContentDimension - this.scrollerDimension;
+
+ if (nothingToScroll){
+ boundary = 0;
+ } else {
+ if (viewContentPosition >= 0){ // preextended
+ boundary = 0
+ } else if (-viewContentPosition > overExtension) { //overextended
+ boundary = -overExtension
+ }
+ }
+
+ return boundary;
+ },
+
+ bounceBack : function(){
+ var boundary = this.boundaryCheck(this.viewContentPosition());
+
+ if (boundary != null) {
+ this.viewContent.stop().animate(
+ this.animateProperties(boundary),
+ {
+ duration: 500,
+ easing : 'easeOutCubic'
+ }
+ );
+ }
+ },
+
+ viewContentPosition : function(){
+ var pos = this.viewContent.css(this.cssAxis);
+ return pos == "auto" ? 0 : +(pos.replace("px", ""));
+ },
+
+ setViewContentPosition : function(val){
+ this.viewContent.css(this.cssAxis, val)
+ },
+
+ coordinates : function(e){
+ var changedTouches = e.originalEvent.changedTouches;
+ var lastTouch = changedTouches.item(changedTouches.length - 1);
+ return {x: lastTouch.screenX, y : lastTouch.screenY};
+ }
+});
+
+var iScrollerY = iScroller.extend({
+ init : function(dom){
+ this.axis = 'y';
+ this.dimension = 'height';
+ this.cssAxis = 'top';
+ this._super(dom);
+ },
+
+ animateProperties : function(val){
+ return { top : val };
+ },
+
+ calcViewContentDimension : function(){
+ return this.viewContent.innerHeight();
+ },
+
+ calcScrollerDimension : function(){
+ return this.dom.innerHeight();
+ }
+});
+
+var iScrollerX = iScroller.extend({
+ init : function(dom){
+ this.axis = 'x';
+ this.dimension = 'width';
+ this.cssAxis = 'left';
+ this._super(dom);
+ },
+
+ animateProperties : function(val){
+ return { left : val };
+ },
+
+ calcViewContentDimension : function(){
+ return this.viewContent.attr('scrollWidth');
+ },
+
+ calcScrollerDimension : function(){
+ return this.dom.innerWidth();
+ }
+});
@@ -0,0 +1,61 @@
+// FROM: http://ejohn.org/blog/simple-javascript-inheritance/
+// Inspired by base2 and Prototype
+(function(){
+ var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
+
+ // The base Class implementation (does nothing)
+ this.Class = function(){};
+
+ // Create a new Class that inherits from this class
+ Class.extend = function(prop) {
+ var _super = this.prototype;
+
+ // Instantiate a base class (but only create the instance,
+ // don't run the init constructor)
+ initializing = true;
+ var prototype = new this();
+ initializing = false;
+
+ // Copy the properties over onto the new prototype
+ for (var name in prop) {
+ // Check if we're overwriting an existing function
+ prototype[name] = typeof prop[name] == "function" &&
+ typeof _super[name] == "function" && fnTest.test(prop[name]) ?
+ (function(name, fn){
+ return function() {
+ var tmp = this._super;
+
+ // Add a new ._super() method that is the same method
+ // but on the super-class
+ this._super = _super[name];
+
+ // The method only need to be bound temporarily, so we
+ // remove it when we're done executing
+ var ret = fn.apply(this, arguments);
+ this._super = tmp;
+
+ return ret;
+ };
+ })(name, prop[name]) :
+ prop[name];
+ }
+
+ // The dummy class constructor
+ function Class() {
+ // All construction is actually done in the init method
+ if ( !initializing && this.init )
+ this.init.apply(this, arguments);
+ }
+
+ // Populate our constructed prototype object
+ Class.prototype = prototype;
+
+ // Enforce the constructor to be what we expect
+ Class.constructor = Class;
+
+ // And make this class extendable
+ Class.extend = arguments.callee;
+
+ return Class;
+ };
+})();
Oops, something went wrong.

0 comments on commit 9d6515e

Please sign in to comment.