mirror of
https://github.com/chinchang/web-maker.git
synced 2025-10-12 20:15:10 +02:00
move source to src.
This commit is contained in:
361
src/lib/split.js
Normal file
361
src/lib/split.js
Normal file
@@ -0,0 +1,361 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
(function() {
|
||||
|
||||
var global = this
|
||||
, addEventListener = 'addEventListener'
|
||||
, removeEventListener = 'removeEventListener'
|
||||
, getBoundingClientRect = 'getBoundingClientRect'
|
||||
, isIE8 = global.attachEvent && !global[addEventListener]
|
||||
, document = global.document
|
||||
|
||||
, calc = (function () {
|
||||
var el
|
||||
, prefixes = ["", "-webkit-", "-moz-", "-o-"]
|
||||
|
||||
for (var i = 0; i < prefixes.length; i++) {
|
||||
el = document.createElement('div')
|
||||
el.style.cssText = "width:" + prefixes[i] + "calc(9px)"
|
||||
|
||||
if (el.style.length) {
|
||||
return prefixes[i] + "calc"
|
||||
}
|
||||
}
|
||||
})()
|
||||
, elementOrSelector = function (el) {
|
||||
if (typeof el === 'string' || el instanceof String) {
|
||||
return document.querySelector(el)
|
||||
} else {
|
||||
return el
|
||||
}
|
||||
}
|
||||
|
||||
, Split = function (ids, options) {
|
||||
var dimension
|
||||
, i
|
||||
, clientDimension
|
||||
, clientAxis
|
||||
, position
|
||||
, gutterClass
|
||||
, paddingA
|
||||
, paddingB
|
||||
, pairs = []
|
||||
|
||||
// Set defaults
|
||||
|
||||
options = typeof options !== 'undefined' ? options : {}
|
||||
|
||||
if (typeof options.gutterSize === 'undefined') options.gutterSize = 10
|
||||
if (typeof options.minSize === 'undefined') options.minSize = 100
|
||||
if (typeof options.snapOffset === 'undefined') options.snapOffset = 30
|
||||
if (typeof options.direction === 'undefined') options.direction = 'horizontal'
|
||||
|
||||
if (options.direction == 'horizontal') {
|
||||
dimension = 'width'
|
||||
clientDimension = 'clientWidth'
|
||||
clientAxis = 'clientX'
|
||||
position = 'left'
|
||||
gutterClass = 'gutter gutter-horizontal'
|
||||
paddingA = 'paddingLeft'
|
||||
paddingB = 'paddingRight'
|
||||
if (!options.cursor) options.cursor = 'ew-resize'
|
||||
} else if (options.direction == 'vertical') {
|
||||
dimension = 'height'
|
||||
clientDimension = 'clientHeight'
|
||||
clientAxis = 'clientY'
|
||||
position = 'top'
|
||||
gutterClass = 'gutter gutter-vertical'
|
||||
paddingA = 'paddingTop'
|
||||
paddingB = 'paddingBottom'
|
||||
if (!options.cursor) options.cursor = 'ns-resize'
|
||||
}
|
||||
|
||||
// Event listeners for drag events, bound to a pair object.
|
||||
// Calculate the pair's position and size when dragging starts.
|
||||
// Prevent selection on start and re-enable it when done.
|
||||
|
||||
var startDragging = function (e) {
|
||||
var self = this
|
||||
, a = self.a
|
||||
, b = self.b
|
||||
|
||||
if (!self.dragging && options.onDragStart) {
|
||||
options.onDragStart()
|
||||
}
|
||||
|
||||
e.preventDefault()
|
||||
|
||||
self.dragging = true
|
||||
self.move = drag.bind(self)
|
||||
self.stop = stopDragging.bind(self)
|
||||
|
||||
global[addEventListener]('mouseup', self.stop)
|
||||
global[addEventListener]('touchend', self.stop)
|
||||
global[addEventListener]('touchcancel', self.stop)
|
||||
|
||||
self.parent[addEventListener]('mousemove', self.move)
|
||||
self.parent[addEventListener]('touchmove', self.move)
|
||||
|
||||
a[addEventListener]('selectstart', preventSelection)
|
||||
a[addEventListener]('dragstart', preventSelection)
|
||||
b[addEventListener]('selectstart', preventSelection)
|
||||
b[addEventListener]('dragstart', preventSelection)
|
||||
|
||||
a.style.userSelect = 'none'
|
||||
a.style.webkitUserSelect = 'none'
|
||||
a.style.MozUserSelect = 'none'
|
||||
a.style.pointerEvents = 'none'
|
||||
|
||||
b.style.userSelect = 'none'
|
||||
b.style.webkitUserSelect = 'none'
|
||||
b.style.MozUserSelect = 'none'
|
||||
b.style.pointerEvents = 'none'
|
||||
|
||||
self.gutter.style.cursor = options.cursor
|
||||
self.parent.style.cursor = options.cursor
|
||||
|
||||
calculateSizes.call(self)
|
||||
}
|
||||
, stopDragging = function () {
|
||||
var self = this
|
||||
, a = self.a
|
||||
, b = self.b
|
||||
|
||||
if (self.dragging && options.onDragEnd) {
|
||||
options.onDragEnd()
|
||||
}
|
||||
|
||||
self.dragging = false
|
||||
|
||||
global[removeEventListener]('mouseup', self.stop)
|
||||
global[removeEventListener]('touchend', self.stop)
|
||||
global[removeEventListener]('touchcancel', self.stop)
|
||||
|
||||
self.parent[removeEventListener]('mousemove', self.move)
|
||||
self.parent[removeEventListener]('touchmove', self.move)
|
||||
|
||||
delete self.stop
|
||||
delete self.move
|
||||
|
||||
a[removeEventListener]('selectstart', preventSelection)
|
||||
a[removeEventListener]('dragstart', preventSelection)
|
||||
b[removeEventListener]('selectstart', preventSelection)
|
||||
b[removeEventListener]('dragstart', preventSelection)
|
||||
|
||||
a.style.userSelect = ''
|
||||
a.style.webkitUserSelect = ''
|
||||
a.style.MozUserSelect = ''
|
||||
a.style.pointerEvents = ''
|
||||
|
||||
b.style.userSelect = ''
|
||||
b.style.webkitUserSelect = ''
|
||||
b.style.MozUserSelect = ''
|
||||
b.style.pointerEvents = ''
|
||||
|
||||
self.gutter.style.cursor = ''
|
||||
self.parent.style.cursor = ''
|
||||
}
|
||||
, drag = function (e) {
|
||||
var offset
|
||||
|
||||
if (!this.dragging) return
|
||||
|
||||
// Get the relative position of the event from the first side of the
|
||||
// pair.
|
||||
|
||||
if ('touches' in e) {
|
||||
offset = e.touches[0][clientAxis] - this.start
|
||||
} else {
|
||||
offset = e[clientAxis] - this.start
|
||||
}
|
||||
|
||||
// If within snapOffset of min or max, set offset to min or max
|
||||
|
||||
if (offset <= this.aMin + options.snapOffset) {
|
||||
offset = this.aMin
|
||||
} else if (offset >= this.size - this.bMin - options.snapOffset) {
|
||||
offset = this.size - this.bMin
|
||||
}
|
||||
|
||||
adjust.call(this, offset)
|
||||
|
||||
if (options.onDrag) {
|
||||
options.onDrag()
|
||||
}
|
||||
}
|
||||
, calculateSizes = function () {
|
||||
// Calculate the pairs size, and percentage of the parent size
|
||||
var computedStyle = global.getComputedStyle(this.parent)
|
||||
, parentSize = this.parent[clientDimension] - parseFloat(computedStyle[paddingA]) - parseFloat(computedStyle[paddingB])
|
||||
|
||||
this.size = this.a[getBoundingClientRect]()[dimension] + this.b[getBoundingClientRect]()[dimension] + this.aGutterSize + this.bGutterSize
|
||||
this.percentage = Math.min(this.size / parentSize * 100, 100)
|
||||
this.start = this.a[getBoundingClientRect]()[position]
|
||||
}
|
||||
, adjust = function (offset) {
|
||||
// A size is the same as offset. B size is total size - A size.
|
||||
// Both sizes are calculated from the initial parent percentage.
|
||||
|
||||
this.a.style[dimension] = calc + '(' + (offset / this.size * this.percentage) + '% - ' + this.aGutterSize + 'px)'
|
||||
this.b.style[dimension] = calc + '(' + (this.percentage - (offset / this.size * this.percentage)) + '% - ' + this.bGutterSize + 'px)'
|
||||
}
|
||||
, fitMin = function () {
|
||||
var self = this
|
||||
, a = self.a
|
||||
, b = self.b
|
||||
|
||||
if (a[getBoundingClientRect]()[dimension] < self.aMin) {
|
||||
a.style[dimension] = (self.aMin - self.aGutterSize) + 'px'
|
||||
b.style[dimension] = (self.size - self.aMin - self.aGutterSize) + 'px'
|
||||
} else if (b[getBoundingClientRect]()[dimension] < self.bMin) {
|
||||
a.style[dimension] = (self.size - self.bMin - self.bGutterSize) + 'px'
|
||||
b.style[dimension] = (self.bMin - self.bGutterSize) + 'px'
|
||||
}
|
||||
}
|
||||
, fitMinReverse = function () {
|
||||
var self = this
|
||||
, a = self.a
|
||||
, b = self.b
|
||||
|
||||
if (b[getBoundingClientRect]()[dimension] < self.bMin) {
|
||||
a.style[dimension] = (self.size - self.bMin - self.bGutterSize) + 'px'
|
||||
b.style[dimension] = (self.bMin - self.bGutterSize) + 'px'
|
||||
} else if (a[getBoundingClientRect]()[dimension] < self.aMin) {
|
||||
a.style[dimension] = (self.aMin - self.aGutterSize) + 'px'
|
||||
b.style[dimension] = (self.size - self.aMin - self.aGutterSize) + 'px'
|
||||
}
|
||||
}
|
||||
, balancePairs = function (pairs) {
|
||||
for (var i = 0; i < pairs.length; i++) {
|
||||
calculateSizes.call(pairs[i])
|
||||
fitMin.call(pairs[i])
|
||||
}
|
||||
|
||||
for (i = pairs.length - 1; i >= 0; i--) {
|
||||
calculateSizes.call(pairs[i])
|
||||
fitMinReverse.call(pairs[i])
|
||||
}
|
||||
}
|
||||
, preventSelection = function () { return false }
|
||||
, parent = elementOrSelector(ids[0]).parentNode
|
||||
|
||||
if (!options.sizes) {
|
||||
var percent = 100 / ids.length
|
||||
|
||||
options.sizes = []
|
||||
|
||||
for (i = 0; i < ids.length; i++) {
|
||||
options.sizes.push(percent)
|
||||
}
|
||||
}
|
||||
|
||||
if (!Array.isArray(options.minSize)) {
|
||||
var minSizes = []
|
||||
|
||||
for (i = 0; i < ids.length; i++) {
|
||||
minSizes.push(options.minSize)
|
||||
}
|
||||
|
||||
options.minSize = minSizes
|
||||
}
|
||||
|
||||
for (i = 0; i < ids.length; i++) {
|
||||
var el = elementOrSelector(ids[i])
|
||||
, isFirst = (i == 1)
|
||||
, isLast = (i == ids.length - 1)
|
||||
, size
|
||||
, gutterSize = options.gutterSize
|
||||
, pair
|
||||
, parentFlexDirection = window.getComputedStyle(parent).flexDirection
|
||||
, temp
|
||||
|
||||
if (i > 0) {
|
||||
pair = {
|
||||
a: elementOrSelector(ids[i - 1]),
|
||||
b: el,
|
||||
aMin: options.minSize[i - 1],
|
||||
bMin: options.minSize[i],
|
||||
dragging: false,
|
||||
parent: parent,
|
||||
isFirst: isFirst,
|
||||
isLast: isLast,
|
||||
direction: options.direction
|
||||
}
|
||||
|
||||
// For first and last pairs, first and last gutter width is half.
|
||||
|
||||
pair.aGutterSize = options.gutterSize
|
||||
pair.bGutterSize = options.gutterSize
|
||||
|
||||
if (isFirst) {
|
||||
pair.aGutterSize = options.gutterSize / 2
|
||||
}
|
||||
|
||||
if (isLast) {
|
||||
pair.bGutterSize = options.gutterSize / 2
|
||||
}
|
||||
|
||||
// if the parent has a reverse flex-direction, switch the pair elements.
|
||||
if (parentFlexDirection === 'row-reverse' || parentFlexDirection === 'column-reverse') {
|
||||
temp = pair.a;
|
||||
pair.a = pair.b;
|
||||
pair.b = temp;
|
||||
}
|
||||
}
|
||||
|
||||
// IE9 and above
|
||||
if (!isIE8) {
|
||||
if (i > 0) {
|
||||
var gutter = document.createElement('div')
|
||||
|
||||
gutter.className = gutterClass
|
||||
gutter.style[dimension] = options.gutterSize + 'px'
|
||||
|
||||
gutter[addEventListener]('mousedown', startDragging.bind(pair))
|
||||
gutter[addEventListener]('touchstart', startDragging.bind(pair))
|
||||
|
||||
parent.insertBefore(gutter, el)
|
||||
|
||||
pair.gutter = gutter
|
||||
}
|
||||
|
||||
if (i === 0 || i == ids.length - 1) {
|
||||
gutterSize = options.gutterSize / 2
|
||||
}
|
||||
|
||||
if (typeof options.sizes[i] === 'string' || options.sizes[i] instanceof String) {
|
||||
size = options.sizes[i]
|
||||
} else {
|
||||
size = calc + '(' + options.sizes[i] + '% - ' + gutterSize + 'px)'
|
||||
}
|
||||
|
||||
// IE8 and below
|
||||
} else {
|
||||
if (typeof options.sizes[i] === 'string' || options.sizes[i] instanceof String) {
|
||||
size = options.sizes[i]
|
||||
} else {
|
||||
size = options.sizes[i] + '%'
|
||||
}
|
||||
}
|
||||
|
||||
el.style[dimension] = size
|
||||
|
||||
if (i > 0) {
|
||||
pairs.push(pair)
|
||||
}
|
||||
}
|
||||
|
||||
balancePairs(pairs)
|
||||
}
|
||||
|
||||
if (typeof exports !== 'undefined') {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
exports = module.exports = Split
|
||||
}
|
||||
exports.Split = Split
|
||||
} else {
|
||||
global.Split = Split
|
||||
}
|
||||
|
||||
}).call(window);
|
Reference in New Issue
Block a user