2011-11-05 16:46:53 +00:00
|
|
|
'use strict';
|
2012-05-21 10:38:18 +00:00
|
|
|
|
2011-05-16 08:24:46 +00:00
|
|
|
/*@
|
2012-05-31 10:32:54 +00:00
|
|
|
Ox.SplitPanel <f> SpliPanel Object
|
2011-05-16 08:24:46 +00:00
|
|
|
options <o> Options object
|
2011-09-04 21:15:16 +00:00
|
|
|
elements <[o]|[]> Array of two or three element objects
|
|
|
|
collapsible <b|false> If true, can be collapsed (if outer element)
|
|
|
|
collapsed <b|false> If true, is collapsed (if collapsible)
|
2014-08-21 10:14:30 +00:00
|
|
|
defaultSize <n|s|"auto"> Default size in px (restorable via reset)
|
2011-09-04 21:15:16 +00:00
|
|
|
element <o> Any Ox.Element
|
|
|
|
If any element is collapsible or resizable, all elements must
|
|
|
|
have an id.
|
2014-08-21 10:14:30 +00:00
|
|
|
resettable <b|false> If true, can be resetted (if outer element)
|
|
|
|
Note that reset fires on doubleclick, and if the element is also
|
|
|
|
collapsible, toggle now fires on singleclick, no longer on click.
|
|
|
|
Singleclick happens 250 ms later.
|
2011-09-04 21:15:16 +00:00
|
|
|
resizable <b|false> If true, can be resized (if outer element)
|
|
|
|
resize <[n]|[]> Min size, optional snappy points, and max size
|
|
|
|
size <n|s|"auto"> Size in px (one element must be "auto")
|
|
|
|
tooltip <b|s|false> If true, show tooltip, if string, append it
|
|
|
|
orientation <s|"horizontal"> orientation ("horizontal" or "vertical")
|
2012-07-04 11:29:18 +00:00
|
|
|
self <o> Shared private variable
|
|
|
|
([options[, self]]) -> <o:Ox.Element> SpliPanel Object
|
|
|
|
resize <!> resize
|
|
|
|
Fires on resize, on both elements being resized
|
2014-08-21 10:14:30 +00:00
|
|
|
resizeend <!> resizeend
|
|
|
|
Fires on resize, on both elements being resized
|
|
|
|
resizepause <!> resizepause
|
|
|
|
Fires on resize, on both elements being resized
|
2012-07-04 11:29:18 +00:00
|
|
|
toggle <!> toggle
|
|
|
|
Fires on collapse or expand, on the element being toggled
|
2011-05-16 08:24:46 +00:00
|
|
|
@*/
|
|
|
|
|
2011-04-22 22:03:10 +00:00
|
|
|
Ox.SplitPanel = function(options, self) {
|
|
|
|
|
2011-06-19 17:48:32 +00:00
|
|
|
self = self || {};
|
2013-12-06 16:26:35 +00:00
|
|
|
var that = Ox.Element({}, self)
|
2011-04-22 22:03:10 +00:00
|
|
|
.defaults({
|
|
|
|
elements: [],
|
|
|
|
orientation: 'horizontal'
|
|
|
|
})
|
|
|
|
.options(options || {})
|
|
|
|
.addClass('OxSplitPanel');
|
|
|
|
|
2014-08-21 10:14:30 +00:00
|
|
|
self.defaultSize = self.options.elements.map(function(element) {
|
|
|
|
return !Ox.isUndefined(element.defaultSize)
|
|
|
|
? element.defaultSize : element.size;
|
2011-04-22 22:03:10 +00:00
|
|
|
});
|
2014-08-21 10:14:30 +00:00
|
|
|
self.dimensions = Ox.UI.DIMENSIONS[self.options.orientation];
|
|
|
|
self.edges = Ox.UI.EDGES[self.options.orientation];
|
|
|
|
self.initialized = false;
|
|
|
|
self.length = self.options.elements.length;
|
2011-04-22 22:03:10 +00:00
|
|
|
|
2014-08-21 10:14:30 +00:00
|
|
|
self.$elements = [];
|
|
|
|
self.$resizebars = [];
|
|
|
|
self.options.elements.forEach(function(element, index) {
|
|
|
|
var elementIndices = index == 0 ? [0, 1] : index == 1 ? [1, 0] : [2, 1],
|
|
|
|
resizebarIndex = self.$resizebars.length;
|
|
|
|
self.options.elements[index] = Ox.extend({
|
2011-04-22 22:03:10 +00:00
|
|
|
collapsible: false,
|
|
|
|
collapsed: false,
|
2014-08-21 10:14:30 +00:00
|
|
|
defaultSize: 'auto',
|
|
|
|
resettable: false,
|
2011-04-22 22:03:10 +00:00
|
|
|
resizable: false,
|
|
|
|
resize: [],
|
2014-08-21 10:14:30 +00:00
|
|
|
size: 'auto',
|
|
|
|
tooltip: false
|
2011-11-01 19:56:11 +00:00
|
|
|
}, element);
|
2013-12-06 16:26:35 +00:00
|
|
|
// top and bottom (horizontal) or left and right (vertical)
|
|
|
|
self.edges.slice(2).forEach(function(edge) {
|
2014-09-02 11:23:06 +00:00
|
|
|
element.element.css(
|
|
|
|
edge, (parseInt(element.element.css(edge)) || 0) + 'px'
|
|
|
|
);
|
2013-12-06 16:26:35 +00:00
|
|
|
});
|
2014-08-21 10:14:30 +00:00
|
|
|
if (element.collapsed) {
|
|
|
|
// left/right (horizontal) or top/bottom (vertical)
|
|
|
|
that.css(self.edges[index == 0 ? 0 : 1], -element.size + 'px');
|
|
|
|
}
|
|
|
|
self.$elements[index] = element.element.appendTo(that);
|
2011-09-04 21:15:16 +00:00
|
|
|
if (element.collapsible || element.resizable) {
|
2014-08-21 10:14:30 +00:00
|
|
|
self.$resizebars[resizebarIndex] = Ox.Resizebar({
|
2011-09-04 21:15:16 +00:00
|
|
|
collapsed: element.collapsed,
|
|
|
|
collapsible: element.collapsible,
|
2014-08-21 10:14:30 +00:00
|
|
|
edge: self.edges[index == 0 ? 0 : 1],
|
2013-12-06 16:26:35 +00:00
|
|
|
orientation: self.options.orientation == 'horizontal'
|
|
|
|
? 'vertical' : 'horizontal',
|
2014-08-21 10:14:30 +00:00
|
|
|
resettable: element.resettable,
|
2011-09-04 21:15:16 +00:00
|
|
|
resizable: element.resizable,
|
|
|
|
resize: element.resize,
|
|
|
|
size: element.size,
|
2014-08-21 10:14:30 +00:00
|
|
|
tooltip: element.tooltip === true ? '' : element.tooltip
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
reset: function() {
|
|
|
|
that.resetElement(index);
|
|
|
|
},
|
|
|
|
resize: function(data) {
|
|
|
|
onResize(elementIndices, data.size);
|
|
|
|
triggerEvents(elementIndices, 'resize', data);
|
|
|
|
},
|
|
|
|
resizepause: function(data) {
|
|
|
|
triggerEvents(elementIndices, 'resizepause', data);
|
|
|
|
},
|
|
|
|
resizeend: function(data) {
|
|
|
|
triggerEvents(elementIndices, 'resizeend', data);
|
|
|
|
},
|
|
|
|
toggle: function(data) {
|
|
|
|
that.toggleElement(index);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
[index == 0 ? 'insertAfter' : 'insertBefore'](self.$elements[index]);
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2014-08-21 10:14:30 +00:00
|
|
|
setSizes();
|
2011-04-22 22:03:10 +00:00
|
|
|
|
2013-12-06 16:26:35 +00:00
|
|
|
function getSize(index) {
|
|
|
|
var element = self.options.elements[index];
|
2011-04-22 22:03:10 +00:00
|
|
|
return element.size + (element.collapsible || element.resizable);
|
|
|
|
}
|
|
|
|
|
2013-12-06 16:26:35 +00:00
|
|
|
function getVisibleSize(index) {
|
|
|
|
var element = self.options.elements[index];
|
2014-01-17 11:17:27 +00:00
|
|
|
return getSize(index) * !element.collapsed;
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2014-08-21 10:14:30 +00:00
|
|
|
function onResize(elementIndices, size) {
|
|
|
|
var dimension = self.dimensions[0],
|
|
|
|
edge = self.edges[elementIndices[0] == 0 ? 0 : 1];
|
|
|
|
self.options.elements[elementIndices[0]].size = size;
|
|
|
|
elementIndices.forEach(function(elementIndex, index) {
|
|
|
|
self.$elements[elementIndex].css(
|
|
|
|
index == 0 ? dimension : edge,
|
2014-09-20 10:31:05 +00:00
|
|
|
(index == 0 ? size : size + 1) + 'px'
|
2014-08-21 10:14:30 +00:00
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function setSizes(animate) {
|
2012-05-27 19:32:39 +00:00
|
|
|
// will animate if animate is truthy and call animate if it's a function
|
2014-08-21 10:14:30 +00:00
|
|
|
self.options.elements.forEach(function(element, index) {
|
|
|
|
var $resizebar,
|
|
|
|
css = {},
|
2013-12-06 16:26:35 +00:00
|
|
|
edges = self.edges.slice(0, 2).map(function(edge) {
|
|
|
|
// left/right (horizontal) or top/bottom (vertical)
|
2014-08-21 10:14:30 +00:00
|
|
|
var value = parseInt(self.$elements[index].css(edge));
|
|
|
|
return !self.initialized && value || 0;
|
2013-12-06 16:26:35 +00:00
|
|
|
});
|
2011-09-18 21:17:39 +00:00
|
|
|
if (element.size != 'auto') {
|
2013-12-06 16:26:35 +00:00
|
|
|
// width (horizontal) or height (vertical)
|
2011-09-18 21:17:39 +00:00
|
|
|
css[self.dimensions[0]] = element.size + 'px';
|
|
|
|
}
|
2014-08-21 10:14:30 +00:00
|
|
|
if (index == 0) {
|
2013-12-06 16:26:35 +00:00
|
|
|
// left (horizontal) or top (vertical)
|
2011-09-18 21:17:39 +00:00
|
|
|
css[self.edges[0]] = edges[0] + 'px';
|
2013-12-06 16:26:35 +00:00
|
|
|
// right (horizontal) or bottom (vertical)
|
2011-09-18 21:17:39 +00:00
|
|
|
if (element.size == 'auto') {
|
2014-08-21 10:14:30 +00:00
|
|
|
css[self.edges[1]] = getSize(1) + (
|
2013-12-06 16:26:35 +00:00
|
|
|
self.length == 3 ? getVisibleSize(2) : 0
|
2011-09-18 21:17:39 +00:00
|
|
|
) + 'px';
|
|
|
|
}
|
2014-08-21 10:14:30 +00:00
|
|
|
} else if (index == 1) {
|
2013-12-06 16:26:35 +00:00
|
|
|
// left (horizontal) or top (vertical)
|
2011-09-18 21:17:39 +00:00
|
|
|
if (self.options.elements[0].size != 'auto') {
|
2014-08-21 10:14:30 +00:00
|
|
|
css[self.edges[0]] = edges[0] + getSize(0) + 'px';
|
2011-09-18 21:17:39 +00:00
|
|
|
} else {
|
|
|
|
css[self.edges[0]] = 'auto'; // fixme: why is this needed?
|
|
|
|
}
|
2013-12-06 16:26:35 +00:00
|
|
|
// right (horizontal) or bottom (vertical)
|
2014-08-21 10:14:30 +00:00
|
|
|
css[self.edges[1]] = (self.length == 3 ? getSize(2) : 0) + 'px';
|
2011-09-18 21:17:39 +00:00
|
|
|
} else {
|
2013-12-06 16:26:35 +00:00
|
|
|
// left (horizontal) or top (vertical)
|
2011-09-18 21:17:39 +00:00
|
|
|
if (element.size == 'auto') {
|
2014-01-17 11:17:27 +00:00
|
|
|
css[self.edges[0]] = getVisibleSize(0) + getSize(1) + 'px';
|
2011-09-18 21:17:39 +00:00
|
|
|
} else {
|
|
|
|
css[self.edges[0]] = 'auto'; // fixme: why is this needed?
|
|
|
|
}
|
2013-12-06 16:26:35 +00:00
|
|
|
// right (horizontal) or bottom (vertical)
|
2011-09-18 21:17:39 +00:00
|
|
|
css[self.edges[1]] = edges[1] + 'px';
|
|
|
|
}
|
|
|
|
if (animate) {
|
2014-08-21 10:14:30 +00:00
|
|
|
self.$elements[index].animate(css, 250, function() {
|
|
|
|
index == 0 && Ox.isFunction(animate) && animate();
|
2011-09-18 21:17:39 +00:00
|
|
|
});
|
2011-04-22 22:03:10 +00:00
|
|
|
} else {
|
2014-08-21 10:14:30 +00:00
|
|
|
self.$elements[index].css(css);
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
2011-09-04 21:15:16 +00:00
|
|
|
if (element.collapsible || element.resizable) {
|
2014-08-21 10:14:30 +00:00
|
|
|
$resizebar = self.$resizebars[
|
|
|
|
index < 2 ? 0 : self.$resizebars.length - 1
|
|
|
|
];
|
2013-12-06 16:26:35 +00:00
|
|
|
// left or right (horizontal) or top or bottom (vertical)
|
2014-08-21 10:14:30 +00:00
|
|
|
css = Ox.extend(
|
|
|
|
{}, self.edges[index == 0 ? 0 : 1], element.size + 'px'
|
|
|
|
);
|
2011-09-18 21:17:39 +00:00
|
|
|
if (animate) {
|
2014-08-21 10:14:30 +00:00
|
|
|
$resizebar.animate(css, 250);
|
2011-09-18 21:17:39 +00:00
|
|
|
} else {
|
2014-08-21 10:14:30 +00:00
|
|
|
$resizebar.css(css);
|
2011-09-18 21:17:39 +00:00
|
|
|
}
|
2014-08-21 10:14:30 +00:00
|
|
|
$resizebar.options({size: element.size});
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
});
|
2014-08-21 10:14:30 +00:00
|
|
|
self.initialized = true;
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2014-08-21 10:14:30 +00:00
|
|
|
function triggerEvents(elementIndices, event, data) {
|
|
|
|
elementIndices.forEach(function(elementIndex, index) {
|
|
|
|
var $element = self.$elements[elementIndex],
|
|
|
|
size = index == 0 ? data.size : $element[self.dimensions[0]]();
|
|
|
|
$element.triggerEvent(event, {size: size});
|
|
|
|
});
|
|
|
|
}
|
2012-04-08 18:22:27 +00:00
|
|
|
|
2011-09-05 12:42:37 +00:00
|
|
|
/*@
|
2014-08-21 10:14:30 +00:00
|
|
|
isCollapsed <f> Tests if an outer element is collapsed
|
|
|
|
(index) -> <b> True if collapsed
|
|
|
|
index <i> The element's index
|
2011-09-05 12:42:37 +00:00
|
|
|
@*/
|
2014-08-21 10:14:30 +00:00
|
|
|
that.isCollapsed = function(index) {
|
2013-12-06 16:26:35 +00:00
|
|
|
return self.options.elements[index].collapsed;
|
2011-04-22 22:03:10 +00:00
|
|
|
};
|
|
|
|
|
2011-09-05 12:42:37 +00:00
|
|
|
/*@
|
2014-08-21 10:14:30 +00:00
|
|
|
replaceElement <f> Replaces an element
|
|
|
|
(index, element) -> <f> replace element
|
|
|
|
index <n> The element's index
|
2013-12-06 16:26:35 +00:00
|
|
|
element <o> New element
|
2011-09-05 12:42:37 +00:00
|
|
|
@*/
|
2014-08-21 10:14:30 +00:00
|
|
|
that.replaceElement = function(index, element) {
|
2013-12-06 16:26:35 +00:00
|
|
|
// top and bottom (horizontal) or left and right (vertical)
|
|
|
|
self.edges.slice(2).forEach(function(edge) {
|
2014-01-17 11:23:22 +00:00
|
|
|
element.css(edge, (parseInt(element.css(edge)) || 0) + 'px');
|
2013-12-06 16:26:35 +00:00
|
|
|
});
|
2014-08-21 10:14:30 +00:00
|
|
|
self.$elements[index] = element;
|
2013-12-06 16:26:35 +00:00
|
|
|
self.options.elements[index].element.replaceWith(
|
|
|
|
self.options.elements[index].element = element
|
2011-11-01 19:56:11 +00:00
|
|
|
);
|
2011-04-22 22:03:10 +00:00
|
|
|
setSizes();
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
2011-09-05 12:42:37 +00:00
|
|
|
/*@
|
2014-08-21 10:14:30 +00:00
|
|
|
resetElement <f> Resets an outer element to its initial size
|
2011-09-05 12:42:37 +00:00
|
|
|
@*/
|
2014-08-21 10:14:30 +00:00
|
|
|
that.resetElement = function(index) {
|
|
|
|
var element = self.options.elements[index];
|
2013-12-06 16:26:35 +00:00
|
|
|
element.size = self.defaultSize[index];
|
2014-08-21 10:14:30 +00:00
|
|
|
setSizes(function() {
|
2012-08-29 15:41:40 +00:00
|
|
|
element.element.triggerEvent('resize', {
|
2012-04-23 09:37:49 +00:00
|
|
|
size: element.size
|
|
|
|
});
|
2013-12-06 16:26:35 +00:00
|
|
|
element = self.options.elements[index == 0 ? 1 : index - 1];
|
2012-04-23 09:37:49 +00:00
|
|
|
element.element.triggerEvent('resize', {
|
2012-08-29 15:41:40 +00:00
|
|
|
size: element.element[self.dimensions[0]]()
|
|
|
|
});
|
|
|
|
});
|
2014-08-21 10:14:30 +00:00
|
|
|
return that;
|
2012-04-23 09:37:49 +00:00
|
|
|
};
|
|
|
|
|
2011-09-05 12:42:37 +00:00
|
|
|
/*@
|
2011-09-18 21:17:39 +00:00
|
|
|
size <f> Get or set size of an element
|
2014-08-21 10:14:30 +00:00
|
|
|
(index) -> <i> Returns size
|
|
|
|
(index, size) -> <o> Sets size, returns SplitPanel
|
|
|
|
(index, size, callback) -> <o> Sets size with animation, returns SplitPanel
|
|
|
|
index <i> The element's index
|
2011-09-18 21:17:39 +00:00
|
|
|
size <i> New size, in px
|
|
|
|
callback <b|f> Callback function (passing true animates w/o callback)
|
2011-09-05 12:42:37 +00:00
|
|
|
@*/
|
2014-08-21 10:14:30 +00:00
|
|
|
that.resizeElement = that.size = function(index, size, callback) {
|
|
|
|
var element = self.options.elements[index];
|
2012-08-29 15:41:40 +00:00
|
|
|
if (arguments.length == 1) {
|
2014-08-21 10:14:30 +00:00
|
|
|
return element.element[self.dimensions[0]]()
|
|
|
|
* !that.isCollapsed(index);
|
2012-08-29 15:41:40 +00:00
|
|
|
} else {
|
|
|
|
element.size = size;
|
2014-08-21 10:14:30 +00:00
|
|
|
setSizes(callback);
|
2011-04-22 22:03:10 +00:00
|
|
|
return that;
|
2012-08-29 15:41:40 +00:00
|
|
|
}
|
2011-04-22 22:03:10 +00:00
|
|
|
};
|
2011-09-05 12:42:37 +00:00
|
|
|
|
|
|
|
/*@
|
2014-08-21 10:14:30 +00:00
|
|
|
toggleElement <f> Toggles collapsed state of an outer element
|
|
|
|
(index) -> <o> The SplitPanel
|
|
|
|
index <s|i> The element's index
|
2011-09-05 12:42:37 +00:00
|
|
|
@*/
|
2014-08-21 10:14:30 +00:00
|
|
|
that.toggleElement = function(index) {
|
2013-07-28 23:33:12 +00:00
|
|
|
if (self.toggling) {
|
2014-08-21 10:14:30 +00:00
|
|
|
return that;
|
2013-07-28 23:33:12 +00:00
|
|
|
}
|
2014-08-21 10:14:30 +00:00
|
|
|
var element = self.options.elements[index],
|
|
|
|
value = parseInt(that.css(self.edges[index == 0 ? 0 : 1]))
|
|
|
|
+ element.element[self.dimensions[0]]()
|
|
|
|
* (element.collapsed ? 1 : -1),
|
|
|
|
animate = Ox.extend({}, self.edges[index == 0 ? 0 : 1], value);
|
2013-07-28 23:33:12 +00:00
|
|
|
self.toggling = true;
|
2011-09-18 21:17:39 +00:00
|
|
|
that.animate(animate, 250, function() {
|
2011-04-22 22:03:10 +00:00
|
|
|
element.collapsed = !element.collapsed;
|
|
|
|
element.element.triggerEvent('toggle', {
|
2012-04-23 09:37:49 +00:00
|
|
|
collapsed: element.collapsed
|
2011-04-22 22:03:10 +00:00
|
|
|
});
|
2014-08-21 10:14:30 +00:00
|
|
|
self.$resizebars[index < 2 ? 0 : self.$resizebars.length - 1].options({
|
|
|
|
collapsed: element.collapsed
|
|
|
|
});
|
2013-12-06 16:26:35 +00:00
|
|
|
element = self.options.elements[index == 0 ? 1 : index - 1];
|
2011-09-20 21:50:00 +00:00
|
|
|
element.element.triggerEvent('resize', {
|
2012-08-29 15:41:40 +00:00
|
|
|
size: element.element[self.dimensions[0]]()
|
|
|
|
});
|
2013-07-28 23:33:12 +00:00
|
|
|
self.toggling = false;
|
2011-04-22 22:03:10 +00:00
|
|
|
});
|
2014-08-21 10:14:30 +00:00
|
|
|
return that;
|
2011-06-19 17:48:32 +00:00
|
|
|
};
|
2011-04-22 22:03:10 +00:00
|
|
|
|
|
|
|
return that;
|
|
|
|
|
2012-05-21 10:38:18 +00:00
|
|
|
};
|