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

View File

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

View File

@ -1,13 +1,21 @@
'use strict'; 'use strict';
const START = Date.now(); const START = Date.now();
{
document.getElementById('pac-mods').onchange = function() { const enableButton = function enablebutton() {
this.classList.add('changed'); this.classList.add('changed');
document.getElementById('apply-mods').disabled = false; document.getElementById('apply-mods').disabled = false;
}; };
['pac-mods', 'own-mods'].forEach((id) => {
document.getElementById(id).onchange = enableButton;
});
}
chrome.runtime.getBackgroundPage( (backgroundPage) => chrome.runtime.getBackgroundPage( (backgroundPage) =>
backgroundPage.apis.errorHandlers.installListenersOn( backgroundPage.apis.errorHandlers.installListenersOn(
@ -131,7 +139,13 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
const inputs = document.querySelectorAll('input'); const inputs = document.querySelectorAll('input');
for ( let i = 0; i < inputs.length; i++ ) { 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 = '') => { const appendInfoRow = (mountEl, conf, inputTypeName, inputId, htmlAfterLabel = '') => {
mountEl.classList.add('info-row', 'hor-flex'); mountEl.classList.add('info-row', 'hor-flex');
if (conf.ifDisabled) {
mountEl.title = 'В РАЗРАБОТКЕ!';
}
mountEl.innerHTML = ` mountEl.innerHTML = `
<input ${inputTypeName} id="${inputId}"> <input ${inputTypeName} id="${inputId}" ${conf.ifDisabled ? 'disabled' : ''}>
<div class="label-container"> <div class="label-container">
<label for="${inputId}"> ${conf.label}</label> <label for="${inputId}">${conf.label}</label>
${htmlAfterLabel} ${htmlAfterLabel}
</div>` + (conf.desc ? infoSign(conf.desc) : infoUrl(conf.url)); </div>` + (conf.desc ? infoSign(conf.desc) : infoUrl(conf.url));
}; };
{ { // PAC-PROVIDERS starts.
const ul = document.querySelector('#list-of-providers');
const _firstChild = ul.firstChild; const ul = document.getElementById('list-of-providers');
const _firstChildOrNull = ul.firstChild;
for( for(
const provConf of antiCensorRu.getSortedEntriesForProviders() const provConf of antiCensorRu.getSortedEntriesForProviders()
) { ) {
@ -204,16 +222,11 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
); );
return false; return false;
}; };
ul.insertBefore( li, _firstChild ); ul.insertBefore( li, _firstChildOrNull );
} }
checkChosenProvider(); checkChosenProvider();
}
const radios = [].slice.apply( const radioClickHandler = function radioClickHandler(event) {
document.querySelectorAll('[name=pacProvider]')
);
for(const radio of radios) {
radio.onclick = function(event) {
if ( if (
event.target.id === ( event.target.id === (
@ -240,7 +253,14 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
} }
return false; return false;
}; };
}
document.querySelectorAll('input[name=pacProvider]').forEach((radio) => {
radio.onclick = radioClickHandler;
});
} // PAC-PROVIDERS ends.
// IF MINI // IF MINI
@ -266,275 +286,337 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
{ // KITCHEN PANELS starts. { // KITCHEN PANELS starts.
const pacKitchen = backgroundPage.apis.pacKitchen; 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. { // 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])$/; for(const conf of pacKitchen.getOrderedConfigs('exceptions')) {
if(!ValidHostnameRegex.test(host)) {
showErrors(new TypeError('Должно быть только доменное имя, без протокола, порта и пути. Попробуйте ещё раз.'));
return false;
}
return true;
}; 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 oldMods = pacKitchen.getPacMods();
const labelIfNotProxied = '✘'; oldMods[key] = this.checked;
const labelIfAuto = '↻'; 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(); }// EXC-MODS ends.
const ifInit = !event;
const currentHost = ifTriangleClicked ? '' : (originalHost || (ifInit ? '' : ' '));
setInputValue(currentHost);
let exactOpt = false; { // EXC-EDITOR starts.
let editedOpt = false;
excList.childNodes.forEach(
(opt) => {
unhideOptAndAddSpace(opt); const excEditor = document.getElementById('exc-editor');
if(opt.label === labelIfAuto) { const validateHost = function validateHost(host) {
editedOpt = opt;
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; return;
} }
if (opt.dataset.host === originalHost) { // See bug in my comment to http://stackoverflow.com/a/32394157/521957
exactOpt = opt; // 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; const ifInputEmpty = !originalHost;
excEditor.parentNode.classList.remove(noClass, yesClass); if (ifTriangleClicked || ifInputEmpty) {
// Show all opts.
const ifInputEmpty = !originalHost; if (editedOpt) {
if (ifTriangleClicked || ifInputEmpty) { // Example of editedOpt.value: 'abcde ' <- Mind the space (see unhideOptAndAddSpace)!
// Show all opts. const ifBackspacedOneChar = ifInputEmpty && editedOpt.value.length < 3;
if (editedOpt) { if (ifBackspacedOneChar) {
// Example of editedOpt.value: 'abcde ' <- Mind the space (see unhideOptAndAddSpace)! editedOpt.remove();
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; return true;
} }
// Not exact! Update!
editedOpt.remove();
}
if (!exactOpt) { if (editedOpt) {
editedOpt = addOption(originalHost, undefined); const ifEditedOptAlreadyExists = editedOpt.dataset.host === originalHost;
if (!ifClick) { if(ifEditedOptAlreadyExists) {
// New value was typed -- don't show tooltip. hideOpt(editedOpt);
hideOpt(editedOpt); return true;
}
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);
} }
}; // 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( { // Populate selector.
'Применяем исключения...',
(cb) => pacKitchen.keepCookedNowAsync(pacMods, cb),
'Исключения применены. Не забывайте о кэше!',
() => {
fixOptions();
// Window may be closed before this line executes.
renderExceptionsPanelFromExcList();
const pacMods = pacKitchen.getPacMods();
for(const host of Object.keys(pacMods.exceptions || {}).sort()) {
addOption(host, pacMods.exceptions[host]);
} }
); renderExceptionsPanelFromExcList(); // Colorize input.
return false; // Don't check before operation is finished.
}; }
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. } // 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. { // OWN PROXIES TAB starts.
const ownsList = document.getElementById('own-proxies'); const ownsList = document.getElementById('own-mods');
const _firstChild = ownsList.firstChild; const _firstChildOrNull = ownsList.firstChild;
const keyToLi = {};
const customProxyStringKey = 'customProxyStringRaw';
const uiRaw = 'ui-proxy-string-raw';
for(const conf of pacKitchen.getOrderedConfigs('ownProxies')) { 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. } // 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 = () => { document.getElementById('apply-mods').onclick = () => {
const oldMods = pacKitchen.getPacMods(); const oldMods = pacKitchen.getPacMods();
for(const key of Object.keys(keyToLi)) { for(const key of Object.keys(modKeyToLi)) {
oldMods[key] = keyToLi[key].querySelector('input').checked; oldMods[key] = modKeyToLi[key].querySelector('input').checked;
}; };
{ {
// OWN PROXY // OWN PROXY
const liPs = keyToLi[customProxyStringKey]; const liPs = modKeyToLi[customProxyStringKey];
oldMods[customProxyStringKey] oldMods[customProxyStringKey]
= liPs.querySelector('input').checked = liPs.querySelector('input').checked
&& liPs.querySelector('textarea').value.trim(); && liPs.querySelector('textarea').value.trim();
@ -621,17 +690,7 @@ PROXY foobar.com:8080; # Not HTTP!">${conf.value || localStorage.getItem(uiRaw)
} }
} }
applyMods(oldMods);
conduct(
'Применяем настройки...',
(cb) => pacKitchen.keepCookedNowAsync(oldMods, cb),
'Настройки применены.',
() => {
document.getElementById('apply-mods').disabled = true;
}
);
}; };
@ -653,9 +712,9 @@ PROXY foobar.com:8080; # Not HTTP!">${conf.value || localStorage.getItem(uiRaw)
() => window.close() () => window.close()
); );
}; }
} // PAC MODS TAB ends. } // APPLY MODS PANEL ends.
} // KITCHEN PANELS ends. } // KITCHEN PANELS ends.

View File

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