PageRenderTime 24ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/RazorPad.Website/Scripts/splitter.js

#
JavaScript | 187 lines | 131 code | 19 blank | 37 comment | 18 complexity | fabf5c316e0facf99e427e98ae5b1c82 MD5 | raw file
  1. /*
  2. * jQuery.splitter.js - animated splitter plugin
  3. *
  4. * version 1.0 (2010/01/02)
  5. *
  6. * Dual licensed under the MIT and GPL licenses:
  7. * http://www.opensource.org/licenses/mit-license.php
  8. * http://www.gnu.org/licenses/gpl.html
  9. */
  10. /**
  11. * jQuery.splitter() plugin implements a two-pane resizable animated window, using existing DIV elements for layout.
  12. * For more details and demo visit: http://krikus.com/js/splitter
  13. *
  14. * @example $("#splitterContainer").splitter({splitVertical:true,A:$('#leftPane'),B:$('#rightPane'),closeableto:0});
  15. * @desc Create a vertical splitter with toggle button
  16. *
  17. * @example $("#splitterContainer").splitter({minAsize:100,maxAsize:300,splitVertical:true,A:$('#leftPane'),B:$('#rightPane'),slave:$("#rightSplitterContainer"),closeableto:0});
  18. * @desc Create a vertical splitter with toggle button, with minimum and maximum width for plane A and bind resize event to the slave element
  19. *
  20. * @name splitter
  21. * @type jQuery
  22. * @param Object options Options for the splitter ( required)
  23. * @cat Plugins/Splitter
  24. * @return jQuery
  25. * @author Kristaps Kukurs (contact@krikus.com)
  26. */
  27. ;(function($){
  28. $.fn.splitter = function(args){
  29. args = args || {};
  30. return this.each(function() {
  31. var _ghost; //splitbar ghosted element
  32. var splitPos; // current splitting position
  33. var _splitPos; // saved splitting position
  34. var _initPos; //initial mouse position
  35. var _ismovingNow=false; // animaton state flag
  36. // Default opts
  37. var direction = (args.splitHorizontal? 'h':'v');
  38. var opts = $.extend({
  39. minAsize:0, //minimum width/height in PX of the first (A) div.
  40. maxAsize:0, //maximum width/height in PX of the first (A) div.
  41. minBsize:0, //minimum width/height in PX of the second (B) div.
  42. maxBsize:0, //maximum width/height in PX of the second (B) div.
  43. ghostClass: 'working',// class name for _ghosted splitter and hovered button
  44. invertClass: 'invert',//class name for invert splitter button
  45. animSpeed: 250 //animation speed in ms
  46. },{
  47. v:{ // Vertical
  48. moving:"left",sizing: "width", eventPos: "pageX",splitbarClass:"splitbarV",buttonClass: "splitbuttonV", cursor: "e-resize"
  49. },
  50. h: { // Horizontal
  51. moving:"top",sizing: "height", eventPos: "pageY",splitbarClass:"splitbarH",buttonClass: "splitbuttonH", cursor: "n-resize"
  52. }
  53. }[direction], args);
  54. //setup elements
  55. var splitter = $(this);
  56. var mychilds =splitter.children(); //$(">*", splitter[0]);
  57. var A = args.A; // left/top frame
  58. var B = args.B;// right/bottom frame
  59. var slave=args.slave;//optional, elemt forced to receive resize event
  60. //Create splitbar
  61. var C=$('<div><span></span></div>');
  62. A.after(C);
  63. C.attr({"class": opts.splitbarClass,unselectable:"on"}).css({"cursor":opts.cursor,"user-select": "none", "-webkit-user-select": "none","-khtml-user-select": "none", "-moz-user-select": "none"})
  64. .bind("mousedown", startDrag);
  65. if(opts.closeableto!=undefined){
  66. var Bt=$('<div></div>').css("cursor",'pointer');
  67. C.append(Bt);
  68. Bt.attr({"class": opts.buttonClass, unselectable: "on"});
  69. Bt.hover(function(){$(this).addClass(opts.ghostClass);},function(){$(this).removeClass(opts.ghostClass);});
  70. Bt.mousedown(function(e){if(e.target != this)return;Bt.toggleClass(opts.invertClass).hide();splitTo((splitPos==opts.closeableto)?_splitPos:opts.closeableto,true);return false;});
  71. }
  72. //reset size to default.
  73. var perc=(((C.position()[opts.moving]-splitter.offset()[opts.moving])/splitter[opts.sizing]())*100).toFixed(1);
  74. splitTo(perc,false,true);
  75. // resize event handlers;
  76. splitter.bind("resize",function(e, size){if(e.target!=this)return;splitTo(splitPos,false,true);});
  77. $(window).bind("resize",function(){splitTo(splitPos,false,true);});
  78. //C.onmousedown=startDrag
  79. function startDrag(e) {
  80. if(e.target != this)return;
  81. _ghost = _ghost || C.clone(false).insertAfter(A);
  82. splitter._initPos=C.position();
  83. splitter._initPos[opts.moving]-=C[opts.sizing]();
  84. _ghost.addClass(opts.ghostClass).css('position','absolute').css('z-index','250').css("-webkit-user-select", "none").width(C.width()).height(C.height()).css(opts.moving,splitter._initPos[opts.moving]);
  85. mychilds.css("-webkit-user-select", "none"); // Safari selects A/B text on a move
  86. A._posSplit = e[opts.eventPos];
  87. $(document).bind("mousemove", performDrag).bind("mouseup", endDrag);
  88. }
  89. //document.onmousemove=performDrag
  90. function performDrag(e) {
  91. if (!_ghost||!A) return;
  92. var incr = e[opts.eventPos]-A._posSplit;
  93. _ghost.css(opts.moving, splitter._initPos[opts.moving]+incr);
  94. }
  95. //C.onmouseup=endDrag
  96. function endDrag(e){
  97. var p=_ghost.position();
  98. _ghost.remove(); _ghost = null;
  99. mychilds.css("-webkit-user-select", "text");// let Safari select text again
  100. $(document).unbind("mousemove", performDrag).unbind("mouseup", endDrag);
  101. var perc=(((p[opts.moving]-splitter.offset()[opts.moving])/splitter[opts.sizing]())*100).toFixed(1);
  102. splitTo(perc,(splitter._initPos[opts.moving]>p[opts.moving]),false);
  103. splitter._initPos=0;
  104. }
  105. //Perform actual splitting and animate it;
  106. function splitTo(perc,reversedorder,fast) {
  107. if(_ismovingNow||perc==undefined)return;//generally MSIE problem
  108. _ismovingNow=true;
  109. if(splitPos&&splitPos>10&&splitPos<90)//do not save accidental events
  110. _splitPos=splitPos;
  111. splitPos=perc;
  112. var barsize=C[opts.sizing]()+(2*parseInt(C.css('border-'+opts.moving+'-width')));//+ border. cehap&dirty
  113. var splitsize=splitter[opts.sizing]();
  114. if(opts.closeableto!=perc){
  115. var percpx=Math.max(parseInt((splitsize/100)*perc),opts.minAsize);
  116. if(opts.maxAsize)percpx=Math.min(percpx,opts.maxAsize);
  117. }else{
  118. var percpx=parseInt((splitsize/100)*perc,0);
  119. }
  120. if(opts.maxBsize){
  121. if((splitsize-percpx)>opts.maxBsize)
  122. percpx=splitsize-opts.maxBsize;
  123. }
  124. if(opts.minBsize){
  125. if((splitsize-percpx)<opts.minBsize)
  126. percpx=splitsize-opts.minBsize;
  127. }
  128. var sizeA=Math.max(0,(percpx-barsize));
  129. var sizeB=Math.max(0,(splitsize-percpx));
  130. splitsize=(splitsize-barsize);
  131. //A.attr('title','- '+sizeA); B.attr('title','- '+sizeB);
  132. if(fast){
  133. A.show().css(opts.sizing,sizeA+'px');
  134. B.show().css(opts.sizing,sizeB+'px');
  135. Bt.show();
  136. if (!$.browser.msie ){
  137. mychilds.trigger("resize");if(slave)slave.trigger("resize");
  138. }
  139. _ismovingNow=false;
  140. return true;
  141. }
  142. if(reversedorder){//reduces flickering if total percentage becomes more than 100 (possible while animating)
  143. var anob={};
  144. anob[opts.sizing]=sizeA+'px';
  145. A.show().animate(anob,opts.animSpeed,function(){Bt.fadeIn('fast');if($(this)[opts.sizing]()<2){this.style.display='none';B.stop(true,true);B[opts.sizing](splitsize+'px');}});
  146. var anob2={};
  147. anob2[opts.sizing]=sizeB+'px';
  148. B.show().animate(anob2,opts.animSpeed,function(){Bt.fadeIn('fast');if($(this)[opts.sizing]()<2){this.style.display='none';A.stop(true,true);A[opts.sizing](splitsize+'px')}});
  149. }else{
  150. var anob={};
  151. anob[opts.sizing]=sizeB+'px';
  152. B.show().animate(anob,opts.animSpeed,function(){Bt.fadeIn('fast');if($(this)[opts.sizing]()<2){this.style.display='none';A.stop(true,true);A[opts.sizing](splitsize+'px')}});
  153. var anob={};
  154. anob[opts.sizing]=sizeA+'px';
  155. A.show().animate(anob,opts.animSpeed,function(){Bt.fadeIn('fast');if($(this)[opts.sizing]()<2){this.style.display='none';B.stop(true,true);B[opts.sizing](splitsize+'px');}});
  156. }
  157. //trigger resize evt
  158. splitter.queue(function(){
  159. setTimeout(function(){
  160. splitter.dequeue();
  161. _ismovingNow=false;
  162. mychilds.trigger("resize");if(slave)slave.trigger("resize");
  163. }, opts.animSpeed+5);
  164. });
  165. }//end splitTo()
  166. });//end each
  167. };//end splitter
  168. })(jQuery);