Annotation of loncom/html/adm/split.js/split.js, revision 1.1
1.1 ! damieng 1:
! 2: 'use strict';
! 3:
! 4: (function() {
! 5:
! 6: var global = this
! 7: , querySelector = 'querySelector'
! 8: , addEventListener = 'addEventListener'
! 9: , removeEventListener = 'removeEventListener'
! 10: , getBoundingClientRect = 'getBoundingClientRect'
! 11: , isIE8 = global.attachEvent && !global[addEventListener]
! 12:
! 13: , calc = (function () {
! 14: var el
! 15: , prefixes = ["", "-webkit-", "-moz-", "-o-"]
! 16:
! 17: for (var i = 0; i < prefixes.length; i++) {
! 18: el = global.document.createElement('div')
! 19: el.style.cssText = "width:" + prefixes[i] + "calc(9px)"
! 20:
! 21: if (el.style.length) {
! 22: return prefixes[i] + "calc"
! 23: }
! 24: }
! 25: })()
! 26:
! 27: , Split = function (ids, options) {
! 28: var dimension
! 29: , i
! 30: , clientDimension
! 31: , clientAxis
! 32: , position
! 33: , gutterClass
! 34: , paddingA
! 35: , paddingB
! 36: , pairs = []
! 37:
! 38: // Set defaults
! 39:
! 40: options = typeof options !== 'undefined' ? options : {}
! 41:
! 42: if (!options.gutterSize) options.gutterSize = 10
! 43: if (!options.minSize) options.minSize = 100
! 44: if (!options.snapOffset) options.snapOffset = 30
! 45: if (!options.direction) options.direction = 'horizontal'
! 46: if (!options.cursor) options.cursor = 'grabbing'
! 47:
! 48: if (options.direction == 'horizontal') {
! 49: dimension = 'width'
! 50: clientDimension = 'clientWidth'
! 51: clientAxis = 'clientX'
! 52: position = 'left'
! 53: gutterClass = 'gutter gutter-horizontal'
! 54: paddingA = 'paddingLeft'
! 55: paddingB = 'paddingRight'
! 56: } else if (options.direction == 'vertical') {
! 57: dimension = 'height'
! 58: clientDimension = 'clientHeight'
! 59: clientAxis = 'clientY'
! 60: position = 'top'
! 61: gutterClass = 'gutter gutter-vertical'
! 62: paddingA = 'paddingTop'
! 63: paddingB = 'paddingBottom'
! 64: }
! 65:
! 66: // Event listeners for drag events, bound to a pair object.
! 67: // Calculate the pair's position and size when dragging starts.
! 68: // Prevent selection on start and re-enable it when done.
! 69:
! 70: var startDragging = function (e) {
! 71: if (!this.dragging && options.onDragStart) {
! 72: options.onDragStart()
! 73: }
! 74:
! 75: e.preventDefault()
! 76:
! 77: this.dragging = true
! 78: this.move = drag.bind(this)
! 79: this.stop = stopDragging.bind(this)
! 80:
! 81: global[addEventListener]('mouseup', this.stop)
! 82: global[addEventListener]('touchend', this.stop)
! 83: global[addEventListener]('touchcancel', this.stop)
! 84:
! 85: this.parent[addEventListener]('mousemove', this.move)
! 86: this.parent[addEventListener]('touchmove', this.move)
! 87:
! 88: this.a[addEventListener]('selectstart', preventSelection)
! 89: this.a[addEventListener]('dragstart', preventSelection)
! 90: this.b[addEventListener]('selectstart', preventSelection)
! 91: this.b[addEventListener]('dragstart', preventSelection)
! 92:
! 93: this.a.style.userSelect = 'none'
! 94: this.a.style.webkitUserSelect = 'none'
! 95: this.a.style.MozUserSelect = 'none'
! 96: this.a.style.pointerEvents = 'none'
! 97: this.a.style.cursor = options.cursor
! 98:
! 99: this.b.style.userSelect = 'none'
! 100: this.b.style.webkitUserSelect = 'none'
! 101: this.b.style.MozUserSelect = 'none'
! 102: this.b.style.pointerEvents = 'none'
! 103: this.b.style.cursor = options.cursor
! 104:
! 105: this.gutter.style.cursor = options.cursor
! 106:
! 107: calculateSizes.call(this)
! 108: }
! 109: , stopDragging = function () {
! 110: if (this.dragging && options.onDragEnd) {
! 111: options.onDragEnd()
! 112: }
! 113:
! 114: this.dragging = false
! 115:
! 116: global[removeEventListener]('mouseup', this.stop)
! 117: global[removeEventListener]('touchend', this.stop)
! 118: global[removeEventListener]('touchcancel', this.stop)
! 119:
! 120: this.parent[removeEventListener]('mousemove', this.move)
! 121: this.parent[removeEventListener]('touchmove', this.move)
! 122:
! 123: delete this.stop
! 124: delete this.move
! 125:
! 126: this.a[removeEventListener]('selectstart', preventSelection)
! 127: this.a[removeEventListener]('dragstart', preventSelection)
! 128: this.b[removeEventListener]('selectstart', preventSelection)
! 129: this.b[removeEventListener]('dragstart', preventSelection)
! 130:
! 131: this.a.style.userSelect = ''
! 132: this.a.style.webkitUserSelect = ''
! 133: this.a.style.MozUserSelect = ''
! 134: this.a.style.pointerEvents = ''
! 135: this.a.style.cursor = ''
! 136:
! 137: this.b.style.userSelect = ''
! 138: this.b.style.webkitUserSelect = ''
! 139: this.b.style.MozUserSelect = ''
! 140: this.b.style.pointerEvents = ''
! 141: this.b.style.cursor = ''
! 142:
! 143: this.gutter.style.cursor = ''
! 144: }
! 145: , drag = function (e) {
! 146: var offset
! 147:
! 148: if (!this.dragging) return
! 149:
! 150: // Get the relative position of the event from the first side of the
! 151: // pair.
! 152:
! 153: if ('touches' in e) {
! 154: offset = e.touches[0][clientAxis] - this.start
! 155: } else {
! 156: offset = e[clientAxis] - this.start
! 157: }
! 158:
! 159: // If within snapOffset of min or max, set offset to min or max
! 160:
! 161: if (offset <= this.aMin + options.snapOffset) {
! 162: offset = this.aMin
! 163: } else if (offset >= this.size - this.bMin - options.snapOffset) {
! 164: offset = this.size - this.bMin
! 165: }
! 166:
! 167: adjust.call(this, offset)
! 168:
! 169: if (options.onDrag) {
! 170: options.onDrag()
! 171: }
! 172: }
! 173: , calculateSizes = function () {
! 174: // Calculate the pairs size, and percentage of the parent size
! 175: var computedStyle = global.getComputedStyle(this.parent)
! 176: , parentSize = this.parent[clientDimension] - parseFloat(computedStyle[paddingA]) - parseFloat(computedStyle[paddingB])
! 177:
! 178: this.size = this.a[getBoundingClientRect]()[dimension] + this.b[getBoundingClientRect]()[dimension] + this.aGutterSize + this.bGutterSize
! 179: this.percentage = Math.min(this.size / parentSize * 100, 100)
! 180: this.start = this.a[getBoundingClientRect]()[position]
! 181: }
! 182: , adjust = function (offset) {
! 183: // A size is the same as offset. B size is total size - A size.
! 184: // Both sizes are calculated from the initial parent percentage.
! 185:
! 186: this.a.style[dimension] = calc + '(' + (offset / this.size * this.percentage) + '% - ' + this.aGutterSize + 'px)'
! 187: this.b.style[dimension] = calc + '(' + (this.percentage - (offset / this.size * this.percentage)) + '% - ' + this.bGutterSize + 'px)'
! 188: }
! 189: , fitMin = function () {
! 190: if (this.a[getBoundingClientRect]()[dimension] < this.aMin) {
! 191: this.a.style[dimension] = (this.aMin - this.aGutterSize) + 'px'
! 192: this.b.style[dimension] = (this.size - this.aMin - this.aGutterSize) + 'px'
! 193: } else if (this.b[getBoundingClientRect]()[dimension] < this.bMin) {
! 194: this.a.style[dimension] = (this.size - this.bMin - this.bGutterSize) + 'px'
! 195: this.b.style[dimension] = (this.bMin - this.bGutterSize) + 'px'
! 196: }
! 197: }
! 198: , fitMinReverse = function () {
! 199: if (this.b[getBoundingClientRect]()[dimension] < this.bMin) {
! 200: this.a.style[dimension] = (this.size - this.bMin - this.bGutterSize) + 'px'
! 201: this.b.style[dimension] = (this.bMin - this.bGutterSize) + 'px'
! 202: } else if (this.a[getBoundingClientRect]()[dimension] < this.aMin) {
! 203: this.a.style[dimension] = (this.aMin - this.aGutterSize) + 'px'
! 204: this.b.style[dimension] = (this.size - this.aMin - this.aGutterSize) + 'px'
! 205: }
! 206: }
! 207: , balancePairs = function (pairs) {
! 208: for (var i = 0; i < pairs.length; i++) {
! 209: calculateSizes.call(pairs[i])
! 210: fitMin.call(pairs[i])
! 211: }
! 212:
! 213: for (i = pairs.length - 1; i >= 0; i--) {
! 214: calculateSizes.call(pairs[i])
! 215: fitMinReverse.call(pairs[i])
! 216: }
! 217: }
! 218: , preventSelection = function () { return false }
! 219: , parent = global.document[querySelector](ids[0]).parentNode
! 220:
! 221: if (!options.sizes) {
! 222: var percent = 100 / ids.length
! 223:
! 224: options.sizes = []
! 225:
! 226: for (i = 0; i < ids.length; i++) {
! 227: options.sizes.push(percent)
! 228: }
! 229: }
! 230:
! 231: if (!Array.isArray(options.minSize)) {
! 232: var minSizes = []
! 233:
! 234: for (i = 0; i < ids.length; i++) {
! 235: minSizes.push(options.minSize)
! 236: }
! 237:
! 238: options.minSize = minSizes
! 239: }
! 240:
! 241: for (i = 0; i < ids.length; i++) {
! 242: var el = global.document[querySelector](ids[i])
! 243: , isFirst = (i == 1)
! 244: , isLast = (i == ids.length - 1)
! 245: , size
! 246: , gutterSize = options.gutterSize
! 247: , pair
! 248:
! 249: if (i > 0) {
! 250: pair = {
! 251: a: global.document[querySelector](ids[i - 1]),
! 252: b: el,
! 253: aMin: options.minSize[i - 1],
! 254: bMin: options.minSize[i],
! 255: dragging: false,
! 256: parent: parent,
! 257: isFirst: isFirst,
! 258: isLast: isLast,
! 259: direction: options.direction
! 260: }
! 261:
! 262: // For first and last pairs, first and last gutter width is half.
! 263:
! 264: pair.aGutterSize = options.gutterSize
! 265: pair.bGutterSize = options.gutterSize
! 266:
! 267: if (isFirst) {
! 268: pair.aGutterSize = options.gutterSize / 2
! 269: }
! 270:
! 271: if (isLast) {
! 272: pair.bGutterSize = options.gutterSize / 2
! 273: }
! 274: }
! 275:
! 276: // IE9 and above
! 277: if (!isIE8) {
! 278: if (i > 0) {
! 279: var gutter = global.document.createElement('div')
! 280:
! 281: gutter.className = gutterClass
! 282: gutter.style[dimension] = options.gutterSize + 'px'
! 283:
! 284: gutter[addEventListener]('mousedown', startDragging.bind(pair))
! 285: gutter[addEventListener]('touchstart', startDragging.bind(pair))
! 286:
! 287: parent.insertBefore(gutter, el)
! 288:
! 289: pair.gutter = gutter
! 290: }
! 291:
! 292: if (i === 0 || i == ids.length - 1) {
! 293: gutterSize = options.gutterSize / 2
! 294: }
! 295:
! 296: if (typeof options.sizes[i] === 'string' || options.sizes[i] instanceof String) {
! 297: size = options.sizes[i]
! 298: } else {
! 299: size = calc + '(' + options.sizes[i] + '% - ' + gutterSize + 'px)'
! 300: }
! 301:
! 302: // IE8 and below
! 303: } else {
! 304: if (typeof options.sizes[i] === 'string' || options.sizes[i] instanceof String) {
! 305: size = options.sizes[i]
! 306: } else {
! 307: size = options.sizes[i] + '%'
! 308: }
! 309: }
! 310:
! 311: el.style[dimension] = size
! 312:
! 313: if (i > 0) {
! 314: pairs.push(pair)
! 315: }
! 316: }
! 317:
! 318: balancePairs(pairs)
! 319: }
! 320:
! 321: if (typeof exports !== 'undefined') {
! 322: if (typeof module !== 'undefined' && module.exports) {
! 323: exports = module.exports = Split
! 324: }
! 325: exports.Split = Split
! 326: } else {
! 327: global.Split = Split
! 328: }
! 329:
! 330: }).call(window)
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>