(function() {
/**
* @typedef {Help4.control2.hotspot.Hotspot.Params} Help4.control2.hotspot.Underline.Params
* @property {Help4.control2.AreaXYWH} [rect = {x: 0, y: 0, w: 0, h: 0}] - the rect of the assigned element
* @property {Help4.control2.SizeWidthHeight} [delta = {width: 0, height: 0}] - in case the hotspot is moved
*/
/**
* Creates an underline hotspot
* @augments Help4.control2.hotspot.Hotspot
* @property {Help4.control2.AreaXYWH} rect - the rect of the assigned element
* @property {Help4.control2.SizeWidthHeight} delta - in case the hotspot is moved
*/
Help4.control2.hotspot.Underline = class extends Help4.control2.hotspot.Hotspot {
/**
* @override
* @param {Help4.control2.hotspot.Underline.Params} [params]
*/
constructor(params) {
const T = Help4.jscore.ControlBase.TYPES;
super(params, {
params: {
rect: {type: T.xywh},
delta: {type: T.widthHeight}
},
statics: {
_rectHelper: {destroy: false}
},
config: {
css: 'underline'
}
});
}
/**
* @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 + rh + dh / 2,
w: Math.max(0, rw + dw),
h: parseInt(getComputedStyle(this.getDom()).height) || 0
};
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 */
getConnectionPoints(params) {
const {y: ry, h: rh} = this.rect;
const {height: dh} = this.delta;
const {left, right, width, height: lineH} = this.getDom().getBoundingClientRect();
const top = ry - dh / 2;
const height = rh + dh + lineH;
const bottom = top + height;
const mx = left + (width >> 1); // mid x
const my = top + (height >> 1); // mid y
return {
l: {x: left, y: my},
r: {x: right, y: my},
t: {x: mx, y: top},
b: {x: mx, y: bottom},
m: {x: mx, y: my}
};
}
/**
* @override
* @param {HTMLElement} dom - control DOM
*/
_onDomCreated(dom) {
super._onDomCreated(dom);
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({name, value, oldValue}) {
switch(name) {
case 'rect':
case 'delta':
_apply.call(this);
break;
case 'spotlight':
_handleSpotlight.call(this, value);
// fall-through is intended
default:
super._applyPropertyToDom({name, value, oldValue});
break;
}
}
}
/**
* @memberof Help4.control2.hotspot.Underline#
* @param {boolean} value - whether spotlight is enabled
* @private
*/
function _handleSpotlight(value) {
const {_rectHelper} = this;
if (!value) {
_rectHelper?.parentNode.removeChild(_rectHelper);
delete this._rectHelper;
} else if (!_rectHelper) {
this._rectHelper = this._createElement('div', {id: '-rh', css: 'spotlight-helper'});
_apply.call(this);
}
}
/**
* @memberof Help4.control2.hotspot.Underline#
* @private
*/
function _apply() {
const dom = this.getDom();
if (!dom) 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);
Help4.extendObject(dom.style, {
left: rx - dw / 2 + 'px',
top: ry + rh + dh / 2 + 'px',
width: w + 'px'
});
// XRAY-1465 rect helper
const {_rectHelper} = this;
if (_rectHelper) {
const h = Math.max(0, rh + dh);
Help4.extendObject(_rectHelper.style, {
top: -h + 'px',
width: w + 'px',
height: h + 'px'
});
}
}
})();