(function() {
/**
* @typedef {Help4.control2.hotspot.Hotspot.Params} Help4.control2.hotspot.Rectangle.Params
* @property {Help4.control2.AreaXYWH} [rect = {x: 0, y: 0, w: 0, h: 0}] - the assigned elements rect
* @property {Help4.control2.SizeWidthHeight} [delta = {width: 0, height: 0}] - in case the hotspot is moved
*/
/**
* Creates a rectangle hotspot.
* @augments Help4.control2.hotspot.Hotspot
* @property {Help4.control2.AreaXYWH} rect - the assigned elements rect
* @property {Help4.control2.SizeWidthHeight} delta - in case the hotspot is moved
*/
Help4.control2.hotspot.Rectangle = class extends Help4.control2.hotspot.Hotspot {
/**
* @override
* @param {Help4.control2.hotspot.Rectangle.Params} [params]
*/
constructor(params) {
const T = Help4.jscore.ControlBase.TYPES;
super(params, {
params: {
rect: {type: T.xywh},
delta: {type: T.widthHeight}
},
statics: {
_svg: {destroy: false},
_rect: {destroy: false}
},
config: {
css: 'rectangle'
}
});
}
/**
* @override
* @param {Help4.control2.PositionXY} point
*/
calcMeetingPoint({x, y}) {
const {x: rx, y: ry, w: rw, h: rh} = this.rect;
const {width: dw, height: dh} = this.delta;
const rect = {
x: rx - dw / 2,
y: ry - dh / 2,
w: Math.max(0, rw + dw),
h: Math.max(0, rh + dh)
};
const line = { // line from tile to the center of hotspot
x1: rect.x + rect.w / 2,
y1: rect.y + rect.h / 2,
x2: x,
y2: y
};
return Help4.getRectIntersect(rect, line, this.borderSize) || {x, y};
}
/**
* @override
* @param {HTMLElement} dom - control DOM
*/
_onDomCreated(dom) {
super._onDomCreated(dom);
// svg elements need to be created createElementNS
const svg = this._svg = this._createElement('svg', {id: '-svg', css: 'svg', dom: dom, isNS: true});
const rect = this._rect = this._createElement('rect', {id: '-rect', css: 'rect', dom: svg, isNS: true});
// XRAY-3384: rounded corners (border-radius) of SVG makes hotspot border not clickable in IE
// so no rounded rect at all in IE
if (!Help4.Browser.IE) {
rect.setAttribute('rx', '1');
rect.setAttribute('ry', '1');
}
// must be created after SVG to allow overlapping
const cnt = this._content = this._createElement('div', {css: 'inner'});
this._createElement('div', {id: '-arrow', css: 'arrow', dom: cnt});
_apply.call(this);
}
/**
* @override
* @param {Help4.jscore.ControlBase.PropertyChangeEvent} event - the change event
*/
_applyPropertyToDom(event) {
({rect: 1, delta: 1}[event.name])
? _apply.call(this)
: super._applyPropertyToDom(event);
}
}
/**
* @memberof Help4.control2.hotspot.Rectangle#
* @private
*/
function _apply() {
const dom = this.getDom();
const {_svg, _rect} = this;
if (!dom || !_svg || !_rect) return;
const {x: rx, y: ry, w: rw, h: rh} = this.rect;
const {width: dw, height: dh} = this.delta;
const w = Math.max(0, rw + dw);
const h = Math.max(0, rh + dh);
// XRAY-3388: viewbox -0.5 -0.5 is for correct position of rect in SVG
_svg.setAttribute('viewBox', `-0.5 -0.5 ${w} ${h}`);
Help4.extendObject(_svg.style, {x: 0, y: 0, width: w + 'px', height: h + 'px'});
const sw = parseInt(getComputedStyle(_rect).strokeWidth);
Help4.Element.setAttribute(_rect, {
x: sw >> 1,
y: sw >> 1,
width: Math.max(0, w - sw),
height: Math.max(0, h - sw)
});
Help4.extendObject(dom.style, {
left: rx - dw / 2 + 'px',
top: ry - dh / 2 + 'px',
width: w + 'px',
height: h + 'px',
lineHeight: h + 'px'
});
}
})();