src/js/libs/jquery.splitter.js
changeset 1033 c20df1c080e6
child 1057 3f20f286d43e
equal deleted inserted replaced
1032:74ac0be7655c 1033:c20df1c080e6
       
     1 /*!
       
     2  * JQuery Spliter Plugin
       
     3  * Copyright (C) 2010-2013 Jakub Jankiewicz <http://jcubic.pl> 
       
     4  *
       
     5  * This program is free software: you can redistribute it and/or modify
       
     6  * it under the terms of the GNU Lesser General Public License as published by
       
     7  * the Free Software Foundation, either version 3 of the License, or
       
     8  * (at your option) any later version.
       
     9  *
       
    10  * This program is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13  * GNU Lesser General Public License for more details.
       
    14  * 
       
    15  * You should have received a copy of the GNU Lesser General Public License
       
    16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
       
    17  */
       
    18 (function($, undefined) {
       
    19     var count = 0;
       
    20     var splitter_id = null;
       
    21     var splitters = [];
       
    22     var current_splitter = null;
       
    23     $.fn.split = function(options) {
       
    24         var data = this.data('splitter');
       
    25         if (data) {
       
    26             return data;
       
    27         }
       
    28         var panel_1;
       
    29         var panel_2;
       
    30         var settings = $.extend({
       
    31             limit: 100,
       
    32             orientation: 'horizontal',
       
    33             position: '50%',
       
    34             invisible: false,
       
    35             onDragStart: $.noop,
       
    36             onDragEnd: $.noop,
       
    37             onDrag: $.noop
       
    38         }, options || {});
       
    39         this.settings = settings;
       
    40         var cls;
       
    41         var children = this.children();
       
    42         if (settings.orientation == 'vertical') {
       
    43             panel_1 = children.first().addClass('left_panel');
       
    44             panel_2 = panel_1.next().addClass('right_panel');
       
    45             cls = 'vsplitter';
       
    46         } else if (settings.orientation == 'horizontal') {
       
    47             panel_1 = children.first().addClass('top_panel')
       
    48             panel_2 = panel_1.next().addClass('bottom_panel');
       
    49             cls = 'hsplitter';
       
    50         }
       
    51         if (settings.invisible) {
       
    52             cls += ' splitter-invisible';
       
    53         }
       
    54         var width = this.width();
       
    55         var height = this.height();
       
    56         var id = count++;
       
    57         this.addClass('splitter_panel');
       
    58         var splitter = $('<div/>').addClass(cls).mouseenter(function() {
       
    59             splitter_id = id;
       
    60         }).mouseleave(function() {
       
    61             splitter_id = null;
       
    62         }).insertAfter(panel_1);
       
    63         var position;
       
    64 
       
    65         function get_position(position) {
       
    66             if (typeof position === 'number') {
       
    67                 return position;
       
    68             } else if (typeof position === 'string') {
       
    69                 var match = position.match(/^([0-9]+)(px|%)$/);
       
    70                 if (match) {
       
    71                     if (match[2] == 'px') {
       
    72                         return +match[1];
       
    73                     } else {
       
    74                         if (settings.orientation == 'vertical') {
       
    75                             return (width * +match[1]) / 100;
       
    76                         } else if (settings.orientation == 'horizontal') {
       
    77                             return (height * +match[1]) / 100;
       
    78                         }
       
    79                     }
       
    80                 } else {
       
    81                     //throw position + ' is invalid value';
       
    82                 }
       
    83             } else {
       
    84                 //throw 'position have invalid type';
       
    85             }
       
    86         }
       
    87 
       
    88         var self = $.extend(this, {
       
    89             refresh: function() {
       
    90                 var new_width = this.width();
       
    91                 var new_height = this.height();
       
    92                 if (width != new_width || height != new_height) {
       
    93                     width = this.width();
       
    94                     height = this.height();
       
    95                     self.position(position);
       
    96                 }
       
    97             },
       
    98             position: (function() {
       
    99                 if (settings.orientation == 'vertical') {
       
   100                     return function(n, silent) {
       
   101                         if (n === undefined) {
       
   102                             return position;
       
   103                         } else {
       
   104                             position = get_position(n);
       
   105                             var sw = splitter.width();
       
   106                             var sw2 = sw/2;
       
   107                             if (settings.invisible) {
       
   108                                 var pw = panel_1.width(position).outerWidth();
       
   109                                 panel_2.width(self.width()-pw);
       
   110                                 splitter.css('left', pw-sw2);
       
   111                             } else {
       
   112                                 var pw = panel_1.width(position-sw2).outerWidth();
       
   113                                 panel_2.width(self.width()-pw-sw);
       
   114                                 splitter.css('left', pw);
       
   115                             }
       
   116                         }
       
   117                         if (!silent) {
       
   118                             self.find('.splitter_panel').trigger('splitter.resize');
       
   119                         }
       
   120                         return self;
       
   121                     };
       
   122                 } else if (settings.orientation == 'horizontal') {
       
   123                     return function(n, silent) {
       
   124                         if (n === undefined) {
       
   125                             return position;
       
   126                         } else {
       
   127                             position = get_position(n);
       
   128                             var sw = splitter.height();
       
   129                             var sw2 = sw/2;
       
   130                             if (settings.invisible) {
       
   131                                 var pw = panel_1.height(position).outerHeight();
       
   132                                 panel_2.height(self.height()-pw);
       
   133                                 splitter.css('top', pw-sw2);
       
   134                             } else {
       
   135                                 var pw = panel_1.height(position-sw2).outerHeight();
       
   136                                 panel_2.height(self.height()-pw-sw);
       
   137                                 splitter.css('top', pw);
       
   138                             }
       
   139                         }
       
   140                         if (!silent) {
       
   141                             self.find('.splitter_panel').trigger('splitter.resize');
       
   142                         }
       
   143                         return self;
       
   144                     };
       
   145                 } else {
       
   146                     return $.noop;
       
   147                 }
       
   148             })(),
       
   149             orientation: settings.orientation,
       
   150             limit: settings.limit,
       
   151             isActive: function() {
       
   152                 return splitter_id === id;
       
   153             },
       
   154             destroy: function() {
       
   155                 self.removeClass('splitter_panel');
       
   156                 splitter.unbind('mouseenter');
       
   157                 splitter.unbind('mouseleave');
       
   158                 if (settings.orientation == 'vertical') {
       
   159                     panel_1.removeClass('left_panel');
       
   160                     panel_2.removeClass('right_panel');
       
   161                 } else if (settings.orientation == 'horizontal') {
       
   162                     panel_1.removeClass('top_panel');
       
   163                     panel_2.removeClass('bottom_panel');
       
   164                 }
       
   165                 self.unbind('splitter.resize');
       
   166                 self.find('.splitter_panel').trigger('splitter.resize');
       
   167                 splitters[id] = null;
       
   168                 splitter.remove();
       
   169                 var not_null = false;
       
   170                 for (var i=splitters.length; i--;) {
       
   171                     if (splitters[i] !== null) {
       
   172                         not_null = true;
       
   173                         break;
       
   174                     }
       
   175                 }
       
   176                 //remove document events when no splitters
       
   177                 if (!not_null) {
       
   178                     $(document.documentElement).unbind('.splitter');
       
   179                     $(window).unbind('resize.splitter');
       
   180                     self.data('splitter', null);
       
   181                     splitters = [];
       
   182                     count = 0;
       
   183                 }
       
   184             }
       
   185         });
       
   186         self.bind('splitter.resize', function(e) {
       
   187             var pos = self.position();
       
   188             if (self.orientation == 'vertical' && 
       
   189                 pos > self.width()) {
       
   190                 pos = self.width() - self.limit-1;
       
   191             } else if (self.orientation == 'horizontal' && 
       
   192                        pos > self.height()) {
       
   193                 pos = self.height() - self.limit-1;
       
   194             }
       
   195             if (pos < self.limit) {
       
   196                 pos = self.limit + 1;
       
   197             }
       
   198             self.position(pos, true);
       
   199         });
       
   200         //inital position of splitter
       
   201         var pos;
       
   202         if (settings.orientation == 'vertical') {
       
   203             if (pos > width-settings.limit) {
       
   204                 pos = width-settings.limit;
       
   205             } else {
       
   206                 pos = get_position(settings.position);
       
   207             }
       
   208         } else if (settings.orientation == 'horizontal') {
       
   209             //position = height/2;
       
   210             if (pos > height-settings.limit) {
       
   211                 pos = height-settings.limit;
       
   212             } else {
       
   213                 pos = get_position(settings.position);
       
   214             }
       
   215         }
       
   216         if (pos < settings.limit) {
       
   217             pos = settings.limit;
       
   218         }
       
   219         self.position(pos, true);
       
   220         if (splitters.length == 0) { // first time bind events to document
       
   221             $(window).bind('resize.splitter', function() {
       
   222                 $.each(splitters, function(i, splitter) {
       
   223                     splitter.refresh();
       
   224                 });
       
   225             });
       
   226             $(document.documentElement).bind('mousedown.splitter', function(e) {
       
   227                 if (splitter_id !== null && e.which == 1) {
       
   228                     current_splitter = splitters[splitter_id];
       
   229                     $('<div class="splitterMask"></div>').css('cursor', splitter.css('cursor')).insertAfter(current_splitter);
       
   230                     current_splitter.settings.onDragStart(e);
       
   231                     return false;
       
   232                 }
       
   233             }).bind('mouseup.splitter', function(e) {
       
   234                 if (current_splitter) {
       
   235                     $('.splitterMask').remove();
       
   236                     current_splitter.settings.onDragEnd(e);
       
   237                     current_splitter = null;
       
   238                 }
       
   239             }).bind('mousemove.splitter', function(e) {
       
   240                 if (current_splitter !== null) {
       
   241                     var limit = current_splitter.limit;
       
   242                     var offset = current_splitter.offset();
       
   243                     if (current_splitter.orientation == 'vertical') {
       
   244                         var x = e.pageX - offset.left;
       
   245                         if (x <= current_splitter.limit) {
       
   246                             x = current_splitter.limit + 1;
       
   247                         } else if (x >= current_splitter.width() - limit) {
       
   248                             x = current_splitter.width() - limit - 1;
       
   249                         }
       
   250                         if (x > current_splitter.limit &&
       
   251                             x < current_splitter.width()-limit) {
       
   252                             current_splitter.position(x, true);
       
   253                             current_splitter.trigger('splitter.resize');
       
   254                             e.preventDefault();
       
   255                         }
       
   256                     } else if (current_splitter.orientation == 'horizontal') {
       
   257                         var y = e.pageY-offset.top;
       
   258                         if (y <= current_splitter.limit) {
       
   259                             y = current_splitter.limit + 1;
       
   260                         } else if (y >= current_splitter.height() - limit) {
       
   261                             y = current_splitter.height() - limit - 1;
       
   262                         }
       
   263                         if (y > current_splitter.limit &&
       
   264                             y < current_splitter.height()-limit) {
       
   265                             current_splitter.position(y, true);
       
   266                             current_splitter.trigger('splitter.resize');
       
   267                             e.preventDefault();
       
   268                         }
       
   269                     }
       
   270                     current_splitter.settings.onDrag(e);
       
   271                 }
       
   272             });
       
   273         }
       
   274         splitters.push(self);
       
   275         self.data('splitter', self);
       
   276         return self;
       
   277     };
       
   278 })(jQuery);