src/js/libs/jquery.touchsplitter.js
changeset 1076 510fd2a482f4
parent 1075 92cb33eb7a75
child 1077 48cdc013fc07
equal deleted inserted replaced
1075:92cb33eb7a75 1076:510fd2a482f4
     1 // Generated by CoffeeScript 1.9.3
       
     2 
       
     3 /*
       
     4  * Touch Splitter JQuery was created by Cole Lawrence(github:ZombieHippie)
       
     5  * This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
       
     6  * Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/.
       
     7  */
       
     8 
       
     9 (function() {
       
    10   var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
       
    11 
       
    12   (function(mod) {
       
    13     if (typeof exports === "object" && typeof module === "object") {
       
    14       return mod(require("jquery"));
       
    15     } else if (typeof define === "function" && define.amd) {
       
    16       return define(["jquery"], mod);
       
    17     } else {
       
    18       return mod(jQuery);
       
    19     }
       
    20   })(function(jQuery) {
       
    21     var $, TouchSplitter;
       
    22     $ = jQuery;
       
    23     $.fn.touchSplit = function(options) {
       
    24       if (options == null) {
       
    25         options = {};
       
    26       }
       
    27       if (this[0].touchSplitter != null) {
       
    28         throw "Cannot make a splitter here! '" + this.selector + "' already has a splitter! Use $('" + this.selector + "')[0].touchSplitter.destroy(<optional side to remove>) to remove it!";
       
    29       }
       
    30       if (this.children().length !== 2 && this.children().length !== 0) {
       
    31         throw "Cannot make a splitter here! Incorrect number of div children in '" + this.selector + "'";
       
    32       }
       
    33       return this[0].touchSplitter = new TouchSplitter(this, options);
       
    34     };
       
    35     return TouchSplitter = (function() {
       
    36       function TouchSplitter(element, options) {
       
    37         var barThick, firstdiv, inners, match, splitterHTML, testCalc, testEm, thickness, units;
       
    38         this.element = element;
       
    39         this.resize = bind(this.resize, this);
       
    40         this.onResize = bind(this.onResize, this);
       
    41         this.onResizeWindow = bind(this.onResizeWindow, this);
       
    42         this.getSecond = bind(this.getSecond, this);
       
    43         this.getFirst = bind(this.getFirst, this);
       
    44         this.stopDragging = bind(this.stopDragging, this);
       
    45         this.drag = bind(this.drag, this);
       
    46         this.startDragging = bind(this.startDragging, this);
       
    47         this.onTouchEnd = bind(this.onTouchEnd, this);
       
    48         this.onTouchMove = bind(this.onTouchMove, this);
       
    49         this.onTouchStart = bind(this.onTouchStart, this);
       
    50         this.onMouseDown = bind(this.onMouseDown, this);
       
    51         this.setPercentages = bind(this.setPercentages, this);
       
    52         this.setDock = bind(this.setDock, this);
       
    53         this.moveBar = bind(this.moveBar, this);
       
    54         this.on = bind(this.on, this);
       
    55         this.toggleDock = bind(this.toggleDock, this);
       
    56         this.setRatios = bind(this.setRatios, this);
       
    57         this.destroy = bind(this.destroy, this);
       
    58         this.element.addClass('TouchSplitter');
       
    59         this.support = {};
       
    60         testEm = $('<div class="test-em"></div>');
       
    61         testEm.appendTo(this.element);
       
    62         barThick = testEm.width();
       
    63         testEm.remove();
       
    64         testCalc = $('<div class="test-calc"></div>');
       
    65         testCalc.appendTo(this.element);
       
    66         this.support.calc = true;
       
    67         testCalc.remove();
       
    68         if (options.orientation != null) {
       
    69           if (options.orientation === "vertical") {
       
    70             this.horizontal = false;
       
    71           } else if (options.orientation === "horizontal") {
       
    72 
       
    73           } else {
       
    74             console.log("Touch Splitter ERROR: orientation cannot be:'" + options.orientation + "' defaulted to 'horizontal'");
       
    75           }
       
    76         }
       
    77         if (this.horizontal !== false) {
       
    78           this.horizontal = true;
       
    79         }
       
    80         this.element.addClass(this.horizontal ? "h-ts" : "v-ts");
       
    81         this.firstMin = options.leftMin || options.topMin || options.firstMin || 0;
       
    82         this.firstMax = options.leftMax || options.topMax || options.firstMax || false;
       
    83         this.secondMin = options.rightMin || options.bottomMin || options.secondMin || 0;
       
    84         this.secondMax = options.rightMax || options.bottomMax || options.secondMax || false;
       
    85         if (this.firstMax && this.secondMax) {
       
    86           console.log("Touch Splitter ERROR: cannot set max bounds of both first and second sections!");
       
    87           this.secondMax = false;
       
    88         }
       
    89         if (options.dock != null) {
       
    90           if (/both|left|top|first|right|bottom|second/i.test(options.dock)) {
       
    91             this.docks = (function() {
       
    92               switch (false) {
       
    93                 case !/both/i.test(options.dock):
       
    94                   return {
       
    95                     first: true,
       
    96                     second: true,
       
    97                     name: "both"
       
    98                   };
       
    99                 case !/left|top|first/i.test(options.dock):
       
   100                   return {
       
   101                     first: true,
       
   102                     second: false,
       
   103                     name: "first"
       
   104                   };
       
   105                 case !/right|bottom|second/i.test(options.dock):
       
   106                   return {
       
   107                     first: false,
       
   108                     second: true,
       
   109                     name: "second"
       
   110                   };
       
   111               }
       
   112             })();
       
   113           }
       
   114         }
       
   115         if (this.docks) {
       
   116           this.element.addClass('docks-' + this.docks.name);
       
   117         } else {
       
   118           this.docks = {
       
   119             first: false,
       
   120             second: false,
       
   121             name: false
       
   122           };
       
   123         }
       
   124         if (options.thickness != null) {
       
   125           thickness = options.thickness;
       
   126           units = "px";
       
   127           if (typeof thickness === 'string') {
       
   128             if (match = thickness.match(/^([\d\.]+)([a-zA-Z]+)$/)) {
       
   129               thickness = match[1];
       
   130               units = match[2];
       
   131             }
       
   132             thickness = parseFloat(thickness);
       
   133           }
       
   134           if (!thickness) {
       
   135             throw "Unable to parse given thickness: " + options.thickness;
       
   136           } else {
       
   137             thickness = (function() {
       
   138               switch (units) {
       
   139                 case "px":
       
   140                   return barThick = thickness;
       
   141                 case "em":
       
   142                   return barThick *= thickness;
       
   143                 default:
       
   144                   throw "Invalid unit used in given thickness: " + units;
       
   145               }
       
   146             })();
       
   147           }
       
   148         }
       
   149         firstdiv = this.element.find(">div:first");
       
   150         splitterHTML = "<div class=\"splitter-bar\">" + (this.docks.name && this.docks.name.match(/first|second/) ? '<div></div>' : '') + "</div>";
       
   151         if (firstdiv.length === 0) {
       
   152           inners = this.element.html();
       
   153           this.element.html("<div></div> " + splitterHTML + " <div></div>");
       
   154           this.element.find(">div:first").html(inners);
       
   155         } else {
       
   156           firstdiv.after(splitterHTML);
       
   157         }
       
   158         this.barThicknessPx = barThick / 2;
       
   159         this.barThickness = .04;
       
   160         this.barPosition = options.barPosition || 0.5;
       
   161         this.dragging = false;
       
   162         this.initMouse = 0;
       
   163         this.initBarPosition = 0;
       
   164         this.resize();
       
   165         this.element.on('resize', this.onResize);
       
   166         $(window).on('resize', this.onResizeWindow);
       
   167         $(window).on('mouseup', this.stopDragging);
       
   168         $(window).on('mousemove', this.drag);
       
   169         this.element.find('>.splitter-bar').on('mousedown', this.onMouseDown);
       
   170         this.element.find('>.splitter-bar').bind('touchstart', this.onTouchStart);
       
   171         this.element.on('touchmove', this.onTouchMove);
       
   172         this.element.on('touchend', this.onTouchEnd);
       
   173         this.element.on('touchleave', this.onTouchEnd);
       
   174         this.element.on('touchcancel', this.onTouchEnd);
       
   175       }
       
   176 
       
   177       TouchSplitter.prototype.destroy = function(side) {
       
   178         var toRemove;
       
   179         this.element.off('resize');
       
   180         $(window).off('resize');
       
   181         $(window).off('mouseup');
       
   182         $(window).off('mousemove');
       
   183         this.element.find('>.splitter-bar').off('mousedown');
       
   184         this.element.find('>.splitter-bar').off('touchstart');
       
   185         this.element.off('touchmove');
       
   186         this.element.off('touchend');
       
   187         this.element.off('touchleave');
       
   188         this.element.off('touchcancel');
       
   189         this.element.find('>.splitter-bar').remove();
       
   190         this.element.removeClass('TouchSplitter h-ts v-ts docks-first docks-second docks-both');
       
   191         if (side != null) {
       
   192           toRemove = (function() {
       
   193             switch (side) {
       
   194               case 'left':
       
   195               case 'top':
       
   196                 return '>div:first';
       
   197               case 'right':
       
   198               case 'bottom':
       
   199                 return '>div:last';
       
   200               case 'both':
       
   201                 return '>div';
       
   202             }
       
   203           })();
       
   204           this.element.find(toRemove).remove();
       
   205         }
       
   206         this.element.children().css({
       
   207           width: "",
       
   208           height: ""
       
   209         });
       
   210         return delete this.element[0].touchSplitter;
       
   211       };
       
   212 
       
   213       TouchSplitter.prototype.setRatios = function() {
       
   214         var conv, ref, val;
       
   215         this.splitDistance = this.horizontal ? this.element.width() : this.element.height();
       
   216         ref = {
       
   217           firstMin: this.firstMin,
       
   218           firstMax: this.firstMax,
       
   219           secondMin: this.secondMin,
       
   220           secondMax: this.secondMax
       
   221         };
       
   222         for (conv in ref) {
       
   223           val = ref[conv];
       
   224           if (val) {
       
   225             this[conv + 'Ratio'] = val / this.splitDistance;
       
   226           }
       
   227         }
       
   228         return this.moveBar();
       
   229       };
       
   230 
       
   231       TouchSplitter.prototype.toggleDock = function() {
       
   232         this.element.toggleClass('docked');
       
   233         if (this.docked) {
       
   234           return this.setDock(false);
       
   235         } else {
       
   236           return this.setDock(this.docks.name);
       
   237         }
       
   238       };
       
   239 
       
   240       TouchSplitter.prototype.on = function(eventName, fn) {
       
   241         return this.element.on(eventName, fn);
       
   242       };
       
   243 
       
   244       TouchSplitter.prototype.moveBar = function(newX) {
       
   245         var cursorPos, cursorPos2;
       
   246         cursorPos = this.barPosition;
       
   247         if (newX != null) {
       
   248           cursorPos = this.initBarPosition + (newX - this.initMouse) / this.splitDistance;
       
   249         }
       
   250         cursorPos2 = 1 - cursorPos;
       
   251         if (this.docks.name) {
       
   252           switch (this.docked) {
       
   253             case 'first':
       
   254               if (cursorPos > this.firstMinRatio / 2) {
       
   255                 this.setDock(false);
       
   256               }
       
   257               break;
       
   258             case 'second':
       
   259               if (cursorPos2 > this.secondMinRatio / 2) {
       
   260                 this.setDock(false);
       
   261               }
       
   262               break;
       
   263             default:
       
   264               if (this.docks.first && cursorPos < this.firstMinRatio / 2) {
       
   265                 this.setDock('first');
       
   266               }
       
   267               if (this.docks.second && cursorPos2 < this.secondMinRatio / 2) {
       
   268                 this.setDock('second');
       
   269               }
       
   270           }
       
   271         }
       
   272         if (!this.docked) {
       
   273           this.barPosition = (function() {
       
   274             switch (false) {
       
   275               case !(this.firstMaxRatio && cursorPos > this.firstMaxRatio):
       
   276                 return this.firstMaxRatio;
       
   277               case !(cursorPos < this.firstMinRatio):
       
   278                 return this.firstMinRatio;
       
   279               case !(this.secondMaxRatio && cursorPos2 > this.secondMaxRatio):
       
   280                 return 1 - this.secondMaxRatio;
       
   281               case !(cursorPos2 < this.secondMinRatio):
       
   282                 return 1 - this.secondMinRatio;
       
   283               default:
       
   284                 return cursorPos;
       
   285             }
       
   286           }).call(this);
       
   287           return this.setPercentages();
       
   288         }
       
   289       };
       
   290 
       
   291       TouchSplitter.prototype.setDock = function(val, lastpos) {
       
   292         if (lastpos == null) {
       
   293           lastpos = this.barPosition;
       
   294         }
       
   295         this.docked = val;
       
   296         this.barPosition = this.lastPosition;
       
   297         this.lastPosition = lastpos;
       
   298         return this.setPercentages();
       
   299       };
       
   300 
       
   301       TouchSplitter.prototype.setPercentages = function() {
       
   302         var attr, first, firstCss, pos, second, secondCss, shave;
       
   303         switch (this.docked) {
       
   304           case 'first':
       
   305             this.barPosition = 0;
       
   306             break;
       
   307           case 'second':
       
   308             this.barPosition = 1;
       
   309         }
       
   310         pos = this.barPosition;
       
   311         firstCss = secondCss = "";
       
   312         if (!this.support.calc) {
       
   313           if (pos < this.barThickness) {
       
   314             pos = this.barThickness;
       
   315           }
       
   316           if (pos > 1 - this.barThickness) {
       
   317             pos = 1 - this.barThickness;
       
   318           }
       
   319           first = pos - this.barThickness;
       
   320           second = 1 - pos - this.barThickness;
       
   321           firstCss = (100 * first - this.barThickness) + "%";
       
   322           secondCss = (100 * second - this.barThickness) + "%";
       
   323         } else {
       
   324           shave = this.barThicknessPx;
       
   325           if (this.docked) {
       
   326             shave *= 2;
       
   327           }
       
   328           pos *= 100;
       
   329           firstCss = "calc(" + pos + "% - " + shave + "px)";
       
   330           secondCss = "calc(" + (100 - pos) + "% - " + shave + "px)";
       
   331         }
       
   332         attr = this.horizontal ? "width" : "height";
       
   333         this.getFirst().css(attr, firstCss);
       
   334         return this.getSecond().css(attr, secondCss);
       
   335       };
       
   336 
       
   337       TouchSplitter.prototype.onMouseDown = function(event) {
       
   338         event.preventDefault();
       
   339         this.initMouse = this.horizontal ? event.clientX : event.clientY;
       
   340         return this.startDragging(event);
       
   341       };
       
   342 
       
   343       TouchSplitter.prototype.onTouchStart = function(event) {
       
   344         var orig;
       
   345         orig = event.originalEvent;
       
   346         this.initMouse = this.horizontal ? orig.changedTouches[0].pageX : orig.changedTouches[0].pageY;
       
   347         return this.startDragging(event);
       
   348       };
       
   349 
       
   350       TouchSplitter.prototype.onTouchMove = function(event) {
       
   351         var orig, page;
       
   352         if (!this.dragging) {
       
   353           return;
       
   354         }
       
   355         event.preventDefault();
       
   356         orig = event.originalEvent;
       
   357         page = this.horizontal ? orig.changedTouches[0].pageX : orig.changedTouches[0].pageY;
       
   358         return this.moveBar(page);
       
   359       };
       
   360 
       
   361       TouchSplitter.prototype.onTouchEnd = function(event) {
       
   362         return this.stopDragging(event);
       
   363       };
       
   364 
       
   365       TouchSplitter.prototype.startDragging = function(event) {
       
   366         this.initBarPosition = this.barPosition;
       
   367         this.isToggler = !!event.target.parentNode.className.match(/\bsplitter-bar\b/);
       
   368         this.dragging = true;
       
   369         return this.element.trigger("dragstart");
       
   370       };
       
   371 
       
   372       TouchSplitter.prototype.drag = function(event) {
       
   373         var client, whichM;
       
   374         if (!this.dragging) {
       
   375           return;
       
   376         }
       
   377         whichM = typeof event.buttons !== 'undefined' ? event.buttons : event.which;
       
   378         if (whichM === 0) {
       
   379           this.stopDragging();
       
   380         }
       
   381         client = this.horizontal ? event.clientX : event.clientY;
       
   382         return this.moveBar(client);
       
   383       };
       
   384 
       
   385       TouchSplitter.prototype.stopDragging = function(event) {
       
   386         if (this.dragging) {
       
   387           this.dragging = false;
       
   388           this.element.trigger("dragstop");
       
   389           if (this.isToggler) {
       
   390             return setTimeout((function(_this) {
       
   391               return function() {
       
   392                 if ((_this.barPosition - _this.initBarPosition) === 0) {
       
   393                   return _this.toggleDock();
       
   394                 }
       
   395               };
       
   396             })(this), 0);
       
   397           }
       
   398         }
       
   399       };
       
   400 
       
   401       TouchSplitter.prototype.getFirst = function() {
       
   402         return this.element.find('>div:first');
       
   403       };
       
   404 
       
   405       TouchSplitter.prototype.getSecond = function() {
       
   406         return this.element.find('>div:last');
       
   407       };
       
   408 
       
   409       TouchSplitter.prototype.onResizeWindow = function(event) {
       
   410         return this.resize();
       
   411       };
       
   412 
       
   413       TouchSplitter.prototype.onResize = function(event) {
       
   414         if (event != null) {
       
   415           event.stopPropagation();
       
   416           if (!$(event.target).is(this.element)) {
       
   417             return;
       
   418           }
       
   419         }
       
   420         return this.resize();
       
   421       };
       
   422 
       
   423       TouchSplitter.prototype.resize = function() {
       
   424         var attr;
       
   425         this.setRatios();
       
   426         attr = this.horizontal ? "width" : "height";
       
   427         if (!this.support.calc) {
       
   428           this.barThickness = this.barThicknessPx / this.splitDistance;
       
   429           if (this.barThickness > 1) {
       
   430             this.barThickness = 1;
       
   431           }
       
   432           this.element.find('>.splitter-bar').css(attr, this.barThickness * 200 + '%');
       
   433         } else {
       
   434           this.barThickness = 0;
       
   435         }
       
   436         return this.setPercentages();
       
   437       };
       
   438 
       
   439       return TouchSplitter;
       
   440 
       
   441     })();
       
   442   });
       
   443 
       
   444 }).call(this);