UNPKG

49.1 kBJavaScriptView Raw
1(function webpackUniversalModuleDefinition(root, factory) {
2 if(typeof exports === 'object' && typeof module === 'object')
3 module.exports = factory();
4 else if(typeof define === 'function' && define.amd)
5 define(factory);
6 else if(typeof exports === 'object')
7 exports["Region"] = factory();
8 else
9 root["Region"] = factory();
10})(this, function() {
11return /******/ (function(modules) { // webpackBootstrap
12/******/ // The module cache
13/******/ var installedModules = {};
14/******/
15/******/ // The require function
16/******/ function __webpack_require__(moduleId) {
17/******/
18/******/ // Check if module is in cache
19/******/ if(installedModules[moduleId])
20/******/ return installedModules[moduleId].exports;
21/******/
22/******/ // Create a new module (and put it into the cache)
23/******/ var module = installedModules[moduleId] = {
24/******/ exports: {},
25/******/ id: moduleId,
26/******/ loaded: false
27/******/ };
28/******/
29/******/ // Execute the module function
30/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31/******/
32/******/ // Flag the module as loaded
33/******/ module.loaded = true;
34/******/
35/******/ // Return the exports of the module
36/******/ return module.exports;
37/******/ }
38/******/
39/******/
40/******/ // expose the modules object (__webpack_modules__)
41/******/ __webpack_require__.m = modules;
42/******/
43/******/ // expose the module cache
44/******/ __webpack_require__.c = installedModules;
45/******/
46/******/ // __webpack_public_path__
47/******/ __webpack_require__.p = "";
48/******/
49/******/ // Load entry module and return exports
50/******/ return __webpack_require__(0);
51/******/ })
52/************************************************************************/
53/******/ ([
54/* 0 */
55/***/ function(module, exports, __webpack_require__) {
56
57 module.exports = __webpack_require__(1)
58
59/***/ },
60/* 1 */
61/***/ function(module, exports, __webpack_require__) {
62
63 'use strict';
64
65 var hasOwn = __webpack_require__(6)
66 var newify = __webpack_require__(7)
67
68 var assign = __webpack_require__(8);
69 var EventEmitter = __webpack_require__(5).EventEmitter
70
71 var inherits = __webpack_require__(2)
72 var VALIDATE = __webpack_require__(3)
73
74 var objectToString = Object.prototype.toString
75
76 var isObject = function(value){
77 return objectToString.apply(value) === '[object Object]'
78 }
79
80 function copyList(source, target, list){
81 if (source){
82 list.forEach(function(key){
83 target[key] = source[key]
84 })
85 }
86
87 return target
88 }
89
90 /**
91 * @class Region
92 *
93 * The Region is an abstraction that allows the developer to refer to rectangles on the screen,
94 * and move them around, make diffs and unions, detect intersections, compute areas, etc.
95 *
96 * ## Creating a region
97 * var region = require('region')({
98 * top : 10,
99 * left : 10,
100 * bottom: 100,
101 * right : 100
102 * })
103 * //this region is a square, 90x90, starting from (10,10) to (100,100)
104 *
105 * var second = require('region')({ top: 10, left: 100, right: 200, bottom: 60})
106 * var union = region.getUnion(second)
107 *
108 * //the "union" region is a union between "region" and "second"
109 */
110
111 var POINT_POSITIONS = {
112 cy: 'YCenter',
113 cx: 'XCenter',
114 t : 'Top',
115 tc: 'TopCenter',
116 tl: 'TopLeft',
117 tr: 'TopRight',
118 b : 'Bottom',
119 bc: 'BottomCenter',
120 bl: 'BottomLeft',
121 br: 'BottomRight',
122 l : 'Left',
123 lc: 'LeftCenter',
124 r : 'Right',
125 rc: 'RightCenter',
126 c : 'Center'
127 }
128
129 /**
130 * @constructor
131 *
132 * Construct a new Region.
133 *
134 * Example:
135 *
136 * var r = new Region({ top: 10, left: 20, bottom: 100, right: 200 })
137 *
138 * //or, the same, but with numbers (can be used with new or without)
139 *
140 * r = Region(10, 200, 100, 20)
141 *
142 * //or, with width and height
143 *
144 * r = Region({ top: 10, left: 20, width: 180, height: 90})
145 *
146 * @param {Number|Object} top The top pixel position, or an object with top, left, bottom, right properties. If an object is passed,
147 * instead of having bottom and right, it can have width and height.
148 *
149 * @param {Number} right The right pixel position
150 * @param {Number} bottom The bottom pixel position
151 * @param {Number} left The left pixel position
152 *
153 * @return {Region} this
154 */
155 var REGION = function(top, right, bottom, left){
156
157 if (!(this instanceof REGION)){
158 return newify(REGION, arguments)
159 }
160
161 EventEmitter.call(this)
162
163 if (isObject(top)){
164 copyList(top, this, ['top','right','bottom','left'])
165
166 if (top.bottom == null && top.height != null){
167 this.bottom = this.top + top.height
168 }
169 if (top.right == null && top.width != null){
170 this.right = this.left + top.width
171 }
172
173 if (top.emitChangeEvents){
174 this.emitChangeEvents = top.emitChangeEvents
175 }
176 } else {
177 this.top = top
178 this.right = right
179 this.bottom = bottom
180 this.left = left
181 }
182
183 this[0] = this.left
184 this[1] = this.top
185
186 VALIDATE(this)
187 }
188
189 inherits(REGION, EventEmitter)
190
191 assign(REGION.prototype, {
192
193 /**
194 * @cfg {Boolean} emitChangeEvents If this is set to true, the region
195 * will emit 'changesize' and 'changeposition' whenever the size or the position changs
196 */
197 emitChangeEvents: false,
198
199 /**
200 * Returns this region, or a clone of this region
201 * @param {Boolean} [clone] If true, this method will return a clone of this region
202 * @return {Region} This region, or a clone of this
203 */
204 getRegion: function(clone){
205 return clone?
206 this.clone():
207 this
208 },
209
210 /**
211 * Sets the properties of this region to those of the given region
212 * @param {Region/Object} reg The region or object to use for setting properties of this region
213 * @return {Region} this
214 */
215 setRegion: function(reg){
216
217 if (reg instanceof REGION){
218 this.set(reg.get())
219 } else {
220 this.set(reg)
221 }
222
223 return this
224 },
225
226 /**
227 * Returns true if this region is valid, false otherwise
228 *
229 * @param {Region} region The region to check
230 * @return {Boolean} True, if the region is valid, false otherwise.
231 * A region is valid if
232 * * left <= right &&
233 * * top <= bottom
234 */
235 validate: function(){
236 return REGION.validate(this)
237 },
238
239 _before: function(){
240 if (this.emitChangeEvents){
241 return copyList(this, {}, ['left','top','bottom','right'])
242 }
243 },
244
245 _after: function(before){
246 if (this.emitChangeEvents){
247
248 if(this.top != before.top || this.left != before.left) {
249 this.emitPositionChange()
250 }
251
252 if(this.right != before.right || this.bottom != before.bottom) {
253 this.emitSizeChange()
254 }
255 }
256 },
257
258 notifyPositionChange: function(){
259 this.emit('changeposition', this)
260 },
261
262 emitPositionChange: function(){
263 this.notifyPositionChange()
264 },
265
266 notifySizeChange: function(){
267 this.emit('changesize', this)
268 },
269
270 emitSizeChange: function(){
271 this.notifySizeChange()
272 },
273
274 /**
275 * Add the given amounts to each specified side. Example
276 *
277 * region.add({
278 * top: 50, //add 50 px to the top side
279 * bottom: -100 //substract 100 px from the bottom side
280 * })
281 *
282 * @param {Object} directions
283 * @param {Number} [directions.top]
284 * @param {Number} [directions.left]
285 * @param {Number} [directions.bottom]
286 * @param {Number} [directions.right]
287 *
288 * @return {Region} this
289 */
290 add: function(directions){
291
292 var before = this._before()
293 var direction
294
295 for (direction in directions) if ( hasOwn(directions, direction) ) {
296 this[direction] += directions[direction]
297 }
298
299 this[0] = this.left
300 this[1] = this.top
301
302 this._after(before)
303
304 return this
305 },
306
307 /**
308 * The same as {@link #add}, but substracts the given values
309 * @param {Object} directions
310 * @param {Number} [directions.top]
311 * @param {Number} [directions.left]
312 * @param {Number} [directions.bottom]
313 * @param {Number} [directions.right]
314 *
315 * @return {Region} this
316 */
317 substract: function(directions){
318
319 var before = this._before()
320 var direction
321
322 for (direction in directions) if (hasOwn(directions, direction) ) {
323 this[direction] -= directions[direction]
324 }
325
326 this[0] = this.left
327 this[1] = this.top
328
329 this._after(before)
330
331 return this
332 },
333
334 /**
335 * Retrieves the size of the region.
336 * @return {Object} An object with {width, height}, corresponding to the width and height of the region
337 */
338 getSize: function(){
339 return {
340 width : this.width,
341 height : this.height
342 }
343 },
344
345 /**
346 * Move the region to the given position and keeps the region width and height.
347 *
348 * @param {Object} position An object with {top, left} properties. The values in {top,left} are used to move the region by the given amounts.
349 * @param {Number} [position.left]
350 * @param {Number} [position.top]
351 *
352 * @return {Region} this
353 */
354 setPosition: function(position){
355 var width = this.width
356 var height = this.height
357
358 if (position.left != undefined){
359 position.right = position.left + width
360 }
361
362 if (position.top != undefined){
363 position.bottom = position.top + height
364 }
365
366 return this.set(position)
367 },
368
369 /**
370 * Sets both the height and the width of this region to the given size.
371 *
372 * @param {Number} size The new size for the region
373 * @return {Region} this
374 */
375 setSize: function(size){
376 if (size.height != undefined && size.width != undefined){
377 return this.set({
378 right : this.left + size.width,
379 bottom : this.top + size.height
380 })
381 }
382
383 if (size.width != undefined){
384 this.setWidth(size.width)
385 }
386
387 if (size.height != undefined){
388 this.setHeight(size.height)
389 }
390
391 return this
392 },
393
394
395
396 /**
397 * @chainable
398 *
399 * Sets the width of this region
400 * @param {Number} width The new width for this region
401 * @return {Region} this
402 */
403 setWidth: function(width){
404 return this.set({
405 right: this.left + width
406 })
407 },
408
409 /**
410 * @chainable
411 *
412 * Sets the height of this region
413 * @param {Number} height The new height for this region
414 * @return {Region} this
415 */
416 setHeight: function(height){
417 return this.set({
418 bottom: this.top + height
419 })
420 },
421
422 /**
423 * Sets the given properties on this region
424 *
425 * @param {Object} directions an object containing top, left, and EITHER bottom, right OR width, height
426 * @param {Number} [directions.top]
427 * @param {Number} [directions.left]
428 *
429 * @param {Number} [directions.bottom]
430 * @param {Number} [directions.right]
431 *
432 * @param {Number} [directions.width]
433 * @param {Number} [directions.height]
434 *
435 *
436 * @return {Region} this
437 */
438 set: function(directions){
439 var before = this._before()
440
441 copyList(directions, this, ['left','top','bottom','right'])
442
443 if (directions.bottom == null && directions.height != null){
444 this.bottom = this.top + directions.height
445 }
446 if (directions.right == null && directions.width != null){
447 this.right = this.left + directions.width
448 }
449
450 this[0] = this.left
451 this[1] = this.top
452
453 this._after(before)
454
455 return this
456 },
457
458 /**
459 * Retrieves the given property from this region. If no property is given, return an object
460 * with {left, top, right, bottom}
461 *
462 * @param {String} [dir] the property to retrieve from this region
463 * @return {Number/Object}
464 */
465 get: function(dir){
466 return dir? this[dir]:
467 copyList(this, {}, ['left','right','top','bottom'])
468 },
469
470 /**
471 * Shifts this region to either top, or left or both.
472 * Shift is similar to {@link #add} by the fact that it adds the given dimensions to top/left sides, but also adds the given dimensions
473 * to bottom and right
474 *
475 * @param {Object} directions
476 * @param {Number} [directions.top]
477 * @param {Number} [directions.left]
478 *
479 * @return {Region} this
480 */
481 shift: function(directions){
482
483 var before = this._before()
484
485 if (directions.top){
486 this.top += directions.top
487 this.bottom += directions.top
488 }
489
490 if (directions.left){
491 this.left += directions.left
492 this.right += directions.left
493 }
494
495 this[0] = this.left
496 this[1] = this.top
497
498 this._after(before)
499
500 return this
501 },
502
503 /**
504 * Same as {@link #shift}, but substracts the given values
505 * @chainable
506 *
507 * @param {Object} directions
508 * @param {Number} [directions.top]
509 * @param {Number} [directions.left]
510 *
511 * @return {Region} this
512 */
513 unshift: function(directions){
514
515 if (directions.top){
516 directions.top *= -1
517 }
518
519 if (directions.left){
520 directions.left *= -1
521 }
522
523 return this.shift(directions)
524 },
525
526 /**
527 * Compare this region and the given region. Return true if they have all the same size and position
528 * @param {Region} region The region to compare with
529 * @return {Boolean} True if this and region have same size and position
530 */
531 equals: function(region){
532 return this.equalsPosition(region) && this.equalsSize(region)
533 },
534
535 /**
536 * Returns true if this region has the same bottom,right properties as the given region
537 * @param {Region/Object} size The region to compare against
538 * @return {Boolean} true if this region is the same size as the given size
539 */
540 equalsSize: function(size){
541 var isInstance = size instanceof REGION
542
543 var s = {
544 width: size.width == null && isInstance?
545 size.getWidth():
546 size.width,
547
548 height: size.height == null && isInstance?
549 size.getHeight():
550 size.height
551 }
552 return this.getWidth() == s.width && this.getHeight() == s.height
553 },
554
555 /**
556 * Returns true if this region has the same top,left properties as the given region
557 * @param {Region} region The region to compare against
558 * @return {Boolean} true if this.top == region.top and this.left == region.left
559 */
560 equalsPosition: function(region){
561 return this.top == region.top && this.left == region.left
562 },
563
564 /**
565 * Adds the given ammount to the left side of this region
566 * @param {Number} left The ammount to add
567 * @return {Region} this
568 */
569 addLeft: function(left){
570 var before = this._before()
571
572 this.left = this[0] = this.left + left
573
574 this._after(before)
575
576 return this
577 },
578
579 /**
580 * Adds the given ammount to the top side of this region
581 * @param {Number} top The ammount to add
582 * @return {Region} this
583 */
584 addTop: function(top){
585 var before = this._before()
586
587 this.top = this[1] = this.top + top
588
589 this._after(before)
590
591 return this
592 },
593
594 /**
595 * Adds the given ammount to the bottom side of this region
596 * @param {Number} bottom The ammount to add
597 * @return {Region} this
598 */
599 addBottom: function(bottom){
600 var before = this._before()
601
602 this.bottom += bottom
603
604 this._after(before)
605
606 return this
607 },
608
609 /**
610 * Adds the given ammount to the right side of this region
611 * @param {Number} right The ammount to add
612 * @return {Region} this
613 */
614 addRight: function(right){
615 var before = this._before()
616
617 this.right += right
618
619 this._after(before)
620
621 return this
622 },
623
624 /**
625 * Minimize the top side.
626 * @return {Region} this
627 */
628 minTop: function(){
629 return this.expand({top: 1})
630 },
631 /**
632 * Minimize the bottom side.
633 * @return {Region} this
634 */
635 maxBottom: function(){
636 return this.expand({bottom: 1})
637 },
638 /**
639 * Minimize the left side.
640 * @return {Region} this
641 */
642 minLeft: function(){
643 return this.expand({left: 1})
644 },
645 /**
646 * Maximize the right side.
647 * @return {Region} this
648 */
649 maxRight: function(){
650 return this.expand({right: 1})
651 },
652
653 /**
654 * Expands this region to the dimensions of the given region, or the document region, if no region is expanded.
655 * But only expand the given sides (any of the four can be expanded).
656 *
657 * @param {Object} directions
658 * @param {Boolean} [directions.top]
659 * @param {Boolean} [directions.bottom]
660 * @param {Boolean} [directions.left]
661 * @param {Boolean} [directions.right]
662 *
663 * @param {Region} [region] the region to expand to, defaults to the document region
664 * @return {Region} this region
665 */
666 expand: function(directions, region){
667 var docRegion = region || REGION.getDocRegion()
668 var list = []
669 var direction
670 var before = this._before()
671
672 for (direction in directions) if ( hasOwn(directions, direction) ) {
673 list.push(direction)
674 }
675
676 copyList(docRegion, this, list)
677
678 this[0] = this.left
679 this[1] = this.top
680
681 this._after(before)
682
683 return this
684 },
685
686 /**
687 * Returns a clone of this region
688 * @return {Region} A new region, with the same position and dimension as this region
689 */
690 clone: function(){
691 return new REGION({
692 top : this.top,
693 left : this.left,
694 right : this.right,
695 bottom : this.bottom
696 })
697 },
698
699 /**
700 * Returns true if this region contains the given point
701 * @param {Number/Object} x the x coordinate of the point
702 * @param {Number} [y] the y coordinate of the point
703 *
704 * @return {Boolean} true if this region constains the given point, false otherwise
705 */
706 containsPoint: function(x, y){
707 if (arguments.length == 1){
708 y = x.y
709 x = x.x
710 }
711
712 return this.left <= x &&
713 x <= this.right &&
714 this.top <= y &&
715 y <= this.bottom
716 },
717
718 /**
719 *
720 * @param region
721 *
722 * @return {Boolean} true if this region contains the given region, false otherwise
723 */
724 containsRegion: function(region){
725 return this.containsPoint(region.left, region.top) &&
726 this.containsPoint(region.right, region.bottom)
727 },
728
729 /**
730 * Returns an object with the difference for {top, bottom} positions betwen this and the given region,
731 *
732 * See {@link #diff}
733 * @param {Region} region The region to use for diff
734 * @return {Object} {top,bottom}
735 */
736 diffHeight: function(region){
737 return this.diff(region, {top: true, bottom: true})
738 },
739
740 /**
741 * Returns an object with the difference for {left, right} positions betwen this and the given region,
742 *
743 * See {@link #diff}
744 * @param {Region} region The region to use for diff
745 * @return {Object} {left,right}
746 */
747 diffWidth: function(region){
748 return this.diff(region, {left: true, right: true})
749 },
750
751 /**
752 * Returns an object with the difference in sizes for the given directions, between this and region
753 *
754 * @param {Region} region The region to use for diff
755 * @param {Object} directions An object with the directions to diff. Can have any of the following keys:
756 * * left
757 * * right
758 * * top
759 * * bottom
760 *
761 * @return {Object} and object with the same keys as the directions object, but the values being the
762 * differences between this region and the given region
763 */
764 diff: function(region, directions){
765 var result = {}
766 var dirName
767
768 for (dirName in directions) if ( hasOwn(directions, dirName) ) {
769 result[dirName] = this[dirName] - region[dirName]
770 }
771
772 return result
773 },
774
775 /**
776 * Returns the position, in {left,top} properties, of this region
777 *
778 * @return {Object} {left,top}
779 */
780 getPosition: function(){
781 return {
782 left: this.left,
783 top : this.top
784 }
785 },
786
787 /**
788 * Returns the point at the given position from this region.
789 *
790 * @param {String} position Any of:
791 *
792 * * 'cx' - See {@link #getPointXCenter}
793 * * 'cy' - See {@link #getPointYCenter}
794 * * 'b' - See {@link #getPointBottom}
795 * * 'bc' - See {@link #getPointBottomCenter}
796 * * 'l' - See {@link #getPointLeft}F
797 * * 'lc' - See {@link #getPointLeftCenter}
798 * * 't' - See {@link #getPointTop}
799 * * 'tc' - See {@link #getPointTopCenter}
800 * * 'r' - See {@link #getPointRight}
801 * * 'rc' - See {@link #getPointRightCenter}
802 * * 'c' - See {@link #getPointCenter}
803 * * 'tl' - See {@link #getPointTopLeft}
804 * * 'bl' - See {@link #getPointBottomLeft}
805 * * 'br' - See {@link #getPointBottomRight}
806 * * 'tr' - See {@link #getPointTopRight}
807 *
808 * @param {Boolean} asLeftTop
809 *
810 * @return {Object} either an object with {x,y} or {left,top} if asLeftTop is true
811 */
812 getPoint: function(position, asLeftTop){
813
814 //<debug>
815 if (!POINT_POSITIONS[position]) {
816 console.warn('The position ', position, ' could not be found! Available options are tl, bl, tr, br, l, r, t, b.');
817 }
818 //</debug>
819
820 var method = 'getPoint' + POINT_POSITIONS[position],
821 result = this[method]()
822
823 if (asLeftTop){
824 return {
825 left : result.x,
826 top : result.y
827 }
828 }
829
830 return result
831 },
832
833 /**
834 * Returns a point with x = null and y being the middle of the left region segment
835 * @return {Object} {x,y}
836 */
837 getPointYCenter: function(){
838 return { x: null, y: this.top + this.getHeight() / 2 }
839 },
840
841 /**
842 * Returns a point with y = null and x being the middle of the top region segment
843 * @return {Object} {x,y}
844 */
845 getPointXCenter: function(){
846 return { x: this.left + this.getWidth() / 2, y: null }
847 },
848
849 /**
850 * Returns a point with x = null and y the region top position on the y axis
851 * @return {Object} {x,y}
852 */
853 getPointTop: function(){
854 return { x: null, y: this.top }
855 },
856
857 /**
858 * Returns a point that is the middle point of the region top segment
859 * @return {Object} {x,y}
860 */
861 getPointTopCenter: function(){
862 return { x: this.left + this.getWidth() / 2, y: this.top }
863 },
864
865 /**
866 * Returns a point that is the top-left point of the region
867 * @return {Object} {x,y}
868 */
869 getPointTopLeft: function(){
870 return { x: this.left, y: this.top}
871 },
872
873 /**
874 * Returns a point that is the top-right point of the region
875 * @return {Object} {x,y}
876 */
877 getPointTopRight: function(){
878 return { x: this.right, y: this.top}
879 },
880
881 /**
882 * Returns a point with x = null and y the region bottom position on the y axis
883 * @return {Object} {x,y}
884 */
885 getPointBottom: function(){
886 return { x: null, y: this.bottom }
887 },
888
889 /**
890 * Returns a point that is the middle point of the region bottom segment
891 * @return {Object} {x,y}
892 */
893 getPointBottomCenter: function(){
894 return { x: this.left + this.getWidth() / 2, y: this.bottom }
895 },
896
897 /**
898 * Returns a point that is the bottom-left point of the region
899 * @return {Object} {x,y}
900 */
901 getPointBottomLeft: function(){
902 return { x: this.left, y: this.bottom}
903 },
904
905 /**
906 * Returns a point that is the bottom-right point of the region
907 * @return {Object} {x,y}
908 */
909 getPointBottomRight: function(){
910 return { x: this.right, y: this.bottom}
911 },
912
913 /**
914 * Returns a point with y = null and x the region left position on the x axis
915 * @return {Object} {x,y}
916 */
917 getPointLeft: function(){
918 return { x: this.left, y: null }
919 },
920
921 /**
922 * Returns a point that is the middle point of the region left segment
923 * @return {Object} {x,y}
924 */
925 getPointLeftCenter: function(){
926 return { x: this.left, y: this.top + this.getHeight() / 2 }
927 },
928
929 /**
930 * Returns a point with y = null and x the region right position on the x axis
931 * @return {Object} {x,y}
932 */
933 getPointRight: function(){
934 return { x: this.right, y: null }
935 },
936
937 /**
938 * Returns a point that is the middle point of the region right segment
939 * @return {Object} {x,y}
940 */
941 getPointRightCenter: function(){
942 return { x: this.right, y: this.top + this.getHeight() / 2 }
943 },
944
945 /**
946 * Returns a point that is the center of the region
947 * @return {Object} {x,y}
948 */
949 getPointCenter: function(){
950 return { x: this.left + this.getWidth() / 2, y: this.top + this.getHeight() / 2 }
951 },
952
953 /**
954 * @return {Number} returns the height of the region
955 */
956 getHeight: function(){
957 return this.bottom - this.top
958 },
959
960 /**
961 * @return {Number} returns the width of the region
962 */
963 getWidth: function(){
964 return this.right - this.left
965 },
966
967 /**
968 * @return {Number} returns the top property of the region
969 */
970 getTop: function(){
971 return this.top
972 },
973
974 /**
975 * @return {Number} returns the left property of the region
976 */
977 getLeft: function(){
978 return this.left
979 },
980
981 /**
982 * @return {Number} returns the bottom property of the region
983 */
984 getBottom: function(){
985 return this.bottom
986 },
987
988 /**
989 * @return {Number} returns the right property of the region
990 */
991 getRight: function(){
992 return this.right
993 },
994
995 /**
996 * Returns the area of the region
997 * @return {Number} the computed area
998 */
999 getArea: function(){
1000 return this.getWidth() * this.getHeight()
1001 },
1002
1003 constrainTo: function(contrain){
1004 var intersect = this.getIntersection(contrain)
1005 var shift
1006
1007 if (!intersect || !intersect.equals(this)){
1008
1009 var contrainWidth = contrain.getWidth(),
1010 contrainHeight = contrain.getHeight()
1011
1012 if (this.getWidth() > contrainWidth){
1013 this.left = contrain.left
1014 this.setWidth(contrainWidth)
1015 }
1016
1017 if (this.getHeight() > contrainHeight){
1018 this.top = contrain.top
1019 this.setHeight(contrainHeight)
1020 }
1021
1022 shift = {}
1023
1024 if (this.right > contrain.right){
1025 shift.left = contrain.right - this.right
1026 }
1027
1028 if (this.bottom > contrain.bottom){
1029 shift.top = contrain.bottom - this.bottom
1030 }
1031
1032 if (this.left < contrain.left){
1033 shift.left = contrain.left - this.left
1034 }
1035
1036 if (this.top < contrain.top){
1037 shift.top = contrain.top - this.top
1038 }
1039
1040 this.shift(shift)
1041
1042 return true
1043 }
1044
1045 return false
1046 },
1047
1048 __IS_REGION: true
1049
1050 /**
1051 * @property {Number} top
1052 */
1053
1054 /**
1055 * @property {Number} right
1056 */
1057
1058 /**
1059 * @property {Number} bottom
1060 */
1061
1062 /**
1063 * @property {Number} left
1064 */
1065
1066 /**
1067 * @property {Number} [0] the top property
1068 */
1069
1070 /**
1071 * @property {Number} [1] the left property
1072 */
1073
1074 /**
1075 * @method getIntersection
1076 * Returns a region that is the intersection of this region and the given region
1077 * @param {Region} region The region to intersect with
1078 * @return {Region} The intersection region
1079 */
1080
1081 /**
1082 * @method getUnion
1083 * Returns a region that is the union of this region with the given region
1084 * @param {Region} region The region to make union with
1085 * @return {Region} The union region. The smallest region that contains both this and the given region.
1086 */
1087
1088 })
1089
1090 Object.defineProperties(REGION.prototype, {
1091 width: {
1092 get: function(){
1093 return this.getWidth()
1094 },
1095 set: function(width){
1096 return this.setWidth(width)
1097 }
1098 },
1099 height: {
1100 get: function(){
1101 return this.getHeight()
1102 },
1103 set: function(height){
1104 return this.setHeight(height)
1105 }
1106 }
1107 })
1108
1109 __webpack_require__(4)(REGION)
1110
1111 module.exports = REGION
1112
1113/***/ },
1114/* 2 */
1115/***/ function(module, exports, __webpack_require__) {
1116
1117 'use strict';
1118
1119 module.exports = function(ctor, superCtor) {
1120 ctor.super_ = superCtor
1121 ctor.prototype = Object.create(superCtor.prototype, {
1122 constructor: {
1123 value : ctor,
1124 enumerable : false,
1125 writable : true,
1126 configurable: true
1127 }
1128 })
1129 }
1130
1131/***/ },
1132/* 3 */
1133/***/ function(module, exports, __webpack_require__) {
1134
1135 'use strict';
1136
1137 /**
1138 * @static
1139 * Returns true if the given region is valid, false otherwise.
1140 * @param {Region} region The region to check
1141 * @return {Boolean} True, if the region is valid, false otherwise.
1142 * A region is valid if
1143 * * left <= right &&
1144 * * top <= bottom
1145 */
1146 module.exports = function validate(region){
1147
1148 var isValid = true
1149
1150 if (region.right < region.left){
1151 isValid = false
1152 region.right = region.left
1153 }
1154
1155 if (region.bottom < region.top){
1156 isValid = false
1157 region.bottom = region.top
1158 }
1159
1160 return isValid
1161 }
1162
1163/***/ },
1164/* 4 */
1165/***/ function(module, exports, __webpack_require__) {
1166
1167 'use strict';
1168
1169 var hasOwn = __webpack_require__(6)
1170 var VALIDATE = __webpack_require__(3)
1171
1172 module.exports = function(REGION){
1173
1174 var MAX = Math.max
1175 var MIN = Math.min
1176
1177 var statics = {
1178 init: function(){
1179 var exportAsNonStatic = {
1180 getIntersection : true,
1181 getIntersectionArea : true,
1182 getIntersectionHeight: true,
1183 getIntersectionWidth : true,
1184 getUnion : true
1185 }
1186 var thisProto = REGION.prototype
1187 var newName
1188
1189 var exportHasOwn = hasOwn(exportAsNonStatic)
1190 var methodName
1191
1192 for (methodName in exportAsNonStatic) if (exportHasOwn(methodName)) {
1193 newName = exportAsNonStatic[methodName]
1194 if (typeof newName != 'string'){
1195 newName = methodName
1196 }
1197
1198 ;(function(proto, methodName, protoMethodName){
1199
1200 proto[methodName] = function(region){
1201 //<debug>
1202 if (!REGION[protoMethodName]){
1203 console.warn('cannot find method ', protoMethodName,' on ', REGION)
1204 }
1205 //</debug>
1206 return REGION[protoMethodName](this, region)
1207 }
1208
1209 })(thisProto, newName, methodName);
1210 }
1211 },
1212
1213 validate: VALIDATE,
1214
1215 /**
1216 * Returns the region corresponding to the documentElement
1217 * @return {Region} The region corresponding to the documentElement. This region is the maximum region visible on the screen.
1218 */
1219 getDocRegion: function(){
1220 return REGION.fromDOM(document.documentElement)
1221 },
1222
1223 from: function(reg){
1224 if (reg.__IS_REGION){
1225 return reg
1226 }
1227
1228 if (typeof document != 'undefined'){
1229 if (typeof HTMLElement != 'undefined' && reg instanceof HTMLElement){
1230 return REGION.fromDOM(reg)
1231 }
1232
1233 if (reg.type && typeof reg.pageX !== 'undefined' && typeof reg.pageY !== 'undefined'){
1234 return REGION.fromEvent(reg)
1235 }
1236 }
1237
1238 return REGION(reg)
1239 },
1240
1241 fromEvent: function(event){
1242 return REGION.fromPoint({
1243 x: event.pageX,
1244 y: event.pageY
1245 })
1246 },
1247
1248 fromDOM: function(dom){
1249 var rect = dom.getBoundingClientRect()
1250 // var docElem = document.documentElement
1251 // var win = window
1252
1253 // var top = rect.top + win.pageYOffset - docElem.clientTop
1254 // var left = rect.left + win.pageXOffset - docElem.clientLeft
1255
1256 return new REGION({
1257 top : rect.top,
1258 left : rect.left,
1259 bottom: rect.bottom,
1260 right : rect.right
1261 })
1262 },
1263
1264 /**
1265 * @static
1266 * Returns a region that is the intersection of the given two regions
1267 * @param {Region} first The first region
1268 * @param {Region} second The second region
1269 * @return {Region/Boolean} The intersection region or false if no intersection found
1270 */
1271 getIntersection: function(first, second){
1272
1273 var area = this.getIntersectionArea(first, second)
1274
1275 if (area){
1276 return new REGION(area)
1277 }
1278
1279 return false
1280 },
1281
1282 getIntersectionWidth: function(first, second){
1283 var minRight = MIN(first.right, second.right)
1284 var maxLeft = MAX(first.left, second.left)
1285
1286 if (maxLeft < minRight){
1287 return minRight - maxLeft
1288 }
1289
1290 return 0
1291 },
1292
1293 getIntersectionHeight: function(first, second){
1294 var maxTop = MAX(first.top, second.top)
1295 var minBottom = MIN(first.bottom,second.bottom)
1296
1297 if (maxTop < minBottom){
1298 return minBottom - maxTop
1299 }
1300
1301 return 0
1302 },
1303
1304 getIntersectionArea: function(first, second){
1305 var maxTop = MAX(first.top, second.top)
1306 var minRight = MIN(first.right, second.right)
1307 var minBottom = MIN(first.bottom,second.bottom)
1308 var maxLeft = MAX(first.left, second.left)
1309
1310 if (
1311 maxTop < minBottom &&
1312 maxLeft < minRight
1313 ){
1314 return {
1315 top : maxTop,
1316 right : minRight,
1317 bottom : minBottom,
1318 left : maxLeft,
1319
1320 width : minRight - maxLeft,
1321 height : minBottom - maxTop
1322 }
1323 }
1324
1325 return false
1326 },
1327
1328 /**
1329 * @static
1330 * Returns a region that is the union of the given two regions
1331 * @param {Region} first The first region
1332 * @param {Region} second The second region
1333 * @return {Region} The union region. The smallest region that contains both given regions.
1334 */
1335 getUnion: function(first, second){
1336 var top = MIN(first.top, second.top)
1337 var right = MAX(first.right, second.right)
1338 var bottom = MAX(first.bottom,second.bottom)
1339 var left = MIN(first.left, second.left)
1340
1341 return new REGION(top, right, bottom, left)
1342 },
1343
1344 /**
1345 * @static
1346 * Returns a region. If the reg argument is a region, returns it, otherwise return a new region built from the reg object.
1347 *
1348 * @param {Region} reg A region or an object with either top, left, bottom, right or
1349 * with top, left, width, height
1350 * @return {Region} A region
1351 */
1352 getRegion: function(reg){
1353 return REGION.from(reg)
1354 },
1355
1356 /**
1357 * Creates a region that corresponds to a point.
1358 *
1359 * @param {Object} xy The point
1360 * @param {Number} xy.x
1361 * @param {Number} xy.y
1362 *
1363 * @return {Region} The new region, with top==xy.y, bottom = xy.y and left==xy.x, right==xy.x
1364 */
1365 fromPoint: function(xy){
1366 return new REGION({
1367 top : xy.y,
1368 bottom : xy.y,
1369 left : xy.x,
1370 right : xy.x
1371 })
1372 }
1373 }
1374
1375 Object.keys(statics).forEach(function(key){
1376 REGION[key] = statics[key]
1377 })
1378
1379 REGION.init()
1380 }
1381
1382/***/ },
1383/* 5 */
1384/***/ function(module, exports, __webpack_require__) {
1385
1386 // Copyright Joyent, Inc. and other Node contributors.
1387 //
1388 // Permission is hereby granted, free of charge, to any person obtaining a
1389 // copy of this software and associated documentation files (the
1390 // "Software"), to deal in the Software without restriction, including
1391 // without limitation the rights to use, copy, modify, merge, publish,
1392 // distribute, sublicense, and/or sell copies of the Software, and to permit
1393 // persons to whom the Software is furnished to do so, subject to the
1394 // following conditions:
1395 //
1396 // The above copyright notice and this permission notice shall be included
1397 // in all copies or substantial portions of the Software.
1398 //
1399 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1400 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1401 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
1402 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
1403 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1404 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
1405 // USE OR OTHER DEALINGS IN THE SOFTWARE.
1406
1407 function EventEmitter() {
1408 this._events = this._events || {};
1409 this._maxListeners = this._maxListeners || undefined;
1410 }
1411 module.exports = EventEmitter;
1412
1413 // Backwards-compat with node 0.10.x
1414 EventEmitter.EventEmitter = EventEmitter;
1415
1416 EventEmitter.prototype._events = undefined;
1417 EventEmitter.prototype._maxListeners = undefined;
1418
1419 // By default EventEmitters will print a warning if more than 10 listeners are
1420 // added to it. This is a useful default which helps finding memory leaks.
1421 EventEmitter.defaultMaxListeners = 10;
1422
1423 // Obviously not all Emitters should be limited to 10. This function allows
1424 // that to be increased. Set to zero for unlimited.
1425 EventEmitter.prototype.setMaxListeners = function(n) {
1426 if (!isNumber(n) || n < 0 || isNaN(n))
1427 throw TypeError('n must be a positive number');
1428 this._maxListeners = n;
1429 return this;
1430 };
1431
1432 EventEmitter.prototype.emit = function(type) {
1433 var er, handler, len, args, i, listeners;
1434
1435 if (!this._events)
1436 this._events = {};
1437
1438 // If there is no 'error' event listener then throw.
1439 if (type === 'error') {
1440 if (!this._events.error ||
1441 (isObject(this._events.error) && !this._events.error.length)) {
1442 er = arguments[1];
1443 if (er instanceof Error) {
1444 throw er; // Unhandled 'error' event
1445 }
1446 throw TypeError('Uncaught, unspecified "error" event.');
1447 }
1448 }
1449
1450 handler = this._events[type];
1451
1452 if (isUndefined(handler))
1453 return false;
1454
1455 if (isFunction(handler)) {
1456 switch (arguments.length) {
1457 // fast cases
1458 case 1:
1459 handler.call(this);
1460 break;
1461 case 2:
1462 handler.call(this, arguments[1]);
1463 break;
1464 case 3:
1465 handler.call(this, arguments[1], arguments[2]);
1466 break;
1467 // slower
1468 default:
1469 len = arguments.length;
1470 args = new Array(len - 1);
1471 for (i = 1; i < len; i++)
1472 args[i - 1] = arguments[i];
1473 handler.apply(this, args);
1474 }
1475 } else if (isObject(handler)) {
1476 len = arguments.length;
1477 args = new Array(len - 1);
1478 for (i = 1; i < len; i++)
1479 args[i - 1] = arguments[i];
1480
1481 listeners = handler.slice();
1482 len = listeners.length;
1483 for (i = 0; i < len; i++)
1484 listeners[i].apply(this, args);
1485 }
1486
1487 return true;
1488 };
1489
1490 EventEmitter.prototype.addListener = function(type, listener) {
1491 var m;
1492
1493 if (!isFunction(listener))
1494 throw TypeError('listener must be a function');
1495
1496 if (!this._events)
1497 this._events = {};
1498
1499 // To avoid recursion in the case that type === "newListener"! Before
1500 // adding it to the listeners, first emit "newListener".
1501 if (this._events.newListener)
1502 this.emit('newListener', type,
1503 isFunction(listener.listener) ?
1504 listener.listener : listener);
1505
1506 if (!this._events[type])
1507 // Optimize the case of one listener. Don't need the extra array object.
1508 this._events[type] = listener;
1509 else if (isObject(this._events[type]))
1510 // If we've already got an array, just append.
1511 this._events[type].push(listener);
1512 else
1513 // Adding the second element, need to change to array.
1514 this._events[type] = [this._events[type], listener];
1515
1516 // Check for listener leak
1517 if (isObject(this._events[type]) && !this._events[type].warned) {
1518 var m;
1519 if (!isUndefined(this._maxListeners)) {
1520 m = this._maxListeners;
1521 } else {
1522 m = EventEmitter.defaultMaxListeners;
1523 }
1524
1525 if (m && m > 0 && this._events[type].length > m) {
1526 this._events[type].warned = true;
1527 console.error('(node) warning: possible EventEmitter memory ' +
1528 'leak detected. %d listeners added. ' +
1529 'Use emitter.setMaxListeners() to increase limit.',
1530 this._events[type].length);
1531 if (typeof console.trace === 'function') {
1532 // not supported in IE 10
1533 console.trace();
1534 }
1535 }
1536 }
1537
1538 return this;
1539 };
1540
1541 EventEmitter.prototype.on = EventEmitter.prototype.addListener;
1542
1543 EventEmitter.prototype.once = function(type, listener) {
1544 if (!isFunction(listener))
1545 throw TypeError('listener must be a function');
1546
1547 var fired = false;
1548
1549 function g() {
1550 this.removeListener(type, g);
1551
1552 if (!fired) {
1553 fired = true;
1554 listener.apply(this, arguments);
1555 }
1556 }
1557
1558 g.listener = listener;
1559 this.on(type, g);
1560
1561 return this;
1562 };
1563
1564 // emits a 'removeListener' event iff the listener was removed
1565 EventEmitter.prototype.removeListener = function(type, listener) {
1566 var list, position, length, i;
1567
1568 if (!isFunction(listener))
1569 throw TypeError('listener must be a function');
1570
1571 if (!this._events || !this._events[type])
1572 return this;
1573
1574 list = this._events[type];
1575 length = list.length;
1576 position = -1;
1577
1578 if (list === listener ||
1579 (isFunction(list.listener) && list.listener === listener)) {
1580 delete this._events[type];
1581 if (this._events.removeListener)
1582 this.emit('removeListener', type, listener);
1583
1584 } else if (isObject(list)) {
1585 for (i = length; i-- > 0;) {
1586 if (list[i] === listener ||
1587 (list[i].listener && list[i].listener === listener)) {
1588 position = i;
1589 break;
1590 }
1591 }
1592
1593 if (position < 0)
1594 return this;
1595
1596 if (list.length === 1) {
1597 list.length = 0;
1598 delete this._events[type];
1599 } else {
1600 list.splice(position, 1);
1601 }
1602
1603 if (this._events.removeListener)
1604 this.emit('removeListener', type, listener);
1605 }
1606
1607 return this;
1608 };
1609
1610 EventEmitter.prototype.removeAllListeners = function(type) {
1611 var key, listeners;
1612
1613 if (!this._events)
1614 return this;
1615
1616 // not listening for removeListener, no need to emit
1617 if (!this._events.removeListener) {
1618 if (arguments.length === 0)
1619 this._events = {};
1620 else if (this._events[type])
1621 delete this._events[type];
1622 return this;
1623 }
1624
1625 // emit removeListener for all listeners on all events
1626 if (arguments.length === 0) {
1627 for (key in this._events) {
1628 if (key === 'removeListener') continue;
1629 this.removeAllListeners(key);
1630 }
1631 this.removeAllListeners('removeListener');
1632 this._events = {};
1633 return this;
1634 }
1635
1636 listeners = this._events[type];
1637
1638 if (isFunction(listeners)) {
1639 this.removeListener(type, listeners);
1640 } else {
1641 // LIFO order
1642 while (listeners.length)
1643 this.removeListener(type, listeners[listeners.length - 1]);
1644 }
1645 delete this._events[type];
1646
1647 return this;
1648 };
1649
1650 EventEmitter.prototype.listeners = function(type) {
1651 var ret;
1652 if (!this._events || !this._events[type])
1653 ret = [];
1654 else if (isFunction(this._events[type]))
1655 ret = [this._events[type]];
1656 else
1657 ret = this._events[type].slice();
1658 return ret;
1659 };
1660
1661 EventEmitter.listenerCount = function(emitter, type) {
1662 var ret;
1663 if (!emitter._events || !emitter._events[type])
1664 ret = 0;
1665 else if (isFunction(emitter._events[type]))
1666 ret = 1;
1667 else
1668 ret = emitter._events[type].length;
1669 return ret;
1670 };
1671
1672 function isFunction(arg) {
1673 return typeof arg === 'function';
1674 }
1675
1676 function isNumber(arg) {
1677 return typeof arg === 'number';
1678 }
1679
1680 function isObject(arg) {
1681 return typeof arg === 'object' && arg !== null;
1682 }
1683
1684 function isUndefined(arg) {
1685 return arg === void 0;
1686 }
1687
1688
1689/***/ },
1690/* 6 */
1691/***/ function(module, exports, __webpack_require__) {
1692
1693 'use strict'
1694
1695 var hasOwn = Object.prototype.hasOwnProperty
1696
1697 function curry(fn, n){
1698
1699 if (typeof n !== 'number'){
1700 n = fn.length
1701 }
1702
1703 function getCurryClosure(prevArgs){
1704
1705 function curryClosure() {
1706
1707 var len = arguments.length
1708 var args = [].concat(prevArgs)
1709
1710 if (len){
1711 args.push.apply(args, arguments)
1712 }
1713
1714 if (args.length < n){
1715 return getCurryClosure(args)
1716 }
1717
1718 return fn.apply(this, args)
1719 }
1720
1721 return curryClosure
1722 }
1723
1724 return getCurryClosure([])
1725 }
1726
1727
1728 module.exports = curry(function(object, property){
1729 return hasOwn.call(object, property)
1730 })
1731
1732/***/ },
1733/* 7 */
1734/***/ function(module, exports, __webpack_require__) {
1735
1736 var getInstantiatorFunction = __webpack_require__(9)
1737
1738 module.exports = function(fn, args){
1739 return getInstantiatorFunction(args.length)(fn, args)
1740 }
1741
1742/***/ },
1743/* 8 */
1744/***/ function(module, exports, __webpack_require__) {
1745
1746 'use strict';
1747
1748 function ToObject(val) {
1749 if (val == null) {
1750 throw new TypeError('Object.assign cannot be called with null or undefined');
1751 }
1752
1753 return Object(val);
1754 }
1755
1756 module.exports = Object.assign || function (target, source) {
1757 var from;
1758 var keys;
1759 var to = ToObject(target);
1760
1761 for (var s = 1; s < arguments.length; s++) {
1762 from = arguments[s];
1763 keys = Object.keys(Object(from));
1764
1765 for (var i = 0; i < keys.length; i++) {
1766 to[keys[i]] = from[keys[i]];
1767 }
1768 }
1769
1770 return to;
1771 };
1772
1773
1774/***/ },
1775/* 9 */
1776/***/ function(module, exports, __webpack_require__) {
1777
1778 module.exports = function(){
1779
1780 'use strict';
1781
1782 var fns = {}
1783
1784 return function(len){
1785
1786 if ( ! fns [len ] ) {
1787
1788 var args = []
1789 var i = 0
1790
1791 for (; i < len; i++ ) {
1792 args.push( 'a[' + i + ']')
1793 }
1794
1795 fns[len] = new Function(
1796 'c',
1797 'a',
1798 'return new c(' + args.join(',') + ')'
1799 )
1800 }
1801
1802 return fns[len]
1803 }
1804
1805 }()
1806
1807/***/ }
1808/******/ ])
1809});