Comparing version 1.2.1 to 2.0.0
1298
index.js
@@ -1,1297 +0,1 @@ | ||
'use strict'; | ||
var hasOwn = require('hasown') | ||
var copyUtils = require('copy-utils') | ||
var copyList = copyUtils.copyList | ||
var F = require('functionally') | ||
var isObject = require('i-s').object | ||
/** | ||
* @class Region | ||
* | ||
* # z.region | ||
* | ||
* The Region class is an abstraction that allows the developer to refer to rectangles on the screen, | ||
* and move them around, make diffs and unions, detect intersections, compute areas, etc. | ||
* | ||
* ## Creating a region | ||
* | ||
* | ||
* | ||
* var region = require('region')({ | ||
* top : 10, | ||
* left : 10, | ||
* bottom: 100, | ||
* right : 100 | ||
* }) | ||
* //this region is a square, 90x90, starting from (10,10) to (100,100) | ||
* | ||
* var second = require('region')({ top: 10, left: 100, right: 200, bottom: 60}) | ||
* var union = region.getUnion(second) | ||
* | ||
* //the "union" region is a union between "region" and "second" | ||
* | ||
* ## Element regions | ||
* | ||
* The {@link Element} class has {@link Element#getRegion} and {@link Element#setRegion} methods, so you can easily | ||
* retrieve and set element size and position. | ||
* | ||
* var bodyElement = Element.select('body'), | ||
* bodyRegion = bodyElement.getRegion() | ||
* | ||
* bodyRegion.setWidth(100).setHeight(200) | ||
* | ||
* //this makes the body just 100px in width and 200px in height | ||
* bodyElement.setRegion(bodyRegion) | ||
* | ||
* //you can even bind an element to a region | ||
* | ||
* var reg = bodyElement.getRegion({bound: true}) | ||
* | ||
* reg.setWidth(200) //also sets the width of the bodyElement | ||
* | ||
*/ | ||
var classy = require('classy') | ||
var EventEmitter = require('zemitter').mixin | ||
var MAX = Math.max, | ||
MIN = Math.min, | ||
POINT_POSITIONS = { | ||
cy: 'YCenter', | ||
cx: 'XCenter', | ||
t : 'Top', | ||
tc: 'TopCenter', | ||
tl: 'TopLeft', | ||
tr: 'TopRight', | ||
b : 'Bottom', | ||
bc: 'BottomCenter', | ||
bl: 'BottomLeft', | ||
br: 'BottomRight', | ||
l : 'Left', | ||
lc: 'LeftCenter', | ||
r : 'Right', | ||
rc: 'RightCenter', | ||
c : 'Center' | ||
} | ||
var REGION = classy.define({ | ||
forceInstance: true, | ||
mixins: [ | ||
EventEmitter | ||
], | ||
statics: { | ||
init: function(){ | ||
var exportAsNonStatic = { | ||
getIntersection : true, | ||
getIntersectionArea : true, | ||
getIntersectionHeight: true, | ||
getIntersectionWidth : true, | ||
getUnion : true | ||
} | ||
var thisProto = this.prototype | ||
var newName | ||
var exportHasOwn = hasOwn(exportAsNonStatic) | ||
var methodName | ||
for (methodName in exportAsNonStatic) if (exportHasOwn(methodName)) { | ||
newName = exportAsNonStatic[methodName] | ||
if (typeof newName != 'string'){ | ||
newName = methodName | ||
} | ||
(function(proto, methodName, protoMethodName){ | ||
proto[methodName] = function(region){ | ||
//<debug> | ||
if (!this.$ownClass[protoMethodName]){ | ||
console.warn('cannot find method ', protoMethodName,' on ', this.$ownClass) | ||
} | ||
//</debug> | ||
return this.$ownClass[protoMethodName](this, region) | ||
} | ||
})(thisProto, newName, methodName) | ||
} | ||
}, | ||
/** | ||
* @static | ||
* Returns true if the given region is valid, false otherwise. | ||
* @param {Region} region The region to check | ||
* @return {Boolean} True, if the region is valid, false otherwise. | ||
* A region is valid if | ||
* * left <= right && | ||
* * top <= bottom | ||
*/ | ||
validate: function(region){ | ||
var isValid = true | ||
if (region.right < region.left){ | ||
isValid = false | ||
region.right = region.left | ||
} | ||
if (region.bottom < region.top){ | ||
isValid = false | ||
region.bottom = region.top | ||
} | ||
return isValid | ||
}, | ||
/** | ||
* Returns the region corresponding to the documentElement | ||
* @return {Region} The region corresponding to the documentElement. This region is the maximum region visible on the screen. | ||
*/ | ||
getDocRegion: function(){ | ||
return REGION.fromDOM(document.documentElement) | ||
}, | ||
from: function(reg){ | ||
if (reg.__IS_REGION){ | ||
return reg | ||
} | ||
if (typeof document){ | ||
if (typeof HTMLElement != 'undefined' && reg instanceof HTMLElement){ | ||
return REGION.fromDOM(reg) | ||
} | ||
if (reg.type && reg.pageX != undefined && reg.pageY != undefined){ | ||
return REGION.fromEvent(reg) | ||
} | ||
} | ||
return REGION(reg) | ||
}, | ||
fromEvent: function(event){ | ||
return REGION.fromPoint({ | ||
x: event.pageX, | ||
y: event.pageY | ||
}) | ||
}, | ||
fromDOM: function(dom){ | ||
var rect = dom.getBoundingClientRect() | ||
var docElem = document.documentElement | ||
var win = window | ||
var top = rect.top + win.pageYOffset - docElem.clientTop | ||
var left = rect.left + win.pageXOffset - docElem.clientLeft | ||
return new REGION({ | ||
top : rect.top, | ||
left : rect.left, | ||
bottom: rect.bottom, | ||
right : rect.right | ||
}) | ||
}, | ||
/** | ||
* @static | ||
* Returns a region that is the intersection of the given two regions | ||
* @param {Region} first The first region | ||
* @param {Region} second The second region | ||
* @return {Region/Boolean} The intersection region or false if no intersection found | ||
*/ | ||
getIntersection: function(first, second){ | ||
var area = this.getIntersectionArea(first, second) | ||
if (area){ | ||
return new REGION(area) | ||
} | ||
return false | ||
}, | ||
getIntersectionWidth: function(first, second){ | ||
var minRight = MIN(first.right, second.right) | ||
var maxLeft = MAX(first.left, second.left) | ||
if (maxLeft < minRight){ | ||
return minRight - maxLeft | ||
} | ||
return 0 | ||
}, | ||
getIntersectionHeight: function(first, second){ | ||
var maxTop = MAX(first.top, second.top) | ||
var minBottom = MIN(first.bottom,second.bottom) | ||
if (maxTop < minBottom){ | ||
return minBottom - maxTop | ||
} | ||
return 0 | ||
}, | ||
getIntersectionArea: function(first, second){ | ||
var maxTop = MAX(first.top, second.top) | ||
var minRight = MIN(first.right, second.right) | ||
var minBottom = MIN(first.bottom,second.bottom) | ||
var maxLeft = MAX(first.left, second.left) | ||
if ( | ||
maxTop < minBottom && | ||
maxLeft < minRight | ||
){ | ||
return { | ||
top : maxTop, | ||
right : minRight, | ||
bottom : minBottom, | ||
left : maxLeft, | ||
width : minRight - maxLeft, | ||
height : minBottom - maxTop | ||
} | ||
} | ||
return false | ||
}, | ||
/** | ||
* @static | ||
* Returns a region that is the union of the given two regions | ||
* @param {Region} first The first region | ||
* @param {Region} second The second region | ||
* @return {Region} The union region. The smallest region that contains both given regions. | ||
*/ | ||
getUnion: function(first, second){ | ||
var top = MIN(first.top, second.top) | ||
var right = MAX(first.right, second.right) | ||
var bottom = MAX(first.bottom,second.bottom) | ||
var left = MIN(first.left, second.left) | ||
return new REGION(top, right, bottom, left) | ||
}, | ||
/** | ||
* @static | ||
* Returns a region. If the reg argument is a region, returns it, otherwise return a new region built from the reg object. | ||
* | ||
* @param {Region} reg A region or an object with either top, left, bottom, right or | ||
* with top, left, width, height | ||
* @return {Region} A region | ||
*/ | ||
getRegion: function(reg){ | ||
return REGION.from(reg) | ||
}, | ||
/** | ||
* Creates a region that corresponds to a point. | ||
* | ||
* @param {Object} xy The point | ||
* @param {Number} xy.x | ||
* @param {Number} xy.y | ||
* | ||
* @return {Region} The new region, with top==xy.y, bottom = xy.y and left==xy.x, right==xy.x | ||
*/ | ||
fromPoint: function(xy){ | ||
return new REGION({ | ||
top : xy.y, | ||
bottom : xy.y, | ||
left : xy.x, | ||
right : xy.x | ||
}) | ||
} | ||
}, | ||
/** | ||
* @cfg {Boolean} emitChangeEvents If this is set to true, the region | ||
* will emit 'changesize' and 'changeposition' whenever the size or the position changs | ||
*/ | ||
emitChangeEvents: false, | ||
/** | ||
* @cfg {Number} changeEventsBuffer If {@link #emitChangeEvents} is true, the change events will be emitted in a buffered manner, | ||
* if this value is greater than 0 | ||
*/ | ||
changeEventsBuffer: 0, | ||
/** | ||
* Returns this region, or a clone of this region | ||
* @param {Boolean} [clone] If true, this method will return a clone of this region | ||
* @return {Region} This region, or a clone of this | ||
*/ | ||
getRegion: function(clone){ | ||
return clone? | ||
this.clone(): | ||
this | ||
}, | ||
/** | ||
* Sets the properties of this region to those of the given region | ||
* @param {Region/Object} reg The region or object to use for setting properties of this region | ||
* @return {Region} this | ||
*/ | ||
setRegion: function(reg){ | ||
if (reg instanceof REGION){ | ||
this.set(reg.get()) | ||
} else { | ||
this.set(reg) | ||
} | ||
return this | ||
}, | ||
/** | ||
* Returns true if this region is valid, false otherwise | ||
* | ||
* @param {Region} region The region to check | ||
* @return {Boolean} True, if the region is valid, false otherwise. | ||
* A region is valid if | ||
* * left <= right && | ||
* * top <= bottom | ||
*/ | ||
validate: function(){ | ||
return REGION.validate(this) | ||
}, | ||
_before: function(){ | ||
if (this.emitChangeEvents){ | ||
return copyList(this, {}, ['left','top','bottom','right']) | ||
} | ||
}, | ||
_after: function(before){ | ||
if (this.emitChangeEvents){ | ||
if(this.top != before.top || this.left != before.left) { | ||
this.emitPositionChange() | ||
} | ||
if(this.right != before.right || this.bottom != before.bottom) { | ||
this.emitSizeChange() | ||
} | ||
} | ||
}, | ||
notifyPositionChange: function(){ | ||
this.emit('changeposition', this) | ||
}, | ||
emitPositionChange: function(){ | ||
if (this.changeEventsBuffer){ | ||
if (!this.emitPositionChangeBuffered){ | ||
this.emitPositionChangeBuffered = F.buffer(this.notifyPositionChange, changeEventsBuffer) | ||
} | ||
this.emitPositionChangeBuffered() | ||
} | ||
this.notifyPositionChange() | ||
}, | ||
notifySizeChange: function(){ | ||
this.emit('changesize', this) | ||
}, | ||
emitSizeChange: function(){ | ||
if (this.changeEventsBuffer){ | ||
if (!this.emitSizeChangeBuffered){ | ||
this.emitSizeChangeBuffered = F.buffer(this.notifySizeChange, changeEventsBuffer) | ||
} | ||
this.emitSizeChangeBuffered() | ||
} | ||
this.notifySizeChange() | ||
}, | ||
/** | ||
* Add the given amounts to each specified side. Example | ||
* | ||
* region.add({ | ||
* top: 50, //add 50 px to the top side | ||
* bottom: -100 //substract 100 px from the bottom side | ||
* }) | ||
* | ||
* @param {Object} directions | ||
* @param {Number} [directions.top] | ||
* @param {Number} [directions.left] | ||
* @param {Number} [directions.bottom] | ||
* @param {Number} [directions.right] | ||
* | ||
* @return {Region} this | ||
*/ | ||
add: function(directions){ | ||
var before = this._before() | ||
var direction | ||
for (direction in directions) if ( hasOwn(directions, direction) ) { | ||
this[direction] += directions[direction] | ||
} | ||
this[0] = this.left | ||
this[1] = this.top | ||
this._after(before) | ||
return this | ||
}, | ||
/** | ||
* The same as {@link #add}, but substracts the given values | ||
* @param {Object} directions | ||
* @param {Number} [directions.top] | ||
* @param {Number} [directions.left] | ||
* @param {Number} [directions.bottom] | ||
* @param {Number} [directions.right] | ||
* | ||
* @return {Region} this | ||
*/ | ||
substract: function(directions){ | ||
var before = this._before() | ||
var direction | ||
for (direction in directions) if (hasOwn(directions, direction) ) { | ||
this[direction] -= directions[direction] | ||
} | ||
this[0] = this.left | ||
this[1] = this.top | ||
this._after(before) | ||
return this | ||
}, | ||
/** | ||
* Retrieves the size of the region. | ||
* @return {Object} An object with {width, height}, corresponding to the width and height of the region | ||
*/ | ||
getSize: function(){ | ||
return { | ||
width : this.getWidth(), | ||
height : this.getHeight() | ||
} | ||
}, | ||
/** | ||
* Move the region to the given position and keeps the region width and height. | ||
* | ||
* @param {Object} position An object with {top, left} properties. The values in {top,left} are used to move the region by the given amounts. | ||
* @param {Number} [position.left] | ||
* @param {Number} [position.top] | ||
* | ||
* @return {Region} this | ||
*/ | ||
setPosition: function(position){ | ||
var width = this.getWidth(), | ||
height = this.getHeight() | ||
if (position.left){ | ||
position.right = position.left + width | ||
} | ||
if (position.top){ | ||
position.bottom = position.top + height | ||
} | ||
return this.set(position) | ||
}, | ||
/** | ||
* Sets both the height and the width of this region to the given size. | ||
* | ||
* @param {Number} size The new size for the region | ||
* @return {Region} this | ||
*/ | ||
setSize: function(size){ | ||
if (size.height && size.width){ | ||
return this.set({ | ||
right : this.left + size.width, | ||
bottom : this.top + size.height | ||
}) | ||
} | ||
if (size.width){ | ||
this.setWidth(size.width) | ||
} | ||
if (size.height){ | ||
this.setHeight(size.height) | ||
} | ||
return this | ||
}, | ||
get width(){ | ||
return this.getWidth() | ||
}, | ||
set width(width){ | ||
return this.setWidth(width) | ||
}, | ||
/** | ||
* @chainable | ||
* | ||
* Sets the width of this region | ||
* @param {Number} width The new width for this region | ||
* @return {Region} this | ||
*/ | ||
setWidth: function(width){ | ||
return this.set({ | ||
right: this.left + width | ||
}) | ||
}, | ||
get height(){ | ||
return this.getHeight() | ||
}, | ||
set height(height){ | ||
return this.setHeight(height) | ||
}, | ||
/** | ||
* @chainable | ||
* | ||
* Sets the height of this region | ||
* @param {Number} height The new height for this region | ||
* @return {Region} this | ||
*/ | ||
setHeight: function(height){ | ||
return this.set({ | ||
bottom: this.top + height | ||
}) | ||
}, | ||
/** | ||
* Sets the given properties on this region | ||
* | ||
* @param {Object} directions an object containing top, left, and EITHER bottom, right OR width, height | ||
* @param {Number} [directions.top] | ||
* @param {Number} [directions.left] | ||
* | ||
* @param {Number} [directions.bottom] | ||
* @param {Number} [directions.right] | ||
* | ||
* @param {Number} [directions.width] | ||
* @param {Number} [directions.height] | ||
* | ||
* | ||
* @return {Region} this | ||
*/ | ||
set: function(directions){ | ||
var before = this._before() | ||
copyList(directions, this, ['left','top','bottom','right']) | ||
if (directions.bottom == null && directions.height != null){ | ||
this.bottom = this.top + directions.height | ||
} | ||
if (directions.right == null && directions.width != null){ | ||
this.right = this.left + directions.width | ||
} | ||
this[0] = this.left | ||
this[1] = this.top | ||
this._after(before) | ||
return this | ||
}, | ||
/** | ||
* Retrieves the given property from this region. If no property is given, return an object | ||
* with {left, top, right, bottom} | ||
* | ||
* @param {String} [dir] the property to retrieve from this region | ||
* @return {Number/Object} | ||
*/ | ||
get: function(dir){ | ||
return dir? this[dir]: | ||
copyList(this, {}, ['left','right','top','bottom']) | ||
}, | ||
/** | ||
* Shifts this region to either top, or left or both. | ||
* 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 | ||
* to bottom and right | ||
* | ||
* @param {Object} directions | ||
* @param {Number} [directions.top] | ||
* @param {Number} [directions.left] | ||
* | ||
* @return {Region} this | ||
*/ | ||
shift: function(directions){ | ||
var before = this._before() | ||
if (directions.top){ | ||
this.top += directions.top | ||
this.bottom += directions.top | ||
} | ||
if (directions.left){ | ||
this.left += directions.left | ||
this.right += directions.left | ||
} | ||
this[0] = this.left | ||
this[1] = this.top | ||
this._after(before) | ||
return this | ||
}, | ||
/** | ||
* Same as {@link #shift}, but substracts the given values | ||
* @chainable | ||
* | ||
* @param {Object} directions | ||
* @param {Number} [directions.top] | ||
* @param {Number} [directions.left] | ||
* | ||
* @return {Region} this | ||
*/ | ||
unshift: function(directions){ | ||
if (directions.top){ | ||
directions.top *= -1 | ||
} | ||
if (directions.left){ | ||
directions.left *= -1 | ||
} | ||
return this.shift(directions) | ||
}, | ||
/** | ||
* Compare this region and the given region. Return true if they have all the same size and position | ||
* @param {Region} region The region to compare with | ||
* @return {Boolean} True if this and region have same size and position | ||
*/ | ||
equals: function(region){ | ||
return this.equalsPosition(region) && this.equalsSize(region) | ||
}, | ||
/** | ||
* Returns true if this region has the same bottom,right properties as the given region | ||
* @param {Region/Object} size The region to compare against | ||
* @return {Boolean} true if this region is the same size as the given size | ||
*/ | ||
equalsSize: function(size){ | ||
var isInstance = size instanceof REGION | ||
var s = { | ||
width: size.width == null && isInstance? | ||
size.getWidth(): | ||
size.width, | ||
height: size.height == null && isInstance? | ||
size.getHeight(): | ||
size.height | ||
} | ||
return this.getWidth() == s.width && this.getHeight() == s.height | ||
}, | ||
/** | ||
* Returns true if this region has the same top,left properties as the given region | ||
* @param {Region} region The region to compare against | ||
* @return {Boolean} true if this.top == region.top and this.left == region.left | ||
*/ | ||
equalsPosition: function(region){ | ||
return this.top == region.top && this.left == region.left | ||
}, | ||
/** | ||
* Adds the given ammount to the left side of this region | ||
* @param {Number} left The ammount to add | ||
* @return {Region} this | ||
*/ | ||
addLeft: function(left){ | ||
var before = this._before() | ||
this.left = this[0] = this.left + left | ||
this._after(before) | ||
return this | ||
}, | ||
/** | ||
* Adds the given ammount to the top side of this region | ||
* @param {Number} top The ammount to add | ||
* @return {Region} this | ||
*/ | ||
addTop: function(top){ | ||
var before = this._before() | ||
this.top = this[1] = this.top + top | ||
this._after(before) | ||
return this | ||
}, | ||
/** | ||
* Adds the given ammount to the bottom side of this region | ||
* @param {Number} bottom The ammount to add | ||
* @return {Region} this | ||
*/ | ||
addBottom: function(bottom){ | ||
var before = this._before() | ||
this.bottom += bottom | ||
this._after(before) | ||
return this | ||
}, | ||
/** | ||
* Adds the given ammount to the right side of this region | ||
* @param {Number} right The ammount to add | ||
* @return {Region} this | ||
*/ | ||
addRight: function(right){ | ||
var before = this._before() | ||
this.right += right | ||
this._after(before) | ||
return this | ||
}, | ||
/** | ||
* Minimize the top side. | ||
* @return {Region} this | ||
*/ | ||
minTop: function(){ | ||
return this.expand({top: 1}) | ||
}, | ||
/** | ||
* Minimize the bottom side. | ||
* @return {Region} this | ||
*/ | ||
maxBottom: function(){ | ||
return this.expand({bottom: 1}) | ||
}, | ||
/** | ||
* Minimize the left side. | ||
* @return {Region} this | ||
*/ | ||
minLeft: function(){ | ||
return this.expand({left: 1}) | ||
}, | ||
/** | ||
* Maximize the right side. | ||
* @return {Region} this | ||
*/ | ||
maxRight: function(){ | ||
return this.expand({right: 1}) | ||
}, | ||
/** | ||
* Expands this region to the dimensions of the given region, or the document region, if no region is expanded. | ||
* But only expand the given sides (any of the four can be expanded). | ||
* | ||
* @param {Object} directions | ||
* @param {Boolean} [directions.top] | ||
* @param {Boolean} [directions.bottom] | ||
* @param {Boolean} [directions.left] | ||
* @param {Boolean} [directions.right] | ||
* | ||
* @param {Region} [region] the region to expand to, defaults to the document region | ||
* @return {Region} this region | ||
*/ | ||
expand: function(directions, region){ | ||
var docRegion = region || REGION.getDocRegion(), | ||
list = [], | ||
direction, | ||
before = this._before() | ||
for (direction in directions) if ( hasOwn(directions, direction) ) { | ||
list.push(direction) | ||
} | ||
copyList(docRegion, this, list) | ||
this[0] = this.left | ||
this[1] = this.top | ||
this._after(before) | ||
return this | ||
}, | ||
/** | ||
* Returns a clone of this region | ||
* @return {Region} A new region, with the same position and dimension as this region | ||
*/ | ||
clone: function(){ | ||
return new REGION({ | ||
top : this.top, | ||
left : this.left, | ||
right : this.right, | ||
bottom : this.bottom | ||
}) | ||
}, | ||
/** | ||
* Returns true if this region contains the given point | ||
* @param {Number/Object} x the x coordinate of the point | ||
* @param {Number} [y] the y coordinate of the point | ||
* | ||
* @return {Boolean} true if this region constains the given point, false otherwise | ||
*/ | ||
containsPoint: function(x, y){ | ||
if (arguments.length == 1){ | ||
y = x.y | ||
x = x.x | ||
} | ||
return this.left <= x && | ||
x <= this.right && | ||
this.top <= y && | ||
y <= this.bottom | ||
}, | ||
/** | ||
* | ||
* @param region | ||
* | ||
* @return {Boolean} true if this region contains the given region, false otherwise | ||
*/ | ||
containsRegion: function(region){ | ||
return this.containsPoint(region.left, region.top) && | ||
this.containsPoint(region.right, region.bottom) | ||
}, | ||
/** | ||
* Returns an object with the difference for {top, bottom} positions betwen this and the given region, | ||
* | ||
* See {@link #diff} | ||
* @param {Region} region The region to use for diff | ||
* @return {Object} {top,bottom} | ||
*/ | ||
diffHeight: function(region){ | ||
return this.diff(region, {top: true, bottom: true}) | ||
}, | ||
/** | ||
* Returns an object with the difference for {left, right} positions betwen this and the given region, | ||
* | ||
* See {@link #diff} | ||
* @param {Region} region The region to use for diff | ||
* @return {Object} {left,right} | ||
*/ | ||
diffWidth: function(region){ | ||
return this.diff(region, {left: true, right: true}) | ||
}, | ||
/** | ||
* Returns an object with the difference in sizes for the given directions, between this and region | ||
* | ||
* @param {Region} region The region to use for diff | ||
* @param {Object} directions An object with the directions to diff. Can have any of the following keys: | ||
* * left | ||
* * right | ||
* * top | ||
* * bottom | ||
* | ||
* @return {Object} and object with the same keys as the directions object, but the values being the | ||
* differences between this region and the given region | ||
*/ | ||
diff: function(region, directions){ | ||
var result = {} | ||
var dirName | ||
for (dirName in directions) if ( hasOwn(directions, dirName) ) { | ||
result[dirName] = this[dirName] - region[dirName] | ||
} | ||
return result | ||
}, | ||
/** | ||
* Returns the position, in {left,top} properties, of this region | ||
* | ||
* @return {Object} {left,top} | ||
*/ | ||
getPosition: function(){ | ||
return { | ||
left: this.left, | ||
top : this.top | ||
} | ||
}, | ||
/** | ||
* Returns the point at the given position from this region. | ||
* | ||
* @param {String} position Any of: | ||
* | ||
* * 'cx' - See {@link #getPointXCenter} | ||
* * 'cy' - See {@link #getPointYCenter} | ||
* * 'b' - See {@link #getPointBottom} | ||
* * 'bc' - See {@link #getPointBottomCenter} | ||
* * 'l' - See {@link #getPointLeft} | ||
* * 'lc' - See {@link #getPointLeftCenter} | ||
* * 't' - See {@link #getPointTop} | ||
* * 'tc' - See {@link #getPointTopCenter} | ||
* * 'r' - See {@link #getPointRight} | ||
* * 'rc' - See {@link #getPointRightCenter} | ||
* * 'c' - See {@link #getPointCenter} | ||
* * 'tl' - See {@link #getPointTopLeft} | ||
* * 'bl' - See {@link #getPointBottomLeft} | ||
* * 'br' - See {@link #getPointBottomRight} | ||
* * 'tr' - See {@link #getPointTopRight} | ||
* | ||
* @param {Boolean} asLeftTop | ||
* | ||
* @return {Object} either an object with {x,y} or {left,top} if asLeftTop is true | ||
*/ | ||
getPoint: function(position, asLeftTop){ | ||
//<debug> | ||
if (!POINT_POSITIONS[position]) { | ||
console.warn('The position ', position, ' could not be found! Available options are tl, bl, tr, br, l, r, t, b.'); | ||
} | ||
//</debug> | ||
var method = 'getPoint' + POINT_POSITIONS[position], | ||
result = this[method]() | ||
if (asLeftTop){ | ||
return { | ||
left : result.x, | ||
top : result.y | ||
} | ||
} | ||
return result | ||
}, | ||
/** | ||
* Returns a point with x = null and y being the middle of the left region segment | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointYCenter: function(){ | ||
return { x: null, y: this.top + this.getHeight() / 2 } | ||
}, | ||
/** | ||
* Returns a point with y = null and x being the middle of the top region segment | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointXCenter: function(){ | ||
return { x: this.left + this.getWidth() / 2, y: null } | ||
}, | ||
/** | ||
* Returns a point with x = null and y the region top position on the y axis | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointTop: function(){ | ||
return { x: null, y: this.top } | ||
}, | ||
/** | ||
* Returns a point that is the middle point of the region top segment | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointTopCenter: function(){ | ||
return { x: this.left + this.getWidth() / 2, y: this.top } | ||
}, | ||
/** | ||
* Returns a point that is the top-left point of the region | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointTopLeft: function(){ | ||
return { x: this.left, y: this.top} | ||
}, | ||
/** | ||
* Returns a point that is the top-right point of the region | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointTopRight: function(){ | ||
return { x: this.right, y: this.top} | ||
}, | ||
/** | ||
* Returns a point with x = null and y the region bottom position on the y axis | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointBottom: function(){ | ||
return { x: null, y: this.bottom } | ||
}, | ||
/** | ||
* Returns a point that is the middle point of the region bottom segment | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointBottomCenter: function(){ | ||
return { x: this.left + this.getWidth() / 2, y: this.bottom } | ||
}, | ||
/** | ||
* Returns a point that is the bottom-left point of the region | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointBottomLeft: function(){ | ||
return { x: this.left, y: this.bottom} | ||
}, | ||
/** | ||
* Returns a point that is the bottom-right point of the region | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointBottomRight: function(){ | ||
return { x: this.right, y: this.bottom} | ||
}, | ||
/** | ||
* Returns a point with y = null and x the region left position on the x axis | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointLeft: function(){ | ||
return { x: this.left, y: null } | ||
}, | ||
/** | ||
* Returns a point that is the middle point of the region left segment | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointLeftCenter: function(){ | ||
return { x: this.left, y: this.top + this.getHeight() / 2 } | ||
}, | ||
/** | ||
* Returns a point with y = null and x the region right position on the x axis | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointRight: function(){ | ||
return { x: this.right, y: null } | ||
}, | ||
/** | ||
* Returns a point that is the middle point of the region right segment | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointRightCenter: function(){ | ||
return { x: this.right, y: this.top + this.getHeight() / 2 } | ||
}, | ||
/** | ||
* Returns a point that is the center of the region | ||
* @return {Object} {x,y} | ||
*/ | ||
getPointCenter: function(){ | ||
return { x: this.left + this.getWidth() / 2, y: this.top + this.getHeight() / 2 } | ||
}, | ||
/** | ||
* @return {Number} returns the height of the region | ||
*/ | ||
getHeight: function(){ | ||
return this.bottom - this.top | ||
}, | ||
/** | ||
* @return {Number} returns the width of the region | ||
*/ | ||
getWidth: function(){ | ||
return this.right - this.left | ||
}, | ||
/** | ||
* @return {Number} returns the top property of the region | ||
*/ | ||
getTop: function(){ | ||
return this.top | ||
}, | ||
/** | ||
* @return {Number} returns the left property of the region | ||
*/ | ||
getLeft: function(){ | ||
return this.left | ||
}, | ||
/** | ||
* @return {Number} returns the bottom property of the region | ||
*/ | ||
getBottom: function(){ | ||
return this.bottom | ||
}, | ||
/** | ||
* @return {Number} returns the right property of the region | ||
*/ | ||
getRight: function(){ | ||
return this.right | ||
}, | ||
/** | ||
* Returns the area of the region | ||
* @return {Number} the computed area | ||
*/ | ||
getArea: function(){ | ||
return this.getWidth() * this.getHeight() | ||
}, | ||
constrainTo: function(contrain){ | ||
var intersect = this.getIntersection(contrain), | ||
shift | ||
if (!intersect || !intersect.equals(this)){ | ||
var contrainWidth = contrain.getWidth(), | ||
contrainHeight = contrain.getHeight(), | ||
shift = {} | ||
if (this.getWidth() > contrainWidth){ | ||
this.left = contrain.left | ||
this.setWidth(contrainWidth) | ||
} | ||
if (this.getHeight() > contrainHeight){ | ||
this.top = contrain.top | ||
this.setHeight(contrainHeight) | ||
} | ||
shift = {} | ||
if (this.right > contrain.right){ | ||
shift.left = contrain.right - this.right | ||
} | ||
if (this.bottom > contrain.bottom){ | ||
shift.top = contrain.bottom - this.bottom | ||
} | ||
if (this.left < contrain.left){ | ||
shift.left = contrain.left - this.left | ||
} | ||
if (this.top < contrain.top){ | ||
shift.top = contrain.top - this.top | ||
} | ||
this.shift(shift) | ||
return true | ||
} | ||
return false | ||
}, | ||
/** | ||
* @constructor | ||
* | ||
* Construct a new Region. | ||
* | ||
* Example: | ||
* | ||
* var r = root.create('z.region', { top: 10, left: 20, bottom: 100, right: 200 }) | ||
* | ||
* //or, the same, but with numbers | ||
* | ||
* r = root.create('z.region', 10, 200, 100, 20) | ||
* | ||
* //or, with width and height | ||
* | ||
* r = root.create('z.region', { top: 10, left: 20, width: 180, height: 90}) | ||
* | ||
* @param {Number|Object} top The top pixel position, or an object with top, left, bottom, right properties. If an object is passed, | ||
* instead of having bottom and right, it can have width and height. | ||
* | ||
* @param {Number} right The right pixel position | ||
* @param {Number} bottom The bottom pixel position | ||
* @param {Number} left The left pixel position | ||
* | ||
* @return {Region} this | ||
*/ | ||
init: function(top, right, bottom, left){ | ||
if (isObject(top)){ | ||
copyList(top, this, ['top','right','bottom','left']) | ||
if (top.bottom == null && top.height != null){ | ||
this.bottom = this.top + top.height | ||
} | ||
if (top.right == null && top.width != null){ | ||
this.right = this.left + top.width | ||
} | ||
if (top.emitChangeEvents){ | ||
this.emitChangeEvents = top.emitChangeEvents | ||
} | ||
} else { | ||
this.top = top | ||
this.right = right | ||
this.bottom = bottom | ||
this.left = left | ||
} | ||
this[0] = this.left | ||
this[1] = this.top | ||
REGION.validate(this) | ||
}, | ||
__IS_REGION: true | ||
/** | ||
* @property {Number} top | ||
*/ | ||
/** | ||
* @property {Number} right | ||
*/ | ||
/** | ||
* @property {Number} bottom | ||
*/ | ||
/** | ||
* @property {Number} left | ||
*/ | ||
/** | ||
* @property {Number} [0] the top property | ||
*/ | ||
/** | ||
* @property {Number} [1] the left property | ||
*/ | ||
/** | ||
* @method getIntersection | ||
* Returns a region that is the intersection of this region and the given region | ||
* @param {Region} region The region to intersect with | ||
* @return {Region} The intersection region | ||
*/ | ||
/** | ||
* @method getUnion | ||
* Returns a region that is the union of this region with the given region | ||
* @param {Region} region The region to make union with | ||
* @return {Region} The union region. The smallest region that contains both this and the given region. | ||
*/ | ||
}) | ||
// require('./align')(REGION) | ||
module.exports = REGION | ||
module.exports = require('./src') |
{ | ||
"name": "region", | ||
"version": "1.2.1", | ||
"version": "2.0.0", | ||
"description": "A helper to work with rectangular regions in the DOM", | ||
@@ -9,7 +9,12 @@ "main": "index.js", | ||
"test-w": "make test-w", | ||
"test-debug": "mocha --debug-brk" | ||
"test-debug": "mocha --debug-brk", | ||
"dist": "./node_modules/.bin/webpack --progress --colors --config dist.config.js", | ||
"dist.min": "./node_modules/.bin/webpack --progress --colors --optimize-minimize --optimize-occurence-order --optimize-dedupe --config dist.min.config.js", | ||
"build": "npm run dist && npm run dist.min" | ||
}, | ||
"devDependencies": { | ||
"mocha": "~1.21.0", | ||
"should": "~4.0.4" | ||
"should": "~4.0.4", | ||
"webpack": "^1.4.13", | ||
"webpack-dev-server": "^1.6.5" | ||
}, | ||
@@ -37,9 +42,7 @@ "repository": { | ||
"dependencies": { | ||
"classy": "^1.4.10", | ||
"copy-utils": "^1.0.0", | ||
"functionally": "~0.x.x", | ||
"hasown": "~1.x.x", | ||
"i-s": "~1.x.x", | ||
"zemitter": "~0.x.x" | ||
"newify": "^1.1.9" | ||
} | ||
} |
@@ -6,6 +6,7 @@ describe('Region equal', function(){ | ||
it('size should return fine', function(){ | ||
debugger | ||
var r = Region({ | ||
top: 10, | ||
left: 10, | ||
width: 10, | ||
top : 10, | ||
left : 10, | ||
width : 10, | ||
height: 10 | ||
@@ -15,3 +16,3 @@ }) | ||
r.equalsSize({ | ||
width: 10, | ||
width : 10, | ||
height: 10 | ||
@@ -18,0 +19,0 @@ }) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
177722
4
23
3522
4
1
+ Addednewify@^1.1.9
- Removedclassy@^1.4.10
- Removedfunctionally@~0.x.x
- Removedzemitter@~0.x.x
- Removedclassy@1.4.10(transitive)
- Removedfn-queue@0.2.1(transitive)
- Removedfunctionally@0.6.2(transitive)
- Removedzemitter@0.2.5(transitive)