Files
fmt/src/main/resources/static/axui-v2.1.1/plugins/axRate/axRate.js
WIN-VSNMD38DUOC\Administrator 25817132fd 升级AXUI到v2.1.1
2024-03-11 09:13:08 +08:00

265 lines
10 KiB
JavaScript

/*!
*Last modified: 2023-09-15 14:35:16
*名称: axRate.js
*简介: 评星插件的js文件
*用法: new axRate('#id',{参数})
*版本: v1.0.4
*演示: https://www.axui.cn/v2.0/ax-rate.php
*客服: 3217728223@qq.com
*交流: QQ群952502085
*作者: AXUI团队
*/
class axRate {
constructor(elem, options) {
this.targetDom = axIdToDom(elem);
this.options = axExtend({
insName: '',
half: false,
icon: 'ax-iconfont ax-icon-star-f',
count: 5,
multiplier: 1,
value: 0,
readonly: false,
popShow: false,
popTheme: 'ad',
popFormat: '<i stars></i>星,总分:<i value></i>',
tipsShow: false,
tipsFormat: '<i stars></i>星,总分:<i value></i>',
clearShow: false,
size: '',
rendered: '',
getValue: '',
setValue: '',
breakpoints: {},
}, options, this.targetDom, this.constructor.name);
this.handlers = {};
if (!this.targetDom || this.targetDom.nodeName == 'INPUT') {
this.parent = axAddElem('div', { class: 'ax-rate' });
if (this.targetDom.nodeName == 'INPUT') {
this.hidden = this.targetDom;
this.hidden.insertAdjacentElement('beforeBegin', this.parent);
this.hidden.type != 'hidden' ? this.hidden.style.display = 'none' : null;
}
} else {
this.parent = this.targetDom;
}
this.value = 0;
this.stars = 0;
this.items = [];
this.init();
return this;
}
init() {
axInstance.push(this, this.options.insName, 'rate');
!axIsEmpty(this.options.breakpoints) ? axBreakpoints(this.options, this.options.breakpoints) : null;
this.renderRate();
this.set(this.options.value);
let pop;
if (this.options.popShow) {
pop = axAddElem('div', { class: 'ax-rate-popcon' }, this.options.popFormat);
this.tooltip = new axTooltip(this.items[0].dom, {
trigger: 'none',
theme: this.options.popTheme,
content: pop,
});
new axHover(this.ul, {
enter: () => {
this.tooltip.popup.show()
},
leave: () => {
this.tooltip.popup.hide();
},
hold: this.tooltip.popup.targetDom,
});
}
if (!this.options.readonly) {
this.clear.onclick = () => {
this.set(0);
}
this.items.forEach((item) => {
let itemDom = item.dom,
firstChild = itemDom.firstElementChild,
before = this.items.filter(i => i.id < item.id),
after = this.items.filter(i => i.id > item.id);
if (this.options.popShow) {
new axHover(itemDom, {
enter: () => {
this.tooltip.popup.updatePosition(itemDom);
},
});
}
itemDom.onmousemove = (e) => {
let place = this.movePlace(e, itemDom);
before.forEach(i => {
i.dom.firstElementChild.classList.add('ax-full');
i.value = 1;
});
if (place == 'half') {
firstChild.classList.remove('ax-full');
firstChild.classList.add('ax-half');
} else if (place == 'full') {
firstChild.classList.remove('ax-half');
firstChild.classList.add('ax-full');
}
after.forEach(i => {
i.dom.firstElementChild.classList.remove('ax-half');
i.dom.firstElementChild.classList.remove('ax-full');
});
if (this.options.popShow) {
this.calculate(item, place, pop);
}
itemDom.onclick = () => {
if (place == 'half') {
item.value = 0.5;
} else if (place == 'full') {
item.value = 1;
} else {
item.value = 0;
}
this.calculate(item, place);
if (this.options.tipsShow) {
this.tipsValue ? this.tipsValue.innerHTML = this.value : null;
this.tipsStars ? this.tipsStars.innerHTML = this.stars : null;
}
this.options.getValue && this.options.getValue.call(this, this.value, this.stars);
this.handlers.hasOwnProperty('getValue') ? this.emit('getValue', this.value, this.stars) : null;
}
}
});
this.ul.onmouseleave = () => {
this.set(this.value);
this.options.setValue && this.options.setValue.call(this, this.value, this.stars);
this.handlers.hasOwnProperty('setValue') ? this.emit('setValue', this.value, this.stars) : null;
}
}
}
set(val) {
if (val <= 0) {
val = 0;
}
if (val >= this.options.multiplier * this.options.count) {
val = this.options.multiplier * this.options.count;
}
let stars = val / this.options.multiplier,
beforeStars = Math.floor(stars),
currentStar = stars - beforeStars;
if (!this.options.half) {
currentStar = 0;
}
if (!val) {
this.items.forEach(i => {
let dom = i.dom.firstElementChild;
dom.classList.remove('ax-half');
dom.classList.remove('ax-full');
i.value = 0;
});
} else {
for (let i = 0; i <= beforeStars - 1; i++) {
let dom = this.items[i].dom.firstElementChild;
dom.classList.remove('ax-half');
dom.classList.add('ax-full');
this.items[i].value = 1;
}
}
this.stars = beforeStars;
if (currentStar == 0.5) {
let dom = this.items[beforeStars].dom.firstElementChild;
dom.classList.remove('ax-full');
dom.classList.add('ax-half');
this.items[beforeStars].value = 0.5;
this.stars += 0.5;
beforeStars++;
}
for (let i = beforeStars; i < this.items.length; i++) {
let dom = this.items[i].dom.firstElementChild;
dom.classList.remove('ax-half');
dom.classList.remove('ax-full');
this.items[i].value = 0;
}
this.value = val;
this.tipsValue ? this.tipsValue.innerHTML = val : null;
this.tipsStars ? this.tipsStars.innerHTML = this.stars : null;
this.hidden ? this.hidden.value = val : null;
}
get(attr) {
let obj = { stars: this.stars, value: this.value, count: this.options.count, multiplier: this.options.multiplier };
return obj[attr];
}
calculate(item, place, pop) {
let before = this.items.filter(i => i.id < item.id),
stars = before.length;
if (place == 'half') {
stars += 0.5;
} else if (place == 'full') {
stars++;
}
if (pop) {
pop.querySelector('[stars]').innerHTML = stars;
pop.querySelector('[value]').innerHTML = this.options.multiplier * stars;
} else {
this.value = this.options.multiplier * stars;
this.stars = stars;
}
}
renderRate() {
let fragment = document.createDocumentFragment(),
star = `<i class="${this.options.icon}"></i>`,
itemHTML = `<li class="ax-item">
${star.repeat(2)}
</li>`;
this.ul = axAddElem('ul');
this.tips = axAddElem('div', { class: 'ax-tips' }, this.options.tipsFormat);
this.tipsStars = this.tips.querySelector('[stars]');
this.tipsValue = this.tips.querySelector('[value]');
this.clear = axAddElem('i', { class: 'ax-iconfont ax-icon-close-o-f', clear: '' });
this.options.clearShow ? fragment.appendChild(this.clear) : null;
for (let i = 1; i <= this.options.count; i++) {
let itemDom = axStrToDom(itemHTML),
obj = {
id: i,
value: 0,
dom: itemDom,
};
this.items.push(obj);
this.ul.appendChild(itemDom);
}
fragment.appendChild(this.ul);
this.options.tipsShow ? fragment.appendChild(this.tips) : null;
if (this.options.size) {
this.parent.setAttribute('size', this.options.size);
}
this.parent.appendChild(fragment);
this.options.rendered && this.options.rendered.call(this);
'rendered' in this.handlers ? this.emit('rendered', '') : null;
}
movePlace(e, node) {
if (!this.options.half) {
return 'full';
}
let leftOffset = node.getBoundingClientRect().left,
rightOffset = node.getBoundingClientRect().right,
half = ((rightOffset - leftOffset) / 2),
halfOffset = leftOffset + ~~half,
placement = 'full';
if (e.clientX < halfOffset) {
placement = 'half';
}
return placement;
}
on(type, handler) {
axAddPlan(type, handler, this);
return this;
}
emit(type, ...params) {
axExePlan(type, this, ...params);
}
off(type, handler) {
axDelPlan(type, handler, this);
return this;
}
}
(() => {
document.querySelectorAll('[axRate]').forEach(element => {
new axRate(element);
});
})();