From 91629f1cdab2387ad9b219cb2ebb7eec4b29f808 Mon Sep 17 00:00:00 2001
From: Hilton Janfield
Date: Sun, 13 Sep 2015 03:30:21 -0700
Subject: [PATCH] Implement [left/right][Min/Max]Size options, [min/max]Size
aliases. Refactor internals.
---
CHANGELOG.md | 10 ++-
js/jquery.enhsplitter.js | 159 ++++++++++++++++++---------------------
test.html | 29 +++----
3 files changed, 99 insertions(+), 99 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6cda2f4..33ec583 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,14 @@
# jQuery Enhanced Splitter Change Log
-## Branch v1.2.0
+## Branch v1.2.1
+
+- Considerable internal refactoring.
+- Add options 'leftMinSize', 'leftMaxSize', 'rightMinSize', 'rightMaxSize'.
+- Add aliases 'topMinSize', 'topMaxSize', 'bottomMinSize', 'bottomMaxSize', which refer to the new options above respectively.
+- Add aliases 'minSize' and 'maxSize' to refer to each similarly named pair of options above.
+- Remove options 'lowerLimit' and 'upperLimit', and alias 'limit'. Use 'leftMinSize', 'rightMinSize', and 'minSize' instead.
+
+## Release v1.2.0
A few bug fixes and minor enhancements, with small breaking changes signifying the minor version increment.
- Updated composer.json to specify valid jQuery versions (1.8+ / 2.0+).
diff --git a/js/jquery.enhsplitter.js b/js/jquery.enhsplitter.js
index c27a591..52c9d10 100644
--- a/js/jquery.enhsplitter.js
+++ b/js/jquery.enhsplitter.js
@@ -22,6 +22,8 @@
var splitterCount = 0;
var splitters = [];
var currentSplitter = null; // Reference to current splitter during events.
+ var dragStartPosition = null;
+ var disableClick = false;
$.fn.enhsplitter = function (options) {
var data = this.data('splitter');
@@ -62,16 +64,31 @@
this.css('height', settings.height);
}
- // Verify the limits are within allowed constraints (size of panel)
- // With a little obfuscation to reduce 36 lines to 3
- settings.limit = (settings.limit < 0 ? 0 : (settings.vertical ? (settings.limit > (this.width() / 2) ? this.width() / 2 : settings.limit) : (settings.limit > (this.height() / 2) ? this.height() / 2 : settings.limit)));
- // Once settings.limit has been range checked, use it as a default for lowerLimit and upperLimit.
- settings = $.extend({
- lowerLimit: settings.limit,
- upperLimit: settings.limit
- }, settings);
- settings.lowerLimit = (settings.lowerLimit < 0 ? 0 : (settings.vertical ? (settings.lowerLimit > (this.width()) ? this.width() : settings.lowerLimit) : (settings.lowerLimit > (this.height()) ? this.height() : settings.lowerLimit)));
- settings.upperLimit = (settings.upperLimit < 0 ? 0 : (settings.vertical ? (settings.upperLimit > (this.width()) ? this.width() : settings.upperLimit) : (settings.upperLimit > (this.height()) ? this.height() : settings.upperLimit)));
+ var containerSize = settings.vertical ? this.width() : this.height();
+
+ if (settings.minSize) { settings.leftMinSize = settings.rightMinSize = settings.minSize; }
+ if (settings.maxSize) { settings.leftMaxSize = settings.rightMaxSize = settings.maxSize; }
+
+ // If left/right not defined, check for top/bottom and use them instead. (if all defined for some reason, left/right get precedence)
+ settings.leftMinSize = ((settings.leftMinSize === null) && settings.topMinSize) ? settings.topMinSize : settings.leftMinSize;
+ settings.leftMaxSize = ((settings.leftMaxSize === null) && settings.topMaxSize) ? settings.topMaxSize : settings.leftMaxSize;
+ settings.rightMinSize = ((settings.rightMinSize === null) && settings.bottomMinSize) ? settings.bottomMinSize : settings.rightMinSize;
+ settings.rightMaxSize = ((settings.rightMaxSize === null) && settings.bottomMaxSize) ? settings.bottomMaxSize : settings.rightMaxSize;
+
+ // Verify ranges.
+ settings.leftMinSize = (settings.leftMinSize < 0 ? 0 : (settings.leftMinSize > containerSize ? containerSize : settings.leftMinSize));
+ settings.leftMaxSize = (settings.leftMaxSize < 0 ? 0 : (settings.leftMaxSize > containerSize ? containerSize : settings.leftMaxSize));
+ settings.rightMinSize = (settings.rightMinSize < 0 ? 0 : (settings.rightMinSize > containerSize ? containerSize : settings.rightMinSize));
+ settings.rightMaxSize = (settings.rightMaxSize < 0 ? 0 : (settings.rightMaxSize > containerSize ? containerSize : settings.rightMaxSize));
+
+ // Verify minimum sizes.
+ var totalSize = settings.leftMinSize + settings.rightMinSize;
+ if (totalSize > containerSize) {
+ // User has set the left and right minimums too high. Proportionally reduce them.
+ settings.leftMinSize = containerSize * (settings.leftMinSize / totalSize);
+ settings.rightMinSize = containerSize * (settings.rightMinSize / totalSize);
+ }
+
settings.collapseNormal = !(settings.collapse == 'right' || settings.collapse == 'down');
settings.collapsable = !(settings.collapse == 'none');
@@ -99,54 +116,38 @@
self = $.extend(this, {
currentPosition: 0,
+ containerSize: containerSize,
splitterSize: settings.invisible ? 0 : (settings.vertical ? splitter.outerWidth() : splitter.outerHeight()),
splitterSizeHalf: settings.invisible ? 0 : (settings.vertical ? splitter.outerWidth() / 2 : splitter.outerHeight() / 2),
- containerWidth: this.width(),
- containerHeight: this.height(),
refresh: function () {
- var newWidth = this.width();
- var newHeight = this.height();
- if (self.containerWidth != newWidth || self.containerHeight != newHeight) {
- self.containerWidth = this.width();
- self.containerHeight = this.height();
+ var newSize = self.settings.vertical ? this.width() : this.height();
+ if (self.containerSize != newSize) {
+ self.containerSize = newSize;
self.setPosition(self.currentPosition);
}
},
- setPosition: (function () {
- if (settings.vertical) {
- return function (n) {
- if (n <= settings.lowerLimit) {
- n = settings.lowerLimit + 1;
- } else if (n >= self.containerWidth - settings.upperLimit - self.splitterSizeHalf) {
- n = self.containerWidth - settings.upperLimit - self.splitterSizeHalf;
- }
- self.currentPosition = n;
-
- var panelOneWidth = panelOne.outerWidth(self.currentPosition - self.splitterSizeHalf).outerWidth();
- panelTwo.outerWidth(self.containerWidth - panelOneWidth - self.splitterSize);
- splitter.css('left', panelOneWidth);
+ setPosition: function (newPos) {
+ if (newPos <= settings.leftMinSize) {
+ newPos = settings.leftMinSize;
+ } else if (newPos >= self.containerSize - settings.rightMinSize - self.splitterSize) {
+ newPos = self.containerSize - settings.rightMinSize - self.splitterSize;
+ }
+ self.currentPosition = newPos;
- return self;
- };
+ if (self.settings.vertical) {
+ panelOne.outerWidth(newPos);
+ panelTwo.outerWidth(self.containerSize - newPos - self.splitterSize);
+ splitter.css('left', self.settings.invisible ? newPos - self.splitterSizeHalf : newPos);
} else {
- return function (n) {
- if (n <= settings.lowerLimit) {
- n = settings.lowerLimit + 1;
- } else if (n >= self.containerHeight - settings.upperLimit - self.splitterSizeHalf) {
- n = self.containerHeight - settings.upperLimit - self.splitterSizeHalf;
- }
- self.currentPosition = n;
-
- var panelOneHeight = panelOne.outerHeight(self.currentPosition - self.splitterSizeHalf).outerHeight();
- panelTwo.outerHeight(self.containerHeight - panelOneHeight - self.splitterSize);
- splitter.css('top', panelOneHeight);
-
- return self;
- };
+ panelOne.outerHeight(newPos);
+ panelTwo.outerHeight(self.containerSize - newPos - self.splitterSize);
+ splitter.css('top', self.settings.invisible ? newPos - self.splitterSizeHalf : newPos);
}
- })(),
+
+ return self;
+ },
translatePosition: function (position) {
//TODO: Consider replacing this with a more robust function that can accept any CSS value, such as Length.js at https://github.com/heygrady/Units
@@ -158,11 +159,7 @@
if (match) {
if (match[2] && match[2] == '%') {
var splitter = currentSplitter || self;
- if (splitter.settings.vertical) {
- return (splitter.containerWidth * +match[1]) / 100;
- } else {
- return (splitter.containerHeight * +match[1]) / 100;
- }
+ return (splitter.containerSize * +match[1]) / 100;
}
return +match[1]; // assume pixels for ANY suffix except '%', or lack thereof.
} else {
@@ -211,10 +208,10 @@
.on('click.splitter', '.splitter_handle', function (e) {
// Prevent clicks if the user started dragging too much.
// Some (all?) browsers fire the click event even after the bar has been dragged hundreds of pixels.
- currentSplitter = $(this).closest('.splitter_container').data('splitter');
- if (currentSplitter.disableClick) {
- return currentSplitter.disableClick = false;
+ if (disableClick) {
+ return disableClick = false;
}
+ currentSplitter = $(this).closest('.splitter_container').data('splitter');
if (currentSplitter.settings.collapsable) {
if (currentSplitter.data('savedPosition')) {
@@ -226,13 +223,9 @@
// Save current position and collapse.
currentSplitter.data('savedPosition', currentSplitter.currentPosition);
if (currentSplitter.settings.collapseNormal) {
- currentSplitter.setPosition(currentSplitter.settings.lowerLimit + 1);
+ currentSplitter.setPosition(currentSplitter.settings.leftMinSize);
} else {
- if (currentSplitter.settings.vertical) {
- currentSplitter.setPosition(currentSplitter.containerWidth - currentSplitter.settings.upperLimit);
- } else {
- currentSplitter.setPosition(currentSplitter.containerHeight - currentSplitter.settings.upperLimit);
- }
+ currentSplitter.setPosition(currentSplitter.containerSize - currentSplitter.settings.rightMinSize);
}
}
@@ -247,11 +240,11 @@
.on('mousedown.splitter', '.splitter_handle', function (e) {
e.preventDefault();
- // This mousedown event gets called first because it is on top, but we need the other one to fire
- // first - or duplicate the code, which is bad, m'kay?
- $(this).closest('.splitter_bar').trigger('mousedown');
+ if (currentSplitter == null) {
+ $(this).closest('.splitter_bar').trigger('mousedown');
+ }
- currentSplitter.dragStartPosition = (currentSplitter.settings.vertical) ? e.pageX : e.pageY;
+ dragStartPosition = (currentSplitter.settings.vertical) ? e.pageX : e.pageY;
})
.on('mousedown.splitter touchstart.splitter', '.splitter_container > .splitter_bar', function (e) {
@@ -269,27 +262,20 @@
.on('mouseup.splitter touchend.splitter touchleave.splitter touchcancel.splitter', '.splitter_mask, .splitter_container > .splitter_bar', function (e) {
if (currentSplitter) {
e.preventDefault();
- currentSplitter.dragStartPosition = null;
+ dragStartPosition = null;
// If the slider is dropped near it's collapsed position, set a saved position back to its
// original start position so the collapse handle works at least somewhat properly.
if (!currentSplitter.data('savedPosition')) {
if (currentSplitter.settings.collapseNormal) {
- if (currentSplitter.currentPosition <= (currentSplitter.settings.lowerLimit + 5)) {
+ if (currentSplitter.currentPosition <= (currentSplitter.settings.leftMinSize + 5)) {
currentSplitter.data('savedPosition', self.translatePosition(currentSplitter.settings.position));
- currentSplitter.disableClick = false;
+ disableClick = false;
}
} else {
- if (currentSplitter.settings.vertical) {
- if (currentSplitter.currentPosition >= (currentSplitter.containerWidth - currentSplitter.settings.upperLimit - 5)) {
- currentSplitter.data('savedPosition', self.translatePosition(currentSplitter.settings.position));
- currentSplitter.disableClick = false;
- }
- } else {
- if (currentSplitter.currentPosition >= (currentSplitter.containerHeight - currentSplitter.settings.upperLimit - 5)) {
- currentSplitter.data('savedPosition', self.translatePosition(currentSplitter.settings.position));
- currentSplitter.disableClick = false;
- }
+ if (currentSplitter.currentPosition >= (currentSplitter.containerSize - currentSplitter.settings.rightMinSize - 5)) {
+ currentSplitter.data('savedPosition', self.translatePosition(currentSplitter.settings.position));
+ disableClick = false;
}
}
}
@@ -310,10 +296,10 @@
}
// If the user started the drag with a mousedown on the handle, give it a 5-pixel delay.
- if (currentSplitter.dragStartPosition !== null) {
- if (position > (currentSplitter.dragStartPosition + 5) || position < (currentSplitter.dragStartPosition - 5)) {
- currentSplitter.dragStartPosition = null;
- currentSplitter.disableClick = true;
+ if (dragStartPosition !== null) {
+ if (position > (dragStartPosition + 5) || position < (dragStartPosition - 5)) {
+ dragStartPosition = null;
+ disableClick = true;
} else {
e.preventDefault();
return false;
@@ -321,9 +307,9 @@
}
if (currentSplitter.settings.vertical) {
- currentSplitter.setPosition(position - currentSplitter.offset().left - currentSplitter.splitterSizeHalf);
+ currentSplitter.setPosition(position - currentSplitter.offset().left - currentSplitter.splitterSize + 1);
} else {
- currentSplitter.setPosition(position - currentSplitter.offset().top - currentSplitter.splitterSizeHalf);
+ currentSplitter.setPosition(position - currentSplitter.offset().top - currentSplitter.splitterSize + 1);
}
e.preventDefault();
currentSplitter.settings.onDrag(e, currentSplitter);
@@ -344,8 +330,11 @@
$.fn.enhsplitter.defaults = {
vertical: true,
- limit: 100,
position: '50%',
+ leftMinSize: 100,
+ leftMaxSize: null,
+ rightMinSize: 100,
+ rightMaxSize: null,
invisible: false,
handle: 'default',
fixed: false,
diff --git a/test.html b/test.html
index 7233880..23f654a 100644
--- a/test.html
+++ b/test.html
@@ -68,6 +68,10 @@
br {
line-height: 2.5em;
}
+
+ .splitter_bar {
+ background: transparent;
+ }
@@ -81,6 +85,14 @@ jquery.enhsplitter Features Tests