Finish categories for UI

This commit is contained in:
Ilya Ig. Petrov 2017-04-24 05:16:32 -07:00
parent a1f6784fae
commit 8d1def5a85
4 changed files with 464 additions and 382 deletions

View File

@ -65,25 +65,27 @@
desc: 'Учитывать сайты, добавленные вручную. Только для своих прокси-серверов! Без своих прокси работать не будет.',
order: 6,
},
ifProxyErrors: {
dflt: false,
category: 'exceptions',
label: 'проксировать <a href>выбранные</a> ошибки',
desc: 'Предлагать добавить сайт в исключения при выбранных ошибках',
order: 7,
},
customProxyStringRaw: {
dflt: '',
category: 'ownProxies',
label: 'использовать СВОИ прокси',
url: 'https://rebrand.ly/ac-own-proxy',
order: 8,
order: 7,
},
ifProxyMoreDomains: {
ifDisabled: true,
dflt: false,
category: 'ownProxies',
label: 'проксировать .onion, .i2p и OpenNIC',
desc: 'Проксировать особые домены. Необходима поддержка со стороны прокси.',
order: 8,
},
ifProxyErrors: {
ifDisabled: true,
dflt: false,
category: 'ownProxies',
label: 'проксировать <a href>избранные</a> ошибки',
desc: 'Предлагать добавить сайт в исключения при выбранных ошибках.',
order: 9,
},

View File

@ -8,8 +8,10 @@
--ribbon-color: #4169e1;
--blue-bg: dodgerblue;
--default-grey: #bfbfbf;
--mild-hr: #d3d3d3;
--hr: #bababa;
--cr-options-headline: #d3d3d3;
--cr-icon-selected: #d7d7d7;
--cr-popup-border: #bababa;
--cr-grey-panel: #f2f2f2;
max-width: 28em;
}
body {
@ -70,7 +72,7 @@
}
hr {
border: none;
border-top: 1px solid var(--hr);
border-top: 1px solid var(--cr-popup-border);
margin: 0 0 0.6em 0;
padding: 0;
}
@ -143,12 +145,18 @@
section[data-for] {
padding: 0.6em 0 1em;
}
section[data-for] li label {
display: inline-block; /* Needed for ::first-letter below. */
}
section[data-for] li label::first-letter {
text-transform: uppercase;
}
:root.if-options-page section[data-for] {
padding-bottom: 0.6em;
}
:root.if-options-page section[data-for]:not(:last-child),
.underlined {
border-bottom: 1px solid var(--mild-hr);
.underlined {
border-bottom: 1px solid var(--cr-options-headline);
}
/* HIDE starts. */
@ -157,8 +165,8 @@
:root:not(.if-options-page) #acc-own-mods:not(:checked) ~ .main-nav section[data-for="acc-own-mods"],
:root:not(.if-options-page) #acc-mods:not(:checked) ~ .main-nav section[data-for="acc-mods"],
:root:not(.if-options-page) #acc-ntf:not(:checked) ~ .main-nav section[data-for="acc-ntf"],
/* One button shared between two sections: */
:root:not(.if-options-page) #acc-own-mods:not(:checked) + #acc-mods:not(:checked) ~ .main-nav #apply-mods-button
/* One button shared between two sections: */
:root:not(.if-options-page) #acc-own-mods:not(:checked) + #acc-mods:not(:checked) ~ .main-nav #apply-mods-section
{
/* Hide, but preclude width resizes. */
height: 0px !important;
@ -177,8 +185,8 @@
:root:not(.if-options-page) #acc-own-mods:not(:checked) ~ .main-nav section[data-for="acc-own-mods"] *,
:root:not(.if-options-page) #acc-mods:not(:checked) ~ .main-nav section[data-for="acc-mods"] *,
:root:not(.if-options-page) #acc-ntf:not(:checked) ~ .main-nav section[data-for="acc-ntf"] *,
/* One button shared between two sections: */
:root:not(.if-options-page) #acc-own-mods:not(:checked) + #acc-mods:not(:checked) ~ .main-nav #apply-mods-button *
/* One button shared between two sections: */
:root:not(.if-options-page) #acc-own-mods:not(:checked) + #acc-mods:not(:checked) ~ .main-nav #apply-mods-section *
{
margin-top: 0 !important;
margin-bottom: 0 !important;
@ -186,7 +194,7 @@
/* HIDE ends. */
.nav-labels {
background-color: var(--chrome-grey);
background-color: var(--cr-grey-panel);
text-align: center;
}
.nav-labels li label {
@ -242,6 +250,11 @@
/* INFO SIGNS */
input:disabled + .label-container label {
color: var(--default-grey);
pointer-events: none;
}
.info-row {
position: relative;
}
@ -302,7 +315,7 @@
width: calc(25% + 0.6em);
}
/* TAB_1 PAC PROVIDER */
/* TAB_1: PAC PROVIDER */
.update-button {
visibility: hidden;
@ -323,14 +336,8 @@
margin-top: 0.5em;
}
/* TAB_2 PAC MODS */
/* TAB_2: PAC MODS */
#pac-mods label {
display: block;
}
#pac-mods label:first-letter {
text-transform: uppercase;
}
#mods-custom-proxy-string-raw ~ textarea {
width: 100%;
height: 7em;
@ -341,53 +348,63 @@
display: none;
}
/* TAB_3 EXCEPTIONS */
#exc-address-container {
display: flex;
align-items: center;
width: 100%;
}
#exc-address-container > a {
border-bottom: 1px solid transparent;
margin-left: 0.2em;
}
#exc-address {
width: 100%;
display: flex;
align-items: baseline;
--exc-hieght: 1.6em;
font-size: 1em;
border-bottom: 1px solid var(--ribbon-color) !important;
}
input#exc-editor {
border: none;
width: 100%;
background: inherit;
/* The two below align '.' (dot) vertically. */
max-height: var(--exc-hieght) !important;
min-height: var(--exc-hieght) !important;
}
#exc-radio {
display: flex;
justify-content: space-around;
margin-top: 0.5em;
}
[name="if-proxy-this-site"]:checked + label {
font-weight: bold;
}
#exc-address.if-yes {
background-color: lightgreen;
}
#exc-address.if-no {
background-color: pink;
}
/* TAB_3: EXCEPTIONS */
option.if-proxied {
color: var(--ribbon-color);
}
option:not(.if-proxied) {
color: red;
}
/* EXC-EDITOR starts. */
#exc-address-container {
display: flex;
align-items: center;
width: 100%;
}
#exc-address-container > a {
border-bottom: 1px solid transparent;
margin-left: 0.2em;
}
#exc-address {
width: 100%;
display: flex;
align-items: baseline;
--exc-hieght: 1.6em;
font-size: 1em;
border-bottom: 1px solid var(--ribbon-color) !important;
}
input#exc-editor {
border: none;
width: 100%;
background: inherit;
/* The two below align '.' (dot) vertically. */
max-height: var(--exc-hieght) !important;
min-height: var(--exc-hieght) !important;
}
#exc-radio {
display: flex;
justify-content: space-around;
margin-top: 0.5em;
}
[name="if-proxy-this-site"]:checked + label {
font-weight: bold;
}
#exc-address.if-yes {
background-color: lightgreen;
}
#exc-address.if-no {
background-color: pink;
}
option.if-proxied {
color: var(--ribbon-color);
}
option:not(.if-proxied) {
color: red;
}
/* EXC-EDITOR ends. */
#exc-mods {
padding-top: 1em;
}
#exc-mods input#mods-if-mind-exceptions:not(:checked) + .label-container label {
color: red;
}
/* CONTROL RAW = BUTTON + LINK */
@ -401,7 +418,7 @@
margin: 1em 0 1em 0;
}
.hor-flex > input:not([type="button"]) {
.hor-flex input:not([type="button"]) {
align-self: flex-end;
}
.label-container {
@ -495,41 +512,44 @@
</section>
<section data-for="acc-exc" class="hidden-for-options-page">
<div>Проксировать указанный сайт?</div>
<div id="exc-address-container">
<div id="exc-address">
<span>*.</span><input placeholder="navalny.com" list="exc-list" name="browser" id="exc-editor" style=""/>
</div>
<a href="../exceptions/index.html" title="импорт/экспорт"><svg
class="icon"
><use xlink:href="#icon-import-export"></use></svg>
</a>
</div>
<datalist id="exc-list"></datalist>
<ol class="horizontal-list" id="exc-radio">
<li><input id="this-auto" type="radio" checked name="if-proxy-this-site"/>
<label for="this-auto"><!--span class="emoji">🔄(looks fat)</span--><svg
<section class="exc-editor-section" style="padding-bottom: 1em;">
<div>Проксировать указанный сайт?</div>
<div id="exc-address-container">
<div id="exc-address">
<span>*.</span><input placeholder="navalny.com" list="exc-list" name="browser" id="exc-editor" style=""/>
</div>
<a href="../exceptions/index.html" title="импорт/экспорт"><svg
class="icon"
style="position: relative; top: 0.15em;"><use xlink:href="#icon-loop-round"></use></svg>&nbsp;авто</label>
</li>
<li><input id="this-yes" type="radio" name="if-proxy-this-site"/> <label for="this-yes">&nbsp;да</label></li>
<li><input id="this-no" type="radio" name="if-proxy-this-site"/> <label for="this-no">&nbsp;нет</label></li>
</ol>
><use xlink:href="#icon-import-export"></use></svg>
</a>
</div>
<datalist id="exc-list"></datalist>
<ol class="horizontal-list" id="exc-radio">
<li><input id="this-auto" type="radio" checked name="if-proxy-this-site"/>
<label for="this-auto"><!--span class="emoji">🔄(looks fat)</span--><svg
class="icon"
style="position: relative; top: 0.15em;"><use xlink:href="#icon-loop-round"></use></svg>&nbsp;авто</label>
</li>
<li><input id="this-yes" type="radio" name="if-proxy-this-site"/> <label for="this-yes">&nbsp;да</label></li>
<li><input id="this-no" type="radio" name="if-proxy-this-site"/> <label for="this-no">&nbsp;нет</label></li>
</ol>
</section>
<ul id="exc-mods"></ul>
</section>
<section data-for="acc-own-mods">
<ul id="own-proxies"></ul>
<ul id="own-mods"></ul>
</section>
<section data-for="acc-mods">
<ul id="pac-mods"></ul>
</section>
<section id="apply-mods-button" class="control-row hor-flex" style="margin-top: 0.2em">
<input type="button" value="Применить" id="apply-mods" disabled/>
<a href id="reset-mods">К изначальным!</a>
</section>
<section id="apply-mods-section" class="control-row hor-flex" style="margin-top: 0.2em">
<input type="button" value="Применить" id="apply-mods" disabled/>
<a href id="reset-mods">К изначальным!</a>
</section>
<section data-for="acc-ntf">
<header>Я <span style="color: #f93a17"></span>едомления:</header>

View File

@ -1,13 +1,21 @@
'use strict';
const START = Date.now();
{
document.getElementById('pac-mods').onchange = function() {
const enableButton = function enablebutton() {
this.classList.add('changed');
document.getElementById('apply-mods').disabled = false;
this.classList.add('changed');
document.getElementById('apply-mods').disabled = false;
};
};
['pac-mods', 'own-mods'].forEach((id) => {
document.getElementById(id).onchange = enableButton;
});
}
chrome.runtime.getBackgroundPage( (backgroundPage) =>
backgroundPage.apis.errorHandlers.installListenersOn(
@ -131,7 +139,13 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
const inputs = document.querySelectorAll('input');
for ( let i = 0; i < inputs.length; i++ ) {
inputs[i].disabled = val === 'on' ? false : true;
const input = inputs[i];
if (val === 'off') {
input.dataset.previousDisabledValue = input.disabled;
input.disabled = true;
} else {
input.disabled = input.dataset.previousDisabledValue === 'true';
}
}
};
@ -176,18 +190,22 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
const appendInfoRow = (mountEl, conf, inputTypeName, inputId, htmlAfterLabel = '') => {
mountEl.classList.add('info-row', 'hor-flex');
if (conf.ifDisabled) {
mountEl.title = 'В РАЗРАБОТКЕ!';
}
mountEl.innerHTML = `
<input ${inputTypeName} id="${inputId}">
<input ${inputTypeName} id="${inputId}" ${conf.ifDisabled ? 'disabled' : ''}>
<div class="label-container">
<label for="${inputId}"> ${conf.label}</label>
<label for="${inputId}">${conf.label}</label>
${htmlAfterLabel}
</div>` + (conf.desc ? infoSign(conf.desc) : infoUrl(conf.url));
};
{
const ul = document.querySelector('#list-of-providers');
const _firstChild = ul.firstChild;
{ // PAC-PROVIDERS starts.
const ul = document.getElementById('list-of-providers');
const _firstChildOrNull = ul.firstChild;
for(
const provConf of antiCensorRu.getSortedEntriesForProviders()
) {
@ -204,16 +222,11 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
);
return false;
};
ul.insertBefore( li, _firstChild );
ul.insertBefore( li, _firstChildOrNull );
}
checkChosenProvider();
}
const radios = [].slice.apply(
document.querySelectorAll('[name=pacProvider]')
);
for(const radio of radios) {
radio.onclick = function(event) {
const radioClickHandler = function radioClickHandler(event) {
if (
event.target.id === (
@ -240,7 +253,14 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
}
return false;
};
}
document.querySelectorAll('input[name=pacProvider]').forEach((radio) => {
radio.onclick = radioClickHandler;
});
} // PAC-PROVIDERS ends.
// IF MINI
@ -266,275 +286,337 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
{ // KITCHEN PANELS starts.
const pacKitchen = backgroundPage.apis.pacKitchen;
const camelToDash = (name) => name.replace(/([A-Z])/g, (_, p) => '-' + p.toLowerCase());
const modKeyToLi = {};
const applyMods = function applyMods(newMods) {
conduct(
'Применяем настройки...',
(cb) => pacKitchen.keepCookedNowAsync(newMods, cb),
'Настройки применены.',
() => {
document.getElementById('apply-mods').disabled = true;
}
);
};
{ // EXCEPTIONS TAB starts.
const excEditor = document.getElementById('exc-editor');
{ // EXC-MODS starts.
const validateHost = function validateHost(host) {
const emodsList = document.getElementById('exc-mods');
const _firstChildOrNull = emodsList.firstChild;
const ValidHostnameRegex = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/;
if(!ValidHostnameRegex.test(host)) {
showErrors(new TypeError('Должно быть только доменное имя, без протокола, порта и пути. Попробуйте ещё раз.'));
return false;
}
return true;
for(const conf of pacKitchen.getOrderedConfigs('exceptions')) {
};
const key = conf.key;
const iddy = 'mods-' + camelToDash(conf.key);
const li = document.createElement('li');
appendInfoRow(li, conf, `type="checkbox" ${conf.value ? 'checked' : ''}`, iddy);
emodsList.insertBefore( li, _firstChildOrNull );
modKeyToLi[key] = li;
li.querySelector('input').onclick = function() {
const labelIfProxied = '✔';
const labelIfNotProxied = '✘';
const labelIfAuto = '↻';
const oldMods = pacKitchen.getPacMods();
oldMods[key] = this.checked;
applyMods(oldMods);
const addOption = function addOption(host, yesNoUndefined) {
const opt = document.createElement('option');
// `value` may be changed for hiding line in the tooltip.
opt.value = host;
opt.dataset.host = host;
switch(yesNoUndefined) {
case true:
opt.label = labelIfProxied;
break;
case false:
opt.label = labelIfNotProxied;
break;
default:
opt.label = labelIfAuto;
}
const editorHost = excEditor.value.trim();
if (host === editorHost) {
excList.insertBefore( opt, excList.firstChild );
} else {
excList.appendChild(opt);
}
return opt;
};
const thisYes = document.getElementById('this-yes');
const thisNo = document.getElementById('this-no');
const thisAuto = document.getElementById('this-auto');
const yesClass = 'if-yes';
const noClass = 'if-no';
function moveCursorIfNeeded() {
const nu = excEditor.dataset.moveCursorTo;
if(nu !== undefined) {
excEditor.setSelectionRange(nu, nu);
delete excEditor.dataset.moveCursorTo;
}
}
const hideOpt = (opt) => opt.value = '\n';
const unhideOptAndAddSpace = (opt) => opt.value = opt.dataset.host + ' ';
const excList = document.getElementById('exc-list');
excEditor.onkeydown = function(event) {
moveCursorIfNeeded();
if(event.key === 'Enter') {
// Hide all.
excList.childNodes.forEach( hideOpt );
}
return true;
};
const renderExceptionsPanelFromExcList = function renderExceptionsPanelFromExcList(event) {
// If triangle button on right of datalist input clicked.
let ifTriangleClicked = false;
const ifClick = event && event.type === 'click';
{
const maxIndentFromRightInPx = 15;
ifTriangleClicked = ifClick
&& !excEditor.selectionStart && !excEditor.selectionEnd
&& event.x > excEditor.getBoundingClientRect().right - maxIndentFromRightInPx;
}
const setInputValue = (newValue) => {
if (ifClick && !ifTriangleClicked) {
// Don't jerk cursor on simple clicks.
return;
}
// See bug in my comment to http://stackoverflow.com/a/32394157/521957
// First click on empty input may be still ignored.
const nu = excEditor.selectionStart + newValue.length - excEditor.value.length;
excEditor.value = newValue;
excEditor.dataset.moveCursorTo = nu;
window.setTimeout(moveCursorIfNeeded, 0);
};
};
const originalHost = excEditor.value.trim();
const ifInit = !event;
const currentHost = ifTriangleClicked ? '' : (originalHost || (ifInit ? '' : ' '));
setInputValue(currentHost);
}// EXC-MODS ends.
let exactOpt = false;
let editedOpt = false;
excList.childNodes.forEach(
(opt) => {
{ // EXC-EDITOR starts.
unhideOptAndAddSpace(opt);
const excEditor = document.getElementById('exc-editor');
if(opt.label === labelIfAuto) {
editedOpt = opt;
const validateHost = function validateHost(host) {
const ValidHostnameRegex = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/;
if(!ValidHostnameRegex.test(host)) {
showErrors(new TypeError('Должно быть только доменное имя, без протокола, порта и пути. Попробуйте ещё раз.'));
return false;
}
return true;
};
const labelIfProxied = '✔';
const labelIfNotProxied = '✘';
const labelIfAuto = '↻';
const addOption = function addOption(host, yesNoUndefined) {
const opt = document.createElement('option');
// `value` may be changed for hiding line in the tooltip.
opt.value = host;
opt.dataset.host = host;
switch(yesNoUndefined) {
case true:
opt.label = labelIfProxied;
break;
case false:
opt.label = labelIfNotProxied;
break;
default:
opt.label = labelIfAuto;
}
const editorHost = excEditor.value.trim();
if (host === editorHost) {
excList.insertBefore( opt, excList.firstChild );
} else {
excList.appendChild(opt);
}
return opt;
};
const thisYes = document.getElementById('this-yes');
const thisNo = document.getElementById('this-no');
const thisAuto = document.getElementById('this-auto');
const yesClass = 'if-yes';
const noClass = 'if-no';
function moveCursorIfNeeded() {
const nu = excEditor.dataset.moveCursorTo;
if(nu !== undefined) {
excEditor.setSelectionRange(nu, nu);
delete excEditor.dataset.moveCursorTo;
}
}
const hideOpt = (opt) => opt.value = '\n';
const unhideOptAndAddSpace = (opt) => opt.value = opt.dataset.host + ' ';
const excList = document.getElementById('exc-list');
excEditor.onkeydown = function(event) {
moveCursorIfNeeded();
if(event.key === 'Enter') {
// Hide all.
excList.childNodes.forEach( hideOpt );
}
return true;
};
const renderExceptionsPanelFromExcList = function renderExceptionsPanelFromExcList(event) {
// If triangle button on right of datalist input clicked.
let ifTriangleClicked = false;
const ifClick = event && event.type === 'click';
{
const maxIndentFromRightInPx = 15;
ifTriangleClicked = ifClick
&& !excEditor.selectionStart && !excEditor.selectionEnd
&& event.x > excEditor.getBoundingClientRect().right - maxIndentFromRightInPx;
}
const setInputValue = (newValue) => {
if (ifClick && !ifTriangleClicked) {
// Don't jerk cursor on simple clicks.
return;
}
if (opt.dataset.host === originalHost) {
exactOpt = opt;
// See bug in my comment to http://stackoverflow.com/a/32394157/521957
// First click on empty input may be still ignored.
const nu = excEditor.selectionStart + newValue.length - excEditor.value.length;
excEditor.value = newValue;
excEditor.dataset.moveCursorTo = nu;
window.setTimeout(moveCursorIfNeeded, 0);
};
const originalHost = excEditor.value.trim();
const ifInit = !event;
const currentHost = ifTriangleClicked ? '' : (originalHost || (ifInit ? '' : ' '));
setInputValue(currentHost);
let exactOpt = false;
let editedOpt = false;
excList.childNodes.forEach(
(opt) => {
unhideOptAndAddSpace(opt);
if(opt.label === labelIfAuto) {
editedOpt = opt;
return;
}
if (opt.dataset.host === originalHost) {
exactOpt = opt;
}
}
);
}
);
thisAuto.checked = true;
excEditor.parentNode.classList.remove(noClass, yesClass);
thisAuto.checked = true;
excEditor.parentNode.classList.remove(noClass, yesClass);
const ifInputEmpty = !originalHost;
if (ifTriangleClicked || ifInputEmpty) {
// Show all opts.
if (editedOpt) {
// Example of editedOpt.value: 'abcde ' <- Mind the space (see unhideOptAndAddSpace)!
const ifBackspacedOneChar = ifInputEmpty && editedOpt.value.length < 3;
if (ifBackspacedOneChar) {
editedOpt.remove();
const ifInputEmpty = !originalHost;
if (ifTriangleClicked || ifInputEmpty) {
// Show all opts.
if (editedOpt) {
// Example of editedOpt.value: 'abcde ' <- Mind the space (see unhideOptAndAddSpace)!
const ifBackspacedOneChar = ifInputEmpty && editedOpt.value.length < 3;
if (ifBackspacedOneChar) {
editedOpt.remove();
}
}
}
return true;
}
if (editedOpt) {
const ifEditedOptAlreadyExists = editedOpt.dataset.host === originalHost;
if(ifEditedOptAlreadyExists) {
hideOpt(editedOpt);
return true;
}
// Not exact! Update!
editedOpt.remove();
}
if (!exactOpt) {
editedOpt = addOption(originalHost, undefined);
if (!ifClick) {
// New value was typed -- don't show tooltip.
hideOpt(editedOpt);
}
return true;
}
// Exact found!
excList.childNodes.forEach(hideOpt);
if(exactOpt.label === labelIfProxied) {
thisYes.checked = true;
excEditor.parentNode.classList.add(yesClass);
} else {
thisNo.checked = true;
excEditor.parentNode.classList.add(noClass);
}
return true;
};
excEditor.onclick = excEditor.oninput = renderExceptionsPanelFromExcList;
if (currentTab && !currentTab.url.startsWith('chrome')) {
excEditor.value = new URL(currentTab.url).hostname;
} else {
// Show placeholder.
excEditor.value = '';
}
{ // Populate selector.
const pacMods = pacKitchen.getPacMods();
for(const host of Object.keys(pacMods.exceptions || {}).sort()) {
addOption(host, pacMods.exceptions[host]);
}
renderExceptionsPanelFromExcList(); // Colorize input.
}
document.getElementById('exc-radio').onclick = function(event) {
/* ON CLICK */
if(event.target.tagName !== 'INPUT') {
// Only label on checkbox.
return true;
}
const host = excEditor.value.trim();
const pacMods = pacKitchen.getPacMods();
pacMods.exceptions = pacMods.exceptions || {};
let fixOptions;
const curOptOrNull = excList.querySelector(`[data-host="${host}"]`);
if (thisAuto.checked) {
delete pacMods.exceptions[host];
fixOptions = () => {
curOptOrNull && curOptOrNull.remove();
}
} else {
// YES or NO checked.
const ifYesClicked = thisYes.checked;
if (!validateHost(host)) {
return false;
}
if (ifYesClicked && !pacMods.filteredCustomsString) {
showErrors( new TypeError(
'Проксировать СВОИ сайты можно только при наличии СВОИХ прокси (см. «Модификаторы» ). Нет своих прокси, удовлетворяющих вашим требованиям.'
));
return false;
}
//const ifNew = !(host in pacMods.exceptions);
pacMods.exceptions[host] = ifYesClicked;
// Change label.
fixOptions = () => {
if (curOptOrNull) {
curOptOrNull.label = ifYesClicked ? labelIfProxied : labelIfNotProxied;
} else {
addOption(host, ifYesClicked);
if (editedOpt) {
const ifEditedOptAlreadyExists = editedOpt.dataset.host === originalHost;
if(ifEditedOptAlreadyExists) {
hideOpt(editedOpt);
return true;
}
};
// Not exact! Update!
editedOpt.remove();
}
if (!exactOpt) {
editedOpt = addOption(originalHost, undefined);
if (!ifClick) {
// New value was typed -- don't show tooltip.
hideOpt(editedOpt);
}
return true;
}
// Exact found!
excList.childNodes.forEach(hideOpt);
if(exactOpt.label === labelIfProxied) {
thisYes.checked = true;
excEditor.parentNode.classList.add(yesClass);
} else {
thisNo.checked = true;
excEditor.parentNode.classList.add(noClass);
}
return true;
};
excEditor.onclick = excEditor.oninput = renderExceptionsPanelFromExcList;
if (currentTab && !currentTab.url.startsWith('chrome')) {
excEditor.value = new URL(currentTab.url).hostname;
} else {
// Show placeholder.
excEditor.value = '';
}
conduct(
'Применяем исключения...',
(cb) => pacKitchen.keepCookedNowAsync(pacMods, cb),
'Исключения применены. Не забывайте о кэше!',
() => {
fixOptions();
// Window may be closed before this line executes.
renderExceptionsPanelFromExcList();
{ // Populate selector.
const pacMods = pacKitchen.getPacMods();
for(const host of Object.keys(pacMods.exceptions || {}).sort()) {
addOption(host, pacMods.exceptions[host]);
}
);
return false; // Don't check before operation is finished.
renderExceptionsPanelFromExcList(); // Colorize input.
};
}
document.getElementById('exc-radio').onclick = function(event) {
/* ON CLICK */
if(event.target.tagName !== 'INPUT') {
// Only label on checkbox.
return true;
}
const host = excEditor.value.trim();
const pacMods = pacKitchen.getPacMods();
pacMods.exceptions = pacMods.exceptions || {};
let fixOptions;
const curOptOrNull = excList.querySelector(`[data-host="${host}"]`);
if (thisAuto.checked) {
delete pacMods.exceptions[host];
fixOptions = () => {
curOptOrNull && curOptOrNull.remove();
}
} else {
// YES or NO checked.
const ifYesClicked = thisYes.checked;
if (!validateHost(host)) {
return false;
}
if (ifYesClicked && !pacMods.filteredCustomsString) {
showErrors( new TypeError(
'Проксировать СВОИ сайты можно только при наличии СВОИХ прокси (см. «Модификаторы» ). Нет своих прокси, удовлетворяющих вашим требованиям.'
));
return false;
}
//const ifNew = !(host in pacMods.exceptions);
pacMods.exceptions[host] = ifYesClicked;
// Change label.
fixOptions = () => {
if (curOptOrNull) {
curOptOrNull.label = ifYesClicked ? labelIfProxied : labelIfNotProxied;
} else {
addOption(host, ifYesClicked);
}
};
}
conduct(
'Применяем исключения...',
(cb) => pacKitchen.keepCookedNowAsync(pacMods, cb),
'Исключения применены. Не забывайте о кэше!',
() => {
fixOptions();
// Window may be closed before this line executes.
renderExceptionsPanelFromExcList();
}
);
return false; // Don't check before operation is finished.
};
} // EXC-EDITOR ends.
} // EXCEPTIONS TAB ends.
const camelToDash = (name) => name.replace(/([A-Z])/g, (_, p) => '-' + p.toLowerCase());
{ // PAC MODS TAB starts.
const modsList = document.getElementById('pac-mods');
const _firstChildOrNull = modsList.firstChild;
for(const conf of pacKitchen.getOrderedConfigs('general')) {
const key = conf.key;
const iddy = 'mods-' + camelToDash(conf.key);
const li = document.createElement('li');
appendInfoRow(li, conf, `type="checkbox" ${conf.value ? 'checked' : ''}`, iddy);
modsList.insertBefore( li, _firstChildOrNull );
modKeyToLi[key] = li;
};
} // PAC MODS TAB ends.
const customProxyStringKey = 'customProxyStringRaw';
const uiRaw = 'ui-proxy-string-raw';
{ // OWN PROXIES TAB starts.
const ownsList = document.getElementById('own-proxies');
const _firstChild = ownsList.firstChild;
const keyToLi = {};
const customProxyStringKey = 'customProxyStringRaw';
const uiRaw = 'ui-proxy-string-raw';
const ownsList = document.getElementById('own-mods');
const _firstChildOrNull = ownsList.firstChild;
for(const conf of pacKitchen.getOrderedConfigs('ownProxies')) {
@ -561,39 +643,26 @@ PROXY foobar.com:8080; # Not HTTP!">${conf.value || localStorage.getItem(uiRaw)
};
}
ownsList.insertBefore( li, _firstChild );
ownsList.insertBefore( li, _firstChildOrNull );
modKeyToLi[key] = li;
}
} // OWN PROXIES TAB ends.
{ // PAC MODS TAB starts.
{ // APPLY MODS PANEL starts.
const modsList = document.getElementById('pac-mods');
const _firstChild = modsList.firstChild;
const keyToLi = {};
for(const conf of pacKitchen.getOrderedConfigs('general')) {
const key = conf.key;
const iddy = 'mods-' + camelToDash(conf.key);
const li = document.createElement('li');
appendInfoRow(li, conf, `type="checkbox" ${conf.value ? 'checked' : ''}`, iddy);
keyToLi[key] = li;
modsList.insertBefore( li, _firstChild );
};
document.getElementById('apply-mods').onclick = () => {
const oldMods = pacKitchen.getPacMods();
for(const key of Object.keys(keyToLi)) {
oldMods[key] = keyToLi[key].querySelector('input').checked;
for(const key of Object.keys(modKeyToLi)) {
oldMods[key] = modKeyToLi[key].querySelector('input').checked;
};
{
// OWN PROXY
const liPs = keyToLi[customProxyStringKey];
const liPs = modKeyToLi[customProxyStringKey];
oldMods[customProxyStringKey]
= liPs.querySelector('input').checked
&& liPs.querySelector('textarea').value.trim();
@ -621,17 +690,7 @@ PROXY foobar.com:8080; # Not HTTP!">${conf.value || localStorage.getItem(uiRaw)
}
}
conduct(
'Применяем настройки...',
(cb) => pacKitchen.keepCookedNowAsync(oldMods, cb),
'Настройки применены.',
() => {
document.getElementById('apply-mods').disabled = true;
}
);
applyMods(oldMods);
};
@ -653,9 +712,9 @@ PROXY foobar.com:8080; # Not HTTP!">${conf.value || localStorage.getItem(uiRaw)
() => window.close()
);
};
}
} // PAC MODS TAB ends.
} // APPLY MODS PANEL ends.
} // KITCHEN PANELS ends.

View File

@ -16,7 +16,8 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
# Комментарии НЕ сохраняются!
# Сначала идёт список проксируемых сайтов,
# затем ==== на отдельной строке,
# затем исключённые сайты, отсортированные с конца строки.
# затем исключённые сайты.
# Сортировка с конца строки.
# ПРОКСИРОВАТЬ: