mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
181 lines
7.7 KiB
JavaScript
181 lines
7.7 KiB
JavaScript
/*
|
|
* 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)]);
|
|
});
|
|
};
|