mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-19 07:12:26 +02:00
Moved under "trunk" to be able to track releases under "tags"
SVN:code[55]
This commit is contained in:
180
trunk/js/splitter.js
Normal file
180
trunk/js/splitter.js
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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)]);
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user