| Conditions | 10 |
| Paths | 48 |
| Total Lines | 494 |
| Code Lines | 251 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like split.js ➔ ... ➔ Split often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | /*! Split.js - v1.3.5 */ |
||
| 90 | var Split = function(ids, options) { |
||
| 91 | if (options === void 0) options = {}; |
||
| 92 | |||
| 93 | var dimension; |
||
| 94 | var clientDimension; |
||
| 95 | var clientAxis; |
||
| 96 | var position; |
||
| 97 | var paddingA; |
||
| 98 | var paddingB; |
||
| 99 | var elements; |
||
| 100 | |||
| 101 | // All DOM elements in the split should have a common parent. We can grab |
||
| 102 | // the first elements parent and hope users read the docs because the |
||
| 103 | // behavior will be whacky otherwise. |
||
| 104 | var parent = elementOrSelector(ids[0]).parentNode; |
||
| 105 | var parentFlexDirection = global.getComputedStyle(parent).flexDirection; |
||
| 106 | |||
| 107 | // Set default options.sizes to equal percentages of the parent element. |
||
| 108 | var sizes = |
||
| 109 | options.sizes || |
||
| 110 | ids.map(function() { |
||
| 111 | return 100 / ids.length; |
||
| 112 | }); |
||
| 113 | |||
| 114 | // Standardize minSize to an array if it isn't already. This allows minSize |
||
| 115 | // to be passed as a number. |
||
| 116 | var minSize = options.minSize !== undefined ? options.minSize : 100; |
||
| 117 | var minSizes = Array.isArray(minSize) |
||
| 118 | ? minSize |
||
| 119 | : ids.map(function() { |
||
| 120 | return minSize; |
||
| 121 | }); |
||
| 122 | var gutterSize = options.gutterSize !== undefined ? options.gutterSize : 10; |
||
| 123 | var snapOffset = options.snapOffset !== undefined ? options.snapOffset : 30; |
||
| 124 | var direction = options.direction || 'horizontal'; |
||
| 125 | var cursor = |
||
| 126 | options.cursor || |
||
| 127 | (direction === 'horizontal' ? 'ew-resize' : 'ns-resize'); |
||
| 128 | var gutter = |
||
| 129 | options.gutter || |
||
| 130 | function(i, gutterDirection) { |
||
| 131 | var gut = document.createElement('div'); |
||
| 132 | gut.className = 'gutter gutter-' + gutterDirection; |
||
| 133 | return gut; |
||
| 134 | }; |
||
| 135 | var elementStyle = |
||
| 136 | options.elementStyle || |
||
| 137 | function(dim, size, gutSize) { |
||
| 138 | var style = {}; |
||
| 139 | |||
| 140 | if (typeof size !== 'string' && !(size instanceof String)) { |
||
| 141 | if (!isIE8) { |
||
| 142 | style[dim] = calc + '(' + size + '% - ' + gutSize + 'px)'; |
||
| 143 | } else { |
||
| 144 | style[dim] = size + '%'; |
||
| 145 | } |
||
| 146 | } else { |
||
| 147 | style[dim] = size; |
||
| 148 | } |
||
| 149 | |||
| 150 | return style; |
||
| 151 | }; |
||
| 152 | var gutterStyle = |
||
| 153 | options.gutterStyle || |
||
| 154 | function(dim, gutSize) { |
||
| 155 | return (obj = {}), (obj[dim] = gutSize + 'px'), obj; |
||
| 156 | var obj; |
||
| 157 | }; |
||
| 158 | |||
| 159 | // 2. Initialize a bunch of strings based on the direction we're splitting. |
||
| 160 | // A lot of the behavior in the rest of the library is paramatized down to |
||
| 161 | // rely on CSS strings and classes. |
||
| 162 | if (direction === 'horizontal') { |
||
| 163 | dimension = 'width'; |
||
| 164 | clientDimension = 'clientWidth'; |
||
| 165 | clientAxis = 'clientX'; |
||
| 166 | position = 'left'; |
||
| 167 | paddingA = 'paddingLeft'; |
||
| 168 | paddingB = 'paddingRight'; |
||
| 169 | } else if (direction === 'vertical') { |
||
| 170 | dimension = 'height'; |
||
| 171 | clientDimension = 'clientHeight'; |
||
| 172 | clientAxis = 'clientY'; |
||
| 173 | position = 'top'; |
||
| 174 | paddingA = 'paddingTop'; |
||
| 175 | paddingB = 'paddingBottom'; |
||
| 176 | } |
||
| 177 | |||
| 178 | // 3. Define the dragging helper functions, and a few helpers to go with them. |
||
| 179 | // Each helper is bound to a pair object that contains it's metadata. This |
||
| 180 | // also makes it easy to store references to listeners that that will be |
||
| 181 | // added and removed. |
||
| 182 | // |
||
| 183 | // Even though there are no other functions contained in them, aliasing |
||
| 184 | // this to self saves 50 bytes or so since it's used so frequently. |
||
| 185 | // |
||
| 186 | // The pair object saves metadata like dragging state, position and |
||
| 187 | // event listener references. |
||
| 188 | |||
| 189 | function setElementSize(el, size, gutSize) { |
||
| 190 | // Split.js allows setting sizes via numbers (ideally), or if you must, |
||
| 191 | // by string, like '300px'. This is less than ideal, because it breaks |
||
| 192 | // the fluid layout that `calc(% - px)` provides. You're on your own if you do that, |
||
| 193 | // make sure you calculate the gutter size by hand. |
||
| 194 | var style = elementStyle(dimension, size, gutSize); |
||
| 195 | |||
| 196 | // eslint-disable-next-line no-param-reassign |
||
| 197 | Object.keys(style).forEach(function(prop) { |
||
| 198 | return (el.style[prop] = style[prop]); |
||
| 199 | }); |
||
| 200 | } |
||
| 201 | |||
| 202 | function setGutterSize(gutterElement, gutSize) { |
||
| 203 | var style = gutterStyle(dimension, gutSize); |
||
| 204 | |||
| 205 | // eslint-disable-next-line no-param-reassign |
||
| 206 | Object.keys(style).forEach(function(prop) { |
||
| 207 | return (gutterElement.style[prop] = style[prop]); |
||
| 208 | }); |
||
| 209 | } |
||
| 210 | |||
| 211 | // Actually adjust the size of elements `a` and `b` to `offset` while dragging. |
||
| 212 | // calc is used to allow calc(percentage + gutterpx) on the whole split instance, |
||
| 213 | // which allows the viewport to be resized without additional logic. |
||
| 214 | // Element a's size is the same as offset. b's size is total size - a size. |
||
| 215 | // Both sizes are calculated from the initial parent percentage, |
||
| 216 | // then the gutter size is subtracted. |
||
| 217 | function adjust(offset) { |
||
| 218 | var a = elements[this.a]; |
||
| 219 | var b = elements[this.b]; |
||
| 220 | var percentage = a.size + b.size; |
||
| 221 | |||
| 222 | a.size = offset / this.size * percentage; |
||
| 223 | b.size = percentage - offset / this.size * percentage; |
||
| 224 | |||
| 225 | setElementSize(a.element, a.size, this.aGutterSize); |
||
| 226 | setElementSize(b.element, b.size, this.bGutterSize); |
||
| 227 | } |
||
| 228 | |||
| 229 | // drag, where all the magic happens. The logic is really quite simple: |
||
| 230 | // |
||
| 231 | // 1. Ignore if the pair is not dragging. |
||
| 232 | // 2. Get the offset of the event. |
||
| 233 | // 3. Snap offset to min if within snappable range (within min + snapOffset). |
||
| 234 | // 4. Actually adjust each element in the pair to offset. |
||
| 235 | // |
||
| 236 | // --------------------------------------------------------------------- |
||
| 237 | // | | <- a.minSize || b.minSize -> | | |
||
| 238 | // | | | <- this.snapOffset || this.snapOffset -> | | | |
||
| 239 | // | | | || | | | |
||
| 240 | // | | | || | | | |
||
| 241 | // --------------------------------------------------------------------- |
||
| 242 | // | <- this.start this.size -> | |
||
| 243 | function drag(e) { |
||
| 244 | var offset; |
||
| 245 | |||
| 246 | if (!this.dragging) { |
||
| 247 | return; |
||
| 248 | } |
||
| 249 | |||
| 250 | // Get the offset of the event from the first side of the |
||
| 251 | // pair `this.start`. Supports touch events, but not multitouch, so only the first |
||
| 252 | // finger `touches[0]` is counted. |
||
| 253 | if ('touches' in e) { |
||
| 254 | offset = e.touches[0][clientAxis] - this.start; |
||
| 255 | } else { |
||
| 256 | offset = e[clientAxis] - this.start; |
||
| 257 | } |
||
| 258 | |||
| 259 | // If within snapOffset of min or max, set offset to min or max. |
||
| 260 | // snapOffset buffers a.minSize and b.minSize, so logic is opposite for both. |
||
| 261 | // Include the appropriate gutter sizes to prevent overflows. |
||
| 262 | if (offset <= elements[this.a].minSize + snapOffset + this.aGutterSize) { |
||
| 263 | offset = elements[this.a].minSize + this.aGutterSize; |
||
| 264 | } else if ( |
||
| 265 | offset >= |
||
| 266 | this.size - (elements[this.b].minSize + snapOffset + this.bGutterSize) |
||
| 267 | ) { |
||
| 268 | offset = this.size - (elements[this.b].minSize + this.bGutterSize); |
||
| 269 | } |
||
| 270 | |||
| 271 | // Actually adjust the size. |
||
| 272 | adjust.call(this, offset); |
||
| 273 | |||
| 274 | // Call the drag callback continously. Don't do anything too intensive |
||
| 275 | // in this callback. |
||
| 276 | if (options.onDrag) { |
||
| 277 | options.onDrag(); |
||
| 278 | } |
||
| 279 | } |
||
| 280 | |||
| 281 | // Cache some important sizes when drag starts, so we don't have to do that |
||
| 282 | // continously: |
||
| 283 | // |
||
| 284 | // `size`: The total size of the pair. First + second + first gutter + second gutter. |
||
| 285 | // `start`: The leading side of the first element. |
||
| 286 | // |
||
| 287 | // ------------------------------------------------ |
||
| 288 | // | aGutterSize -> ||| | |
||
| 289 | // | ||| | |
||
| 290 | // | ||| | |
||
| 291 | // | ||| <- bGutterSize | |
||
| 292 | // ------------------------------------------------ |
||
| 293 | // | <- start size -> | |
||
| 294 | function calculateSizes() { |
||
| 295 | // Figure out the parent size minus padding. |
||
| 296 | var a = elements[this.a].element; |
||
| 297 | var b = elements[this.b].element; |
||
| 298 | |||
| 299 | this.size = |
||
| 300 | a[getBoundingClientRect]()[dimension] + |
||
| 301 | b[getBoundingClientRect]()[dimension] + |
||
| 302 | this.aGutterSize + |
||
| 303 | this.bGutterSize; |
||
| 304 | this.start = a[getBoundingClientRect]()[position]; |
||
| 305 | } |
||
| 306 | |||
| 307 | // stopDragging is very similar to startDragging in reverse. |
||
| 308 | function stopDragging() { |
||
| 309 | var self = this; |
||
| 310 | var a = elements[self.a].element; |
||
| 311 | var b = elements[self.b].element; |
||
| 312 | |||
| 313 | if (self.dragging && options.onDragEnd) { |
||
| 314 | options.onDragEnd(); |
||
| 315 | } |
||
| 316 | |||
| 317 | self.dragging = false; |
||
| 318 | |||
| 319 | // Remove the stored event listeners. This is why we store them. |
||
| 320 | global[removeEventListener]('mouseup', self.stop); |
||
| 321 | global[removeEventListener]('touchend', self.stop); |
||
| 322 | global[removeEventListener]('touchcancel', self.stop); |
||
| 323 | |||
| 324 | self.parent[removeEventListener]('mousemove', self.move); |
||
| 325 | self.parent[removeEventListener]('touchmove', self.move); |
||
| 326 | |||
| 327 | // Delete them once they are removed. I think this makes a difference |
||
| 328 | // in memory usage with a lot of splits on one page. But I don't know for sure. |
||
| 329 | delete self.stop; |
||
| 330 | delete self.move; |
||
| 331 | |||
| 332 | a[removeEventListener]('selectstart', NOOP); |
||
| 333 | a[removeEventListener]('dragstart', NOOP); |
||
| 334 | b[removeEventListener]('selectstart', NOOP); |
||
| 335 | b[removeEventListener]('dragstart', NOOP); |
||
| 336 | |||
| 337 | a.style.userSelect = ''; |
||
| 338 | a.style.webkitUserSelect = ''; |
||
| 339 | a.style.MozUserSelect = ''; |
||
| 340 | a.style.pointerEvents = ''; |
||
| 341 | |||
| 342 | b.style.userSelect = ''; |
||
| 343 | b.style.webkitUserSelect = ''; |
||
| 344 | b.style.MozUserSelect = ''; |
||
| 345 | b.style.pointerEvents = ''; |
||
| 346 | |||
| 347 | self.gutter.style.cursor = ''; |
||
| 348 | self.parent.style.cursor = ''; |
||
| 349 | } |
||
| 350 | |||
| 351 | // startDragging calls `calculateSizes` to store the inital size in the pair object. |
||
| 352 | // It also adds event listeners for mouse/touch events, |
||
| 353 | // and prevents selection while dragging so avoid the selecting text. |
||
| 354 | function startDragging(e) { |
||
| 355 | // Alias frequently used variables to save space. 200 bytes. |
||
| 356 | var self = this; |
||
| 357 | var a = elements[self.a].element; |
||
| 358 | var b = elements[self.b].element; |
||
| 359 | |||
| 360 | // Call the onDragStart callback. |
||
| 361 | if (!self.dragging && options.onDragStart) { |
||
| 362 | options.onDragStart(); |
||
| 363 | } |
||
| 364 | |||
| 365 | // Don't actually drag the element. We emulate that in the drag function. |
||
| 366 | e.preventDefault(); |
||
| 367 | |||
| 368 | // Set the dragging property of the pair object. |
||
| 369 | self.dragging = true; |
||
| 370 | |||
| 371 | // Create two event listeners bound to the same pair object and store |
||
| 372 | // them in the pair object. |
||
| 373 | self.move = drag.bind(self); |
||
| 374 | self.stop = stopDragging.bind(self); |
||
| 375 | |||
| 376 | // All the binding. `window` gets the stop events in case we drag out of the elements. |
||
| 377 | global[addEventListener]('mouseup', self.stop); |
||
| 378 | global[addEventListener]('touchend', self.stop); |
||
| 379 | global[addEventListener]('touchcancel', self.stop); |
||
| 380 | |||
| 381 | self.parent[addEventListener]('mousemove', self.move); |
||
| 382 | self.parent[addEventListener]('touchmove', self.move); |
||
| 383 | |||
| 384 | // Disable selection. Disable! |
||
| 385 | a[addEventListener]('selectstart', NOOP); |
||
| 386 | a[addEventListener]('dragstart', NOOP); |
||
| 387 | b[addEventListener]('selectstart', NOOP); |
||
| 388 | b[addEventListener]('dragstart', NOOP); |
||
| 389 | |||
| 390 | a.style.userSelect = 'none'; |
||
| 391 | a.style.webkitUserSelect = 'none'; |
||
| 392 | a.style.MozUserSelect = 'none'; |
||
| 393 | a.style.pointerEvents = 'none'; |
||
| 394 | |||
| 395 | b.style.userSelect = 'none'; |
||
| 396 | b.style.webkitUserSelect = 'none'; |
||
| 397 | b.style.MozUserSelect = 'none'; |
||
| 398 | b.style.pointerEvents = 'none'; |
||
| 399 | |||
| 400 | // Set the cursor, both on the gutter and the parent element. |
||
| 401 | // Doing only a, b and gutter causes flickering. |
||
| 402 | self.gutter.style.cursor = cursor; |
||
| 403 | self.parent.style.cursor = cursor; |
||
| 404 | |||
| 405 | // Cache the initial sizes of the pair. |
||
| 406 | calculateSizes.call(self); |
||
| 407 | } |
||
| 408 | |||
| 409 | // 5. Create pair and element objects. Each pair has an index reference to |
||
| 410 | // elements `a` and `b` of the pair (first and second elements). |
||
| 411 | // Loop through the elements while pairing them off. Every pair gets a |
||
| 412 | // `pair` object, a gutter, and isFirst/isLast properties. |
||
| 413 | // |
||
| 414 | // Basic logic: |
||
| 415 | // |
||
| 416 | // - Starting with the second element `i > 0`, create `pair` objects with |
||
| 417 | // `a = i - 1` and `b = i` |
||
| 418 | // - Set gutter sizes based on the _pair_ being first/last. The first and last |
||
| 419 | // pair have gutterSize / 2, since they only have one half gutter, and not two. |
||
| 420 | // - Create gutter elements and add event listeners. |
||
| 421 | // - Set the size of the elements, minus the gutter sizes. |
||
| 422 | // |
||
| 423 | // ----------------------------------------------------------------------- |
||
| 424 | // | i=0 | i=1 | i=2 | i=3 | |
||
| 425 | // | | isFirst | | isLast | |
||
| 426 | // | pair 0 pair 1 pair 2 | |
||
| 427 | // | | | | | |
||
| 428 | // ----------------------------------------------------------------------- |
||
| 429 | var pairs = []; |
||
| 430 | elements = ids.map(function(id, i) { |
||
| 431 | // Create the element object. |
||
| 432 | var element = { |
||
| 433 | element: elementOrSelector(id), |
||
| 434 | size: sizes[i], |
||
| 435 | minSize: minSizes[i] |
||
| 436 | }; |
||
| 437 | |||
| 438 | var pair; |
||
| 439 | |||
| 440 | if (i > 0) { |
||
| 441 | // Create the pair object with it's metadata. |
||
| 442 | pair = { |
||
| 443 | a: i - 1, |
||
| 444 | b: i, |
||
| 445 | dragging: false, |
||
| 446 | isFirst: i === 1, |
||
| 447 | isLast: i === ids.length - 1, |
||
| 448 | direction: direction, |
||
| 449 | parent: parent |
||
| 450 | }; |
||
| 451 | |||
| 452 | // For first and last pairs, first and last gutter width is half. |
||
| 453 | pair.aGutterSize = gutterSize; |
||
| 454 | pair.bGutterSize = gutterSize; |
||
| 455 | |||
| 456 | if (pair.isFirst) { |
||
| 457 | pair.aGutterSize = gutterSize / 2; |
||
| 458 | } |
||
| 459 | |||
| 460 | if (pair.isLast) { |
||
| 461 | pair.bGutterSize = gutterSize / 2; |
||
| 462 | } |
||
| 463 | |||
| 464 | // if the parent has a reverse flex-direction, switch the pair elements. |
||
| 465 | if ( |
||
| 466 | parentFlexDirection === 'row-reverse' || |
||
| 467 | parentFlexDirection === 'column-reverse' |
||
| 468 | ) { |
||
| 469 | var temp = pair.a; |
||
| 470 | pair.a = pair.b; |
||
| 471 | pair.b = temp; |
||
| 472 | } |
||
| 473 | } |
||
| 474 | |||
| 475 | // Determine the size of the current element. IE8 is supported by |
||
| 476 | // staticly assigning sizes without draggable gutters. Assigns a string |
||
| 477 | // to `size`. |
||
| 478 | // |
||
| 479 | // IE9 and above |
||
| 480 | if (!isIE8) { |
||
| 481 | // Create gutter elements for each pair. |
||
| 482 | if (i > 0) { |
||
| 483 | var gutterElement = gutter(i, direction); |
||
| 484 | setGutterSize(gutterElement, gutterSize); |
||
| 485 | |||
| 486 | gutterElement[addEventListener]( |
||
| 487 | 'mousedown', |
||
| 488 | startDragging.bind(pair) |
||
| 489 | ); |
||
| 490 | gutterElement[addEventListener]( |
||
| 491 | 'touchstart', |
||
| 492 | startDragging.bind(pair) |
||
| 493 | ); |
||
| 494 | |||
| 495 | parent.insertBefore(gutterElement, element.element); |
||
| 496 | |||
| 497 | pair.gutter = gutterElement; |
||
| 498 | } |
||
| 499 | } |
||
| 500 | |||
| 501 | // Set the element size to our determined size. |
||
| 502 | // Half-size gutters for first and last elements. |
||
| 503 | if (i === 0 || i === ids.length - 1) { |
||
| 504 | setElementSize(element.element, element.size, gutterSize / 2); |
||
| 505 | } else { |
||
| 506 | setElementSize(element.element, element.size, gutterSize); |
||
| 507 | } |
||
| 508 | |||
| 509 | var computedSize = element.element[getBoundingClientRect]()[dimension]; |
||
| 510 | |||
| 511 | if (computedSize < element.minSize) { |
||
| 512 | element.minSize = computedSize; |
||
| 513 | } |
||
| 514 | |||
| 515 | // After the first iteration, and we have a pair object, append it to the |
||
| 516 | // list of pairs. |
||
| 517 | if (i > 0) { |
||
| 518 | pairs.push(pair); |
||
| 519 | } |
||
| 520 | |||
| 521 | return element; |
||
| 522 | }); |
||
| 523 | |||
| 524 | function setSizes(newSizes) { |
||
| 525 | newSizes.forEach(function(newSize, i) { |
||
| 526 | if (i > 0) { |
||
| 527 | var pair = pairs[i - 1]; |
||
| 528 | var a = elements[pair.a]; |
||
| 529 | var b = elements[pair.b]; |
||
| 530 | |||
| 531 | a.size = newSizes[i - 1]; |
||
| 532 | b.size = newSize; |
||
| 533 | |||
| 534 | setElementSize(a.element, a.size, pair.aGutterSize); |
||
| 535 | setElementSize(b.element, b.size, pair.bGutterSize); |
||
| 536 | } |
||
| 537 | }); |
||
| 538 | } |
||
| 539 | |||
| 540 | function destroy() { |
||
| 541 | pairs.forEach(function(pair) { |
||
| 542 | pair.parent.removeChild(pair.gutter); |
||
| 543 | elements[pair.a].element.style[dimension] = ''; |
||
| 544 | elements[pair.b].element.style[dimension] = ''; |
||
| 545 | }); |
||
| 546 | } |
||
| 547 | |||
| 548 | if (isIE8) { |
||
| 549 | return { |
||
| 550 | setSizes: setSizes, |
||
| 551 | destroy: destroy |
||
| 552 | }; |
||
| 553 | } |
||
| 554 | |||
| 555 | return { |
||
| 556 | setSizes: setSizes, |
||
| 557 | getSizes: function getSizes() { |
||
| 558 | return elements.map(function(element) { |
||
| 559 | return element.size; |
||
| 560 | }); |
||
| 561 | }, |
||
| 562 | collapse: function collapse(i) { |
||
| 563 | if (i === pairs.length) { |
||
| 564 | var pair = pairs[i - 1]; |
||
| 565 | |||
| 566 | calculateSizes.call(pair); |
||
| 567 | |||
| 568 | if (!isIE8) { |
||
| 569 | adjust.call(pair, pair.size - pair.bGutterSize); |
||
| 570 | } |
||
| 571 | } else { |
||
| 572 | var pair$1 = pairs[i]; |
||
| 573 | |||
| 574 | calculateSizes.call(pair$1); |
||
| 575 | |||
| 576 | if (!isIE8) { |
||
| 577 | adjust.call(pair$1, pair$1.aGutterSize); |
||
| 578 | } |
||
| 579 | } |
||
| 580 | }, |
||
| 581 | destroy: destroy |
||
| 582 | }; |
||
| 583 | }; |
||
| 584 | |||
| 587 |
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.
To learn more about declaring variables in Javascript, see the MDN.