stylus/popup/popup-exclusions.js
2018-07-22 11:21:43 -05:00

161 lines
4.5 KiB
JavaScript

/*
global messageBox
global exclusions
*/
'use strict';
const popupExclusions = (() => {
const popupWidth = '400px';
// return matches on url ending to prevent duplicates in the exclusion list
// e.g. http://test.com and http://test.com/* are equivalent
// this function would return ['', '/*']
function exclusionExists(array, value) {
const match = [];
['', '*', '/', '/*'].forEach(ending => {
if (array.includes(value + ending)) {
match.push(ending);
}
});
return match;
}
/* Modal in Popup.html */
function processURL(url) {
const results = [];
const protocol = url.match(/\w+:\/\//);
const parts = url.replace(/(\w+:\/\/|[#?].*$)/g, '').split('/');
const domain = parts[0].split('.');
/*
Domain: a.b.com
Domain: b.com
Prefix: https://a.b.com
Prefix: https://a.b.com/current
Prefix: https://a.b.com/current/page
*/
while (parts.length > 1) {
results.push([t('excludedPrefix'), protocol + parts.join('/')]);
parts.pop();
}
while (domain.length > 1) {
results.push([t('excludedDomain'), domain.join('.')]);
domain.shift();
}
return results.reverse();
}
function createOption(option) {
// ["Domain/Prefix", "{url}"]
return $create('option', {
value: option[1],
title: option[1],
textContent: `${option[0]}: ${option[1]}`
});
}
function createPopupContent(url) {
const options = processURL(url);
return [
$create('h2', {textContent: t('exclusionsEditTitle')}),
$create('select', {
id: 'popup-exclusions',
size: options.length,
multiple: 'true',
value: ''
}, [
...options.map(option => createOption(option))
])
];
}
function getIframeURLs(style) {
getActiveTab().then(tab => {
if (tab && tab.status === 'complete') {
chrome.webNavigation.getAllFrames({
tabId: tab.id
}, frames => {
const urls = frames.reduce((acc, frame) => processURL(frame.url), []);
updateSelections(style, urls);
});
}
});
}
function updateSelections(style, newOptions = []) {
const select = $('select', messageBox.element);
const exclusions = Object.keys(style.exclusions || {});
if (newOptions.length) {
const currentOptions = [...select.children].map(opt => opt.value);
newOptions.forEach(opt => {
if (!currentOptions.includes(opt[1])) {
select.appendChild(createOption(opt));
}
});
select.size = select.children.length;
}
[...select.children].forEach(option => {
if (exclusionExists(exclusions, option.value).length) {
option.selected = true;
}
});
}
function openPopupDialog(style, tabURL) {
const msgBox = messageBox({
title: style.name,
className: 'center content-left',
contents: createPopupContent(tabURL),
buttons: [t('confirmOK'), t('confirmCancel')],
onshow: box => {
const contents = box.firstElementChild;
contents.style = `max-width: calc(${popupWidth} - 20px); max-height: none;`;
document.body.style.minWidth = popupWidth;
document.body.style.minHeight = popupWidth;
updateSelections(style);
getIframeURLs(style);
$('#message-box-buttons button', messageBox.element).onclick = function () {
handlePopupSave(style, this);
};
}
})
.then(() => {
document.body.style.minWidth = '';
document.body.style.minHeight = '';
});
return msgBox;
}
function handlePopupSave(style, button) {
const current = Object.keys(style.exclusions);
const select = $('#popup-exclusions', messageBox.element);
const all = exclusions.getMultiOptions({select});
const selected = exclusions.getMultiOptions({select, selectedOnly: true});
// Add exclusions
selected.forEach(value => {
let exists = exclusionExists(current, value);
if (!exists.length) {
style.exclusions[value] = exclusions.createRegExp(value);
exists = [''];
}
exists.forEach(ending => {
const index = all.indexOf(value + ending);
if (index > -1) {
all.splice(index, 1);
}
});
});
// Remove exclusions (unselected in popup modal)
all.forEach(value => {
exclusionExists(current, value).forEach(ending => {
delete style.exclusions[value + ending];
});
});
exclusions.save(style);
messageBox.listeners.button.apply(button);
}
return {openPopupDialog};
})();