You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
13 KiB

7 years ago
  1. /*!
  2. * JQuery Spliter Plugin version 0.24.0
  3. * Copyright (C) 2010-2016 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).bind('mouseenter touchstart', function() {
  59. splitter_id = id;
  60. }).bind('mouseleave touchend', function() {
  61. splitter_id = null;
  62. }).insertAfter(panel_1);
  63. var position;
  64. function get_position(position) {
  65. if (typeof position === 'number') {
  66. return position;
  67. } else if (typeof position === 'string') {
  68. var match = position.match(/^([0-9\.]+)(px|%)$/);
  69. if (match) {
  70. if (match[2] == 'px') {
  71. return +match[1];
  72. } else {
  73. if (settings.orientation == 'vertical') {
  74. return (width * +match[1]) / 100;
  75. } else if (settings.orientation == 'horizontal') {
  76. return (height * +match[1]) / 100;
  77. }
  78. }
  79. } else {
  80. //throw position + ' is invalid value';
  81. }
  82. } else {
  83. //throw 'position have invalid type';
  84. }
  85. }
  86. var self = $.extend(this, {
  87. refresh: function() {
  88. var new_width = this.width();
  89. var new_height = this.height();
  90. if (width != new_width || height != new_height) {
  91. width = this.width();
  92. height = this.height();
  93. self.position(position);
  94. }
  95. },
  96. position: (function() {
  97. if (settings.orientation == 'vertical') {
  98. return function(n, silent) {
  99. if (n === undefined) {
  100. return position;
  101. } else {
  102. position = get_position(n);
  103. var sw = splitter.width();
  104. var sw2 = sw/2, pw;
  105. if (settings.invisible) {
  106. pw = panel_1.width(position).outerWidth();
  107. panel_2.width(self.width()-pw);
  108. splitter.css('left', pw-sw2);
  109. } else {
  110. pw = panel_1.width(position-sw2).outerWidth();
  111. panel_2.width(self.width()-pw-sw);
  112. splitter.css('left', pw);
  113. }
  114. panel_1.find('.splitter_panel').eq(0).height(self.height());
  115. panel_2.find('.splitter_panel').eq(0).height(self.height());
  116. }
  117. if (!silent) {
  118. self.trigger('splitter.resize');
  119. self.find('.splitter_panel').trigger('splitter.resize');
  120. }
  121. return self;
  122. };
  123. } else if (settings.orientation == 'horizontal') {
  124. return function(n, silent) {
  125. if (n === undefined) {
  126. return position;
  127. } else {
  128. position = get_position(n);
  129. var sw = splitter.height();
  130. var sw2 = sw/2, pw;
  131. if (settings.invisible) {
  132. pw = panel_1.height(position).outerHeight();
  133. panel_2.height(self.height()-pw);
  134. splitter.css('top', pw-sw2);
  135. } else {
  136. pw = panel_1.height(position-sw2).outerHeight();
  137. panel_2.height(self.height()-pw-sw);
  138. splitter.css('top', pw);
  139. }
  140. }
  141. if (!silent) {
  142. self.trigger('splitter.resize');
  143. self.find('.splitter_panel').trigger('splitter.resize');
  144. }
  145. return self;
  146. };
  147. } else {
  148. return $.noop;
  149. }
  150. })(),
  151. orientation: settings.orientation,
  152. limit: settings.limit,
  153. isActive: function() {
  154. return splitter_id === id;
  155. },
  156. destroy: function() {
  157. self.removeClass('splitter_panel');
  158. splitter.unbind('mouseenter');
  159. splitter.unbind('mouseleave');
  160. splitter.unbind('touchstart');
  161. splitter.unbind('touchmove');
  162. splitter.unbind('touchend');
  163. splitter.unbind('touchleave');
  164. splitter.unbind('touchcancel');
  165. if (settings.orientation == 'vertical') {
  166. panel_1.removeClass('left_panel');
  167. panel_2.removeClass('right_panel');
  168. } else if (settings.orientation == 'horizontal') {
  169. panel_1.removeClass('top_panel');
  170. panel_2.removeClass('bottom_panel');
  171. }
  172. self.unbind('splitter.resize');
  173. self.trigger('splitter.resize');
  174. self.find('.splitter_panel').trigger('splitter.resize');
  175. splitters[id] = null;
  176. count--;
  177. splitter.remove();
  178. self.removeData('splitter');
  179. var not_null = false;
  180. for (var i=splitters.length; i--;) {
  181. if (splitters[i] !== null) {
  182. not_null = true;
  183. break;
  184. }
  185. }
  186. //remove document events when no splitters
  187. if (!not_null) {
  188. $(document.documentElement).unbind('.splitter');
  189. $(window).unbind('resize.splitter');
  190. splitters = [];
  191. count = 0;
  192. }
  193. }
  194. });
  195. self.bind('splitter.resize', function(e) {
  196. var pos = self.position();
  197. if (self.orientation == 'vertical' &&
  198. pos > self.width()) {
  199. pos = self.width() - self.limit-1;
  200. } else if (self.orientation == 'horizontal' &&
  201. pos > self.height()) {
  202. pos = self.height() - self.limit-1;
  203. }
  204. if (pos < self.limit) {
  205. pos = self.limit + 1;
  206. }
  207. e.stopPropagation();
  208. self.position(pos, true);
  209. });
  210. //inital position of splitter
  211. var pos;
  212. if (settings.orientation == 'vertical') {
  213. if (pos > width-settings.limit) {
  214. pos = width-settings.limit;
  215. } else {
  216. pos = get_position(settings.position);
  217. }
  218. } else if (settings.orientation == 'horizontal') {
  219. //position = height/2;
  220. if (pos > height-settings.limit) {
  221. pos = height-settings.limit;
  222. } else {
  223. pos = get_position(settings.position);
  224. }
  225. }
  226. if (pos < settings.limit) {
  227. pos = settings.limit;
  228. }
  229. self.position(pos, true);
  230. var parent = this.closest('.splitter_panel');
  231. if (parent.length) {
  232. this.height(parent.height());
  233. }
  234. // bind events to document if no splitters
  235. if (splitters.filter(Boolean).length === 0) {
  236. $(window).bind('resize.splitter', function() {
  237. $.each(splitters, function(i, splitter) {
  238. if (splitter) {
  239. splitter.refresh();
  240. }
  241. });
  242. });
  243. $(document.documentElement).on('mousedown.splitter touchstart.splitter', function(e) {
  244. if (splitter_id !== null) {
  245. e.preventDefault();
  246. current_splitter = splitters[splitter_id];
  247. setTimeout(function() {
  248. $('<div class="splitterMask"></div>').
  249. css('cursor', current_splitter.children().eq(1).css('cursor')).
  250. insertAfter(current_splitter);
  251. });
  252. current_splitter.settings.onDragStart(e);
  253. }
  254. }).bind('mouseup.splitter touchend.splitter touchleave.splitter touchcancel.splitter', function(e) {
  255. if (current_splitter) {
  256. setTimeout(function() {
  257. $('.splitterMask').remove();
  258. });
  259. current_splitter.settings.onDragEnd(e);
  260. current_splitter = null;
  261. }
  262. }).bind('mousemove.splitter touchmove.splitter', function(e) {
  263. if (current_splitter !== null) {
  264. var limit = current_splitter.limit;
  265. var offset = current_splitter.offset();
  266. if (current_splitter.orientation == 'vertical') {
  267. var pageX = e.pageX;
  268. if(e.originalEvent && e.originalEvent.changedTouches){
  269. pageX = e.originalEvent.changedTouches[0].pageX;
  270. }
  271. var x = pageX - offset.left;
  272. if (x <= current_splitter.limit) {
  273. x = current_splitter.limit + 1;
  274. } else if (x >= current_splitter.width() - limit) {
  275. x = current_splitter.width() - limit - 1;
  276. }
  277. if (x > current_splitter.limit &&
  278. x < current_splitter.width()-limit) {
  279. current_splitter.position(x, true);
  280. current_splitter.trigger('splitter.resize');
  281. current_splitter.find('.splitter_panel').
  282. trigger('splitter.resize');
  283. //e.preventDefault();
  284. }
  285. } else if (current_splitter.orientation == 'horizontal') {
  286. var pageY = e.pageY;
  287. if(e.originalEvent && e.originalEvent.changedTouches){
  288. pageY = e.originalEvent.changedTouches[0].pageY;
  289. }
  290. var y = pageY-offset.top;
  291. if (y <= current_splitter.limit) {
  292. y = current_splitter.limit + 1;
  293. } else if (y >= current_splitter.height() - limit) {
  294. y = current_splitter.height() - limit - 1;
  295. }
  296. if (y > current_splitter.limit &&
  297. y < current_splitter.height()-limit) {
  298. current_splitter.position(y, true);
  299. current_splitter.trigger('splitter.resize');
  300. current_splitter.find('.splitter_panel').
  301. trigger('splitter.resize');
  302. //e.preventDefault();
  303. }
  304. }
  305. current_splitter.settings.onDrag(e);
  306. }
  307. });//*/
  308. }
  309. splitters[id] = self;
  310. self.data('splitter', self);
  311. return self;
  312. };
  313. })(jQuery);