/*! * JQuery Spliter Plugin * Copyright (C) 2010-2013 Jakub Jankiewicz * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ (function($, undefined) { var count = 0; var splitter_id = null; var splitters = []; var current_splitter = null; $.fn.split = function(options) { var data = this.data('splitter'); if (data) { return data; } var panel_1; var panel_2; var settings = $.extend({ limit: 100, orientation: 'horizontal', position: '50%', invisible: false, onDragStart: $.noop, onDragEnd: $.noop, onDrag: $.noop }, options || {}); this.settings = settings; var cls; var children = this.children(); if (settings.orientation == 'vertical') { panel_1 = children.first().addClass('left_panel'); panel_2 = panel_1.next().addClass('right_panel'); cls = 'vsplitter'; } else if (settings.orientation == 'horizontal') { panel_1 = children.first().addClass('top_panel') panel_2 = panel_1.next().addClass('bottom_panel'); cls = 'hsplitter'; } if (settings.invisible) { cls += ' splitter-invisible'; } var width = this.width(); var height = this.height(); var id = count++; this.addClass('splitter_panel'); var splitter = $('
').addClass(cls).bind('mouseenter touchstart', function() { splitter_id = id; }).bind('mouseleave touchend', function() { splitter_id = null; }).insertAfter(panel_1); var position; function get_position(position) { if (typeof position === 'number') { return position; } else if (typeof position === 'string') { var match = position.match(/^([0-9]+)(px|%)$/); if (match) { if (match[2] == 'px') { return +match[1]; } else { if (settings.orientation == 'vertical') { return (width * +match[1]) / 100; } else if (settings.orientation == 'horizontal') { return (height * +match[1]) / 100; } } } else { //throw position + ' is invalid value'; } } else { //throw 'position have invalid type'; } } var self = $.extend(this, { refresh: function() { var new_width = this.width(); var new_height = this.height(); if (width != new_width || height != new_height) { width = this.width(); height = this.height(); self.position(position); } }, position: (function() { if (settings.orientation == 'vertical') { return function(n, silent) { if (n === undefined) { return position; } else { position = get_position(n); var sw = splitter.width(); var sw2 = sw/2; if (settings.invisible) { var pw = panel_1.width(position).outerWidth(); panel_2.width(self.width()-pw); splitter.css('left', pw-sw2); } else { var pw = panel_1.width(position-sw2).outerWidth(); panel_2.width(self.width()-pw-sw); splitter.css('left', pw); } } if (!silent) { self.find('.splitter_panel').trigger('splitter.resize'); } return self; }; } else if (settings.orientation == 'horizontal') { return function(n, silent) { if (n === undefined) { return position; } else { position = get_position(n); var sw = splitter.height(); var sw2 = sw/2; if (settings.invisible) { var pw = panel_1.height(position).outerHeight(); panel_2.height(self.height()-pw); splitter.css('top', pw-sw2); } else { var pw = panel_1.height(position-sw2).outerHeight(); panel_2.height(self.height()-pw-sw); splitter.css('top', pw); } } if (!silent) { self.find('.splitter_panel').trigger('splitter.resize'); } return self; }; } else { return $.noop; } })(), orientation: settings.orientation, limit: settings.limit, isActive: function() { return splitter_id === id; }, destroy: function() { self.removeClass('splitter_panel'); splitter.unbind('mouseenter'); splitter.unbind('mouseleave'); splitter.unbind('touchstart'); splitter.unbind('touchmove'); splitter.unbind('touchend'); splitter.unbind('touchleave'); splitter.unbind('touchcancel'); if (settings.orientation == 'vertical') { panel_1.removeClass('left_panel'); panel_2.removeClass('right_panel'); } else if (settings.orientation == 'horizontal') { panel_1.removeClass('top_panel'); panel_2.removeClass('bottom_panel'); } self.unbind('splitter.resize'); self.find('.splitter_panel').trigger('splitter.resize'); splitters[id] = null; splitter.remove(); var not_null = false; for (var i=splitters.length; i--;) { if (splitters[i] !== null) { not_null = true; break; } } //remove document events when no splitters if (!not_null) { $(document.documentElement).unbind('.splitter'); $(window).unbind('resize.splitter'); self.data('splitter', null); splitters = []; count = 0; } } }); self.bind('splitter.resize', function(e) { var pos = self.position(); if (self.orientation == 'vertical' && pos > self.width()) { pos = self.width() - self.limit-1; } else if (self.orientation == 'horizontal' && pos > self.height()) { pos = self.height() - self.limit-1; } if (pos < self.limit) { pos = self.limit + 1; } self.position(pos, true); }); //inital position of splitter var pos; if (settings.orientation == 'vertical') { if (pos > width-settings.limit) { pos = width-settings.limit; } else { pos = get_position(settings.position); } } else if (settings.orientation == 'horizontal') { //position = height/2; if (pos > height-settings.limit) { pos = height-settings.limit; } else { pos = get_position(settings.position); } } if (pos < settings.limit) { pos = settings.limit; } self.position(pos, true); if (splitters.length == 0) { // first time bind events to document $(window).bind('resize.splitter', function() { $.each(splitters, function(i, splitter) { splitter.refresh(); }); }); $(document.documentElement).bind('mousedown.splitter touchstart.splitter', function(e) { if (splitter_id !== null) { current_splitter = splitters[splitter_id]; $('
').css('cursor', splitter.css('cursor')).insertAfter(current_splitter); current_splitter.settings.onDragStart(e); return false; } }).bind('mouseup.splitter touchend.splitter touchleave.splitter touchcancel.splitter', function(e) { if (current_splitter) { $('.splitterMask').remove(); current_splitter.settings.onDragEnd(e); current_splitter = null; } }).bind('mousemove.splitter touchmove.splitter', function(e) { if (current_splitter !== null) { var limit = current_splitter.limit; var offset = current_splitter.offset(); if (current_splitter.orientation == 'vertical') { var pageX = e.pageX; if(e.originalEvent && e.originalEvent.changedTouches){ pageX = e.originalEvent.changedTouches[0].pageX; } var x = pageX - offset.left; if (x <= current_splitter.limit) { x = current_splitter.limit + 1; } else if (x >= current_splitter.width() - limit) { x = current_splitter.width() - limit - 1; } if (x > current_splitter.limit && x < current_splitter.width()-limit) { current_splitter.position(x, true); current_splitter.find('.splitter_panel'). trigger('splitter.resize'); e.preventDefault(); } } else if (current_splitter.orientation == 'horizontal') { var pageY = e.pageY; if(e.originalEvent && e.originalEvent.changedTouches){ pageY = e.originalEvent.changedTouches[0].pageY; } var y = pageY-offset.top; if (y <= current_splitter.limit) { y = current_splitter.limit + 1; } else if (y >= current_splitter.height() - limit) { y = current_splitter.height() - limit - 1; } if (y > current_splitter.limit && y < current_splitter.height()-limit) { current_splitter.position(y, true); current_splitter.find('.splitter_panel'). trigger('splitter.resize'); e.preventDefault(); } } current_splitter.settings.onDrag(e); } }); } splitters.push(self); self.data('splitter', self); return self; }; })(jQuery);