/* global applyOnMessage installed */ 'use strict'; // eslint-disable-next-line no-var var hotkeys = (() => { let togglablesShown; let togglables; let enabled = false; let ready = false; window.addEventListener('showStyles:done', function _() { window.removeEventListener('showStyles:done', _); togglablesShown = true; togglables = getTogglables(); ready = true; setState(true); initHotkeyInfo(); }); window.addEventListener('resize', adjustInfoPosition); return {setState}; function setState(newState = !enabled) { if (!ready) { throw new Error('hotkeys no ready'); } if (newState !== enabled) { window[`${newState ? 'add' : 'remove'}EventListener`]('keydown', onKeyDown); enabled = newState; } } function onKeyDown(event) { if (event.ctrlKey || event.altKey || event.metaKey || !enabled) { return; } let entry; const {which: k, key} = event; if (key ? key >= '0' && key <= '9' : k >= 48 && k <= 57 || k >= 96 && k <= 105) { // 0-9, numpad 0-9 const i = key === '0' ? 9 : key ? Number(key) - 1 : k === 48 || k === 96 ? 9 : k - (k > 96 ? 97 : 49); entry = installed.children[i]; } else if (key ? key === '`' || key === '*' && !event.shiftKey : k === 192 || k === 106) { // backtick ` and numpad * invertTogglables(); } else if (key ? key === '-' : k === 109) { // numpad - toggleState(installed.children, 'enabled', false); } else if (key ? key === '+' : k === 107) { // numpad + toggleState(installed.children, 'disabled', true); } else if (key ? key.length === 1 : k >= 65 && k <= 90) { // any single character const letter = new RegExp(key ? '^' + key : '^\\x' + k.toString(16), 'i'); entry = [...installed.children].find(entry => letter.test(entry.textContent)); } if (!entry) { return; } const target = $(event.shiftKey ? '.style-edit-link' : '.checker', entry); target.dispatchEvent(new MouseEvent('click')); } function getTogglables() { const all = [...installed.children]; const enabled = []; for (const entry of all) { if (entry.classList.contains('enabled')) { enabled.push(entry.id); } } return enabled.length ? enabled : all.map(entry => entry.id); } function countEnabledTogglables() { let num = 0; for (const id of togglables) { num += $(`#${id}`).classList.contains('enabled'); } return num; } function invertTogglables() { togglables = togglables.length ? togglables : getTogglables(); togglablesShown = countEnabledTogglables() > togglables.length / 2; toggleState(togglables, null, !togglablesShown); togglablesShown = !togglablesShown; } function toggleState(list, match, enable) { const results = []; let task = Promise.resolve(); for (let entry of list) { entry = typeof entry === 'string' ? $('#' + entry) : entry; if (!match && $('.checker', entry).checked !== enable || entry.classList.contains(match)) { results.push(entry.id); task = task.then(() => saveStyleSafe({ id: entry.styleId, enabled: enable, notify: false, })); } } if (results.length) { task.then(refreshAllTabs); } return results; } function refreshAllTabs() { getStylesSafe({matchUrl: location.href, enabled: true, asHash: true}) .then(styles => applyOnMessage({method: 'styleReplaceAll', styles})); queryTabs().then(tabs => tabs.forEach(tab => (!FIREFOX || tab.width) && refreshTab(tab))); } function refreshTab(tab) { const tabId = tab.id; chrome.webNavigation.getAllFrames({tabId}, frames => { frames = frames && frames[0] ? frames : [{frameId: 0}]; frames.forEach(({frameId}) => getStylesSafe({matchUrl: tab.url, enabled: true, asHash: true}).then(styles => { const message = {method: 'styleReplaceAll', tabId, frameId, styles}; invokeOrPostpone(tab.active, sendMessage, message, ignoreChromeError); if (frameId === 0) { setTimeout(BG.updateIcon, 0, tab, styles); } })); ignoreChromeError(); }); } function initHotkeyInfo() { const container = $('#hotkey-info'); let title; container.onclick = ({target}) => { if (target.localName === 'button') { close(); } else if (!container.dataset.active) { open(); } }; function close() { delete container.dataset.active; document.body.style.height = ''; container.title = title; window.addEventListener('resize', adjustInfoPosition); } function open() { window.removeEventListener('resize', adjustInfoPosition); debounce.unregister(adjustInfoPosition); title = container.title; container.title = ''; container.style = ''; container.dataset.active = true; if (!container.firstElementChild) { buildElement(); } const height = 4 + container.firstElementChild.scrollHeight + container.lastElementChild.scrollHeight + parseFloat(getComputedStyle(container.lastElementChild).paddingBottom); if (height > document.body.clientHeight) { document.body.style.height = height + 'px'; } } function buildElement() { const keysToElements = line => line .split(/(<.*?>)/) .map(s => (!s.startsWith('<') ? s : $create('mark', s.slice(1, -1)))); const linesToElements = text => text .trim() .split('\n') .map((line, i, array) => $create(i < array.length - 1 ? { tag: 'p', appendChild: keysToElements(line), } : { tag: 'a', target: '_blank', href: 'https://github.com/openstyles/stylus/wiki/Popup', textContent: line, })); [ linesToElements(t('popupHotkeysInfo')), $create('button', t('confirmOK')), ].forEach(child => { container.appendChild($create('div', child)); }); } } function adjustInfoPosition(debounced) { if (debounced !== true) { debounce(adjustInfoPosition, 100, true); return; } const style = $('#hotkey-info').style; if (installed.scrollHeight > installed.clientHeight || document.scrollingElement.scrollHeight > document.scrollingElement.innerHeight) { const entryRight = installed.firstElementChild.getBoundingClientRect().right; style.setProperty('right', window.innerWidth - entryRight + 'px', 'important'); } const installedBottom = installed.getBoundingClientRect().bottom + window.scrollY; style.setProperty('bottom', window.innerHeight - installedBottom + 'px', 'important'); } })();