/** @module candidates */
// Imports
import ripplet from 'ripplet.js';
import addRipplet from './tools';
import cookie from './cookie';
import notifications from './notifications';
// eslint-disable-next-line import/no-cycle
import { selectTxt } from './settings';
import { oneSpace, toTitle } from './stringUtilities';
import winner from './winner';
// Variables
const firstBlock = document.querySelector('.block');
const firstName = firstBlock.querySelector('.name');
const firstCost = firstBlock.querySelector('.cost');
const firstKpLink = firstBlock.querySelector('.kp-link');
const firstClearRowBtn = firstBlock.querySelector('.btn');
const buyBlock = document.querySelector('.block-buy');
const buyText = document.querySelector('.block-buy span');
const buyInput = buyBlock.querySelector('.cost-buy');
const buyClear = buyBlock.querySelector('.btn');
const buyCookie = cookie.get('buyCost');
const buyDisableCookie = cookie.get('buyDisable');
const buyCheckbox = document.querySelector('#switch1');
const modalOverlay = document.getElementById('modal-overlay');
const modal = document.getElementById('modal');
const stopBtn = document.getElementById('stop-btn');
const addBtn = document.getElementById('add-btn');
const resetButton = document.getElementById('reset-icon');
const area = document.getElementById('candidates-area');
const defaultSize = 16.2; // vw
const defaultMargin = 2.96; // vw
const highestMargin = 35.71; // vw
let maxSize = defaultSize;
// Functions
/**
* Add <link> element to head with type
*
* @param {string} type - type of event (preload, prefetch, etc.)
* @param {string} url - address to load
*/
function addHint(type, url) {
const el = document.createElement('link');
if (!type || !url) return;
el.setAttribute('rel', type);
el.setAttribute('href', url);
document.head.appendChild(el);
}
/**
* Change width of element
*
* @private
* @param {Object} element - element, which width to change
* @param {Number} width - width value
*/
function applyWidth(element, width) {
element.style.width = `${width}vw`;
}
/**
* Trim name element value
*
* @private
* @param {Object} nameEl - name input
*/
function trimValue(nameEl) {
nameEl.value = nameEl.value.trim();
}
/**
* Sort name and cost inputs by cost value
*
*/
function sortCandidates() {
const names = Array.from(document.getElementsByClassName('name'));
const costs = Array.from(document.getElementsByClassName('cost'));
let total = [];
names.forEach((name, i) => {
const cost = costs[i];
const nameVal = name.value;
const costVal = Number(cost.value);
const nameTitle = name.getAttribute('title');
const costTitle = cost.getAttribute('title');
const link = name.parentElement.parentElement.querySelector('.kp-link').href;
total.push({
nameVal,
costVal,
nameTitle,
costTitle,
link,
});
});
total = total.sort((e1, e2) => e1.costVal - e2.costVal)
.reverse();
names.forEach((name, i) => {
const totalE = total[i];
let { costVal } = totalE;
costVal = costVal ? Number(costVal) : '';
name.value = totalE.nameVal;
costs[i].value = costVal;
name.setAttribute('title', totalE.nameTitle);
costs[i].setAttribute('title', totalE.costTitle);
name.parentElement.parentElement.querySelector('.kp-link').href = totalE.link;
});
}
/**
* Change sizes of all name inputs
*
* @param {Object} nameEl - name input
*/
function changeSize(nameEl) {
const names = Array.from(document.getElementsByClassName('name'));
const factor = 1.1;
const delta = nameEl.value.length - 10;
let width;
let margin;
if (delta > 0) {
width = defaultSize + delta * factor;
margin = defaultMargin + delta * factor;
margin = margin > highestMargin ? highestMargin : margin;
} else if (names.length === 1) {
maxSize = defaultSize;
names[0].removeAttribute('style');
addBtn.removeAttribute('style');
buyText.removeAttribute('style');
}
if (width && width > maxSize) {
maxSize = width;
names.forEach(name => applyWidth(name, width));
addBtn.style.width = `${width + 10}vw`;
buyText.style.marginRight = `${margin}vw`;
}
}
/**
* Make values of first name and cost elements empty
*
*/
function clearFirstRow() {
firstName.value = '';
firstCost.value = '';
firstName.setAttribute('title', 'Фильм, игра, etc');
firstCost.setAttribute('title', 'Сумма');
firstKpLink.href = 'https://www.kinopoisk.ru';
changeSize(firstName);
sortCandidates();
// To reset buy position
if (window.isBuy) window.isBuy = false;
}
/**
* Remove row from list
*
* @param {Object} delBtn - block delete button
*/
function removeRow(delBtn) {
const names = document.getElementsByClassName('name');
// Remove .block
delBtn.parentElement.parentElement.remove();
// Get back to default size after delete last non-empty row
if (names.length === 1 && !names[0].value) {
maxSize = defaultSize;
names[0].removeAttribute('style');
addBtn.removeAttribute('style');
buyText.removeAttribute('style');
}
}
/**
* Set title attribute to cost input
*
* @param {Object} costEl - cost input
*/
function changeTitle(costEl) {
const cost = costEl.value ? `: ${costEl.value} ₽` : '';
costEl.setAttribute('title', `Сумма${cost}`);
}
/**
* Eval cost input value to calculate
*
* @param {Object} costEl - cost input
*/
function checksum(costEl) {
const calc = costEl.value.replace(/[^\d+*/,.()-]/g, '')
.replace(/,/, '.');
try {
// eslint-disable-next-line no-eval
let result = eval(calc);
if (Number.isNaN(result) || !Number.isFinite(result)) {
costEl.value = '';
} else {
result = result <= 0 ? '' : Number(Number(result)
.toFixed(2));
costEl.value = result;
costEl.blur();
}
} catch {
costEl.value = '';
}
}
/**
* Check if cost value is already > buy
*
* @param {Object} costEl - cost input
* @see firstCost
*/
function checkOnBuy(costEl) {
if (!buyCheckbox.checked) return;
const need = Number(buyInput.value);
const curr = Number(costEl.value);
const name = winner.decorate(toTitle(costEl.previousElementSibling.value));
if (!need || !name || curr < need) return;
if (window.started) {
window.isBuy = true;
window.buyWinner = name;
window.buyCost = curr;
stopBtn.click();
} else {
modalOverlay.onclick = () => {
modal.classList.add('closed');
modalOverlay.classList.add('closed');
document.title = 'Аукцион';
};
modal.querySelector('p').innerText = `${name} выкупили, аж за ${curr} ₽ Pog!`;
modalOverlay.classList.remove('closed');
modal.classList.remove('closed');
notifications.playNotificationSound();
notifications.sendNotification('Аукцион окончен!', `Выкупили ${name}!`);
document.title = `${name} выкупили!`;
}
}
/**
* Set href attribute to sibling kp-link
*
* @param {Object} nameEl - name input
*/
function createLink(nameEl) {
const name = nameEl.value;
let link;
if (name) {
link = nameEl.parentElement.parentElement.querySelector('.kp-link');
link.href = encodeURI(`https://www.kinopoisk.ru/s/type/all/find/${name}/`);
// link.setAttribute('title', `Искать ${name}`);
nameEl.setAttribute('title', toTitle(name));
} else {
nameEl.parentElement.parentElement.querySelector('.kp-link').href = 'https://www.kinopoisk.ru';
nameEl.setAttribute('title', 'Фильм, игра, etc');
}
}
/**
* Cut more than 2 spaces to one
*
* @private
* @param {Object} nameEl - name input
*/
function oneSpacedValue(nameEl) {
nameEl.value = oneSpace(nameEl.value);
}
/**
* Add row to list through copy first block
*
* @param {string} [nameVal] - name of position
* @param {string} [costVal] - cost of position
*
*/
function createBlock(nameVal = '', costVal = '') {
const section = firstBlock.cloneNode(true);
const name = section.querySelector('.name');
const cost = section.querySelector('.cost');
const link = section.querySelector('.kp-link');
const btn = section.querySelector('.btn');
const delIcon = btn.querySelector('img');
const fromDA = nameVal && costVal;
name.value = nameVal;
cost.value = costVal;
addRipplet([name, cost, link, btn]);
btn.onclick = () => removeRow(btn);
cost.onchange = () => {
checksum(cost);
checkOnBuy(cost);
changeTitle(cost);
sortCandidates();
};
name.onchange = () => changeSize(name);
name.onkeyup = () => {
createLink(name);
changeSize(name);
};
delIcon.setAttribute('src', 'img/icons/material/delete.svg');
delIcon.setAttribute('alt', 'Удалить');
delIcon.setAttribute('title', 'Удалить');
link.setAttribute('title', 'Кинопоиск');
if (fromDA) {
checkOnBuy(cost);
createLink(name);
changeTitle(cost);
} else {
name.setAttribute('title', 'Фильм, игра, etc');
cost.setAttribute('title', 'Сумма');
link.setAttribute('href', 'https://www.kinopoisk.ru');
}
area.insertBefore(section, area.lastElementChild);
section.classList.add('visible');
if (fromDA) {
addHint('prefetch prerender', link.getAttribute('href'));
changeSize(name);
sortCandidates();
} else {
name.focus();
}
}
/**
* Works on click addBtn
*
* @private
* @param {Object} args - arguments object for ripplet
*/
function addBtnClick(...args) {
createBlock();
ripplet(args[0]);
}
/**
* Disable ransom on page
*
*/
function disableRansom() {
buyBlock.value = '';
buyBlock.style.display = 'none';
cookie.del('buyCost');
cookie.set('buyDisable', true);
}
/**
* Enable ransom on page
*
*/
function enableRansom() {
buyBlock.removeAttribute('style');
cookie.del('buyDisable');
}
// Exec
addRipplet([firstName, firstCost, firstKpLink,
firstClearRowBtn, buyInput, buyClear, resetButton]);
firstName.onchange = () => {
changeSize(firstName);
trimValue(firstName);
};
firstName.onkeyup = () => {
createLink(firstName);
changeSize(firstName);
oneSpacedValue(firstName);
};
firstCost.onchange = () => {
checksum(firstCost);
checkOnBuy(firstCost);
changeTitle(firstCost);
sortCandidates();
};
firstClearRowBtn.onclick = clearFirstRow;
addBtn.onclick = addBtnClick;
resetButton.onclick = () => {
while (area.children.length > 3) {
area.children[area.children.length - 2].remove();
}
clearFirstRow();
firstName.focus();
// To reset buy position
window.isBuy = false;
};
buyInput.value = buyCookie || '';
changeTitle(buyInput);
buyClear.onclick = () => {
buyInput.value = '';
buyInput.setAttribute('title', 'Сумма выкупа');
cookie.del('buyCost');
};
buyInput.onchange = () => {
checksum(buyInput);
changeTitle(buyInput);
if (buyInput.value) {
cookie.set('buyCost', buyInput.value);
} else {
cookie.del('buyCost');
}
};
buyInput.onclick = () => selectTxt(buyInput);
if (buyDisableCookie) {
disableRansom();
buyCheckbox.checked = false;
}
// Exports
export {
sortCandidates, changeTitle, checkOnBuy, createBlock,
enableRansom, disableRansom,
};