123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- /*
- * jquery.splitter.js - two-pane splitter window plugin
- *
- * version 1.01 (01/05/2007)
- *
- * Dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- */
- /**
- * The splitter() plugin implements a two-pane resizable splitter window.
- * The selected elements in the jQuery object are converted to a splitter;
- * each element should have two child elements which are used for the panes
- * of the splitter. The plugin adds a third child element for the splitbar.
- *
- * For more details see: http://methvin.com/jquery/splitter/
- *
- *
- * @example $('#MySplitter').splitter();
- * @desc Create a vertical splitter with default settings
- *
- * @example $('#MySplitter').splitter({direction: 'h', accessKey: 'M'});
- * @desc Create a horizontal splitter resizable via Alt+Shift+M
- *
- * @name splitter
- * @type jQuery
- * @param String options Options for the splitter
- * @cat Plugins/Splitter
- * @return jQuery
- * @author Dave Methvin (dave.methvin@gmail.com)
- */
- jQuery.fn.splitter = function(opts){
- opts = jQuery.extend({
- type: 'v', // v=vertical, h=horizontal split
- activeClass: 'active', // class name for active splitter
- pxPerKey: 5, // splitter px moved per keypress
- tabIndex: 0, // tab order indicator
- accessKey: '' // accelerator key for splitter
- // initA initB // initial A/B size (pick ONE)
- // minA maxA minB maxB // min/max pane sizes
- },{
- v: { // Vertical splitters:
- keyGrowA: 39, // left arrow key
- keyShrinkA: 37, // right arrow key
- cursor: "e-resize", // double-arrow horizontal
- splitbarClass: "vsplitbar",
- eventPos: "pageX", set: "left",
- adjust: "width", offsetAdjust: "offsetWidth", adjSide1: "Left", adjSide2: "Right",
- fixed: "height", offsetFixed: "offsetHeight", fixSide1: "Top", fixSide2: "Bottom"
- },
- h: { // Horizontal splitters:
- keyGrowA: 40, // down arrow key
- keyShrinkA: 38, // up arrow key
- cursor: "n-resize", // double-arrow vertical
- splitbarClass: "hsplitbar",
- eventPos: "pageY", set: "top",
- adjust: "height", offsetAdjust: "offsetHeight", adjSide1: "Top", adjSide2: "Bottom",
- fixed: "width", offsetFixed: "offsetWidth", fixSide1: "Left", fixSide2: "Right"
- }
- }[((opts||{}).type||'v').charAt(0).toLowerCase()], opts||{});
- return this.each(function() {
- function startSplit(e) {
- splitbar.addClass(opts.activeClass);
- if ( e.type == "mousedown" ) {
- paneA._posAdjust = paneA[0][opts.offsetAdjust] - e[opts.eventPos];
- jQuery(document)
- .bind("mousemove", doSplitMouse)
- .bind("mouseup", endSplit);
- }
- return true; // required???
- }
- function doSplitKey(e) {
- var key = e.which || e.keyCode;
- var dir = key==opts.keyGrowA? 1 : key==opts.keyShrinkA? -1 : 0;
- if ( dir )
- moveSplitter(paneA[0][opts.offsetAdjust]+dir*opts.pxPerKey);
- return true; // required???
- }
- function doSplitMouse(e) {
- moveSplitter(paneA._posAdjust+e[opts.eventPos]);
- }
- function endSplit(e) {
- splitbar.removeClass(opts.activeClass);
- jQuery(document)
- .unbind("mousemove", doSplitMouse)
- .unbind("mouseup", endSplit);
- }
- function moveSplitter(np) {
- // Constrain new position to fit pane size limits; 16=scrollbar fudge factor
- // TODO: enforce group width in IE6 since it lacks min/max css properties?
- np = Math.max(paneA._min+paneA._padAdjust, group._adjust - (paneB._max||9999), 16,
- Math.min(np, paneA._max||9999, group._adjust - splitbar._adjust -
- Math.max(paneB._min+paneB._padAdjust, 16)));
- // Resize/position the two panes and splitbar
- splitbar.css(opts.set, np+"px");
- paneA.css(opts.adjust, np-paneA._padAdjust+"px");
- paneB.css(opts.set, np+splitbar._adjust+"px")
- .css(opts.adjust, group._adjust-splitbar._adjust-paneB._padAdjust-np+"px");
- // IE fires resize for us; all others pay cash
- if ( !jQuery.browser.msie ) {
- paneA.trigger("resize");
- paneB.trigger("resize");
- }
- }
- function cssCache(jq, n, pf, m1, m2) {
- // IE backCompat mode thinks width/height includes border and padding
- jq[n] = jQuery.boxModel? (parseInt(jq.css(pf+m1))||0) + (parseInt(jq.css(pf+m2))||0) : 0;
- }
- function optCache(jq, pane) {
- // Opera returns -1px for min/max dimensions when they're not there!
- jq._min = Math.max(0, opts["min"+pane] || parseInt(jq.css("min-"+opts.adjust)) || 0);
- jq._max = Math.max(0, opts["max"+pane] || parseInt(jq.css("max-"+opts.adjust)) || 0);
- }
- // Create jQuery object closures for splitter group and both panes
- var group = jQuery(this).css({position: "relative"});
- var divs = jQuery(">div", group).css({
- position: "absolute", // positioned inside splitter container
- margin: "0", // remove any stylesheet margin or ...
- border: "0", // ... border added for non-script situations
- "-moz-user-focus": "ignore" // disable focusability in Firefox
- });
- var paneA = jQuery(divs[0]); // left or top
- var paneB = jQuery(divs[1]); // right or bottom
- // Focuser element, provides keyboard support
- var focuser = jQuery('<a href="javascript:void(0)"></a>')
- .bind("focus", startSplit).bind("keydown", doSplitKey).bind("blur", endSplit)
- .attr({accessKey: opts.accessKey, tabIndex: opts.tabIndex});
- // Splitbar element, displays actual splitter bar
- // The select-related properties prevent unintended text highlighting
- var splitbar = jQuery('<div></div>')
- .insertAfter(paneA).append(focuser)
- .attr({"class": opts.splitbarClass, unselectable: "on"})
- .css({position: "absolute", "-khtml-user-select": "none",
- "-moz-user-select": "none", "user-select": "none"})
- .bind("mousedown", startSplit);
- if ( /^(auto|default)$/.test(splitbar.css("cursor") || "auto") )
- splitbar.css("cursor", opts.cursor);
- // Cache several dimensions for speed--assume these don't change
- splitbar._adjust = splitbar[0][opts.offsetAdjust];
- cssCache(group, "_borderAdjust", "border", opts.adjSide1+"Width", opts.adjSide2+"Width");
- cssCache(group, "_borderFixed", "border", opts.fixSide1+"Width", opts.fixSide2+"Width");
- cssCache(paneA, "_padAdjust", "padding", opts.adjSide1, opts.adjSide2);
- cssCache(paneA, "_padFixed", "padding", opts.fixSide1, opts.fixSide2);
- cssCache(paneB, "_padAdjust", "padding", opts.adjSide1, opts.adjSide2);
- cssCache(paneB, "_padFixed", "padding", opts.fixSide1, opts.fixSide2);
- optCache(paneA, 'A');
- optCache(paneB, 'B');
- // Initial splitbar position as measured from left edge of splitter
- paneA._init = (opts.initA==true? parseInt(jQuery.curCSS(paneA[0],opts.adjust)) : opts.initA) || 0;
- paneB._init = (opts.initB==true? parseInt(jQuery.curCSS(paneB[0],opts.adjust)) : opts.initB) || 0;
- if ( paneB._init )
- paneB._init = group[0][opts.offsetAdjust] - group._borderAdjust - paneB._init - splitbar._adjust;
- // Set up resize event handler and trigger immediately to set initial position
- group.bind("resize", function(e,size){
- // Determine new width/height of splitter container
- group._fixed = group[0][opts.offsetFixed] - group._borderFixed;
- group._adjust = group[0][opts.offsetAdjust] - group._borderAdjust;
- // Bail if splitter isn't visible or content isn't there yet
- if ( group._fixed <= 0 || group._adjust <= 0 ) return;
- // Set the fixed dimension (e.g., height on a vertical splitter)
- paneA.css(opts.fixed, group._fixed-paneA._padFixed+"px");
- paneB.css(opts.fixed, group._fixed-paneB._padFixed+"px");
- splitbar.css(opts.fixed, group._fixed+"px");
- // Re-divvy the adjustable dimension; maintain size of the preferred pane
- moveSplitter(size || (!opts.initB? paneA[0][opts.offsetAdjust] :
- group._adjust-paneB[0][opts.offsetAdjust]-splitbar._adjust));
- }).trigger("resize" , [paneA._init || paneB._init ||
- Math.round((group[0][opts.offsetAdjust] - group._borderAdjust - splitbar._adjust)/2)]);
- });
- };
|