diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css
index 4ad9e57b..6e688190 100644
--- a/copyparty/web/browser.css
+++ b/copyparty/web/browser.css
@@ -629,6 +629,9 @@ input.eq_gain {
margin-top: .5em;
padding: 1.3em .3em;
}
+#ico1 {
+ cursor: pointer;
+}
@@ -1076,7 +1079,8 @@ a.btn,
#rui label,
#modal-ok,
#modal-ng,
-#ops {
+#ops,
+#ico1 {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js
index c3392e37..6e793c34 100644
--- a/copyparty/web/browser.js
+++ b/copyparty/web/browser.js
@@ -168,6 +168,15 @@ ebi('op_cfg').innerHTML = (
' \n' +
' \n' +
'\n' +
+ '
\n' +
'\n' +
''
);
diff --git a/copyparty/web/up2k.js b/copyparty/web/up2k.js
index cdcd771d..0f5f3c85 100644
--- a/copyparty/web/up2k.js
+++ b/copyparty/web/up2k.js
@@ -2012,6 +2012,15 @@ function warn_uploader_busy(e) {
tt.init();
+favico.init();
+ebi('ico1').onclick = function () {
+ var a = favico.txt == this.textContent;
+ swrite('icot', a ? 'c' : this.textContent);
+ swrite('icof', a ? null : '000');
+ swrite('icob', a ? null : '');
+ favico.init();
+};
+
if (QS('#op_up2k.act'))
goto_up2k();
diff --git a/copyparty/web/util.js b/copyparty/web/util.js
index a5c927c8..6fb3512f 100644
--- a/copyparty/web/util.js
+++ b/copyparty/web/util.js
@@ -621,9 +621,9 @@ function icfg_get(name, defval) {
}
function fcfg_get(name, defval) {
- var o = ebi(name);
+ var o = ebi(name),
+ val = parseFloat(sread(name));
- var val = parseFloat(sread(name));
if (isNaN(val))
return parseFloat(o ? o.value : defval);
@@ -633,6 +633,19 @@ function fcfg_get(name, defval) {
return val;
}
+function scfg_get(name, defval) {
+ var o = ebi(name),
+ val = sread(name);
+
+ if (val === null)
+ val = defval;
+
+ if (o)
+ o.value = val;
+
+ return val;
+}
+
function bcfg_get(name, defval) {
var o = ebi(name);
if (!o)
@@ -684,6 +697,21 @@ function bcfg_bind(obj, oname, cname, defval, cb, un_ev) {
return v;
}
+function scfg_bind(obj, oname, cname, defval, cb) {
+ var v = scfg_get(cname, defval),
+ el = ebi(cname);
+
+ obj[oname] = v;
+ if (el)
+ el.oninput = function (e) {
+ swrite(cname, obj[oname] = this.value);
+ if (cb)
+ cb(obj[oname]);
+ };
+
+ return v;
+}
+
function hist_push(url) {
console.log("h-push " + url);
@@ -849,16 +877,7 @@ var tt = (function () {
}
r.init = function () {
- var ttb = ebi('tooltips');
- if (ttb) {
- ttb.onclick = function (e) {
- ev(e);
- r.en = !r.en;
- bcfg_set('tooltips', r.en);
- r.init();
- };
- r.en = bcfg_get('tooltips', true)
- }
+ bcfg_bind(r, 'en', 'tooltips', r.en, r.init);
r.att(document);
};
@@ -1181,3 +1200,54 @@ function repl(e) {
}
if (ebi('repl'))
ebi('repl').onclick = repl;
+
+
+var favico = (function () {
+ var r = {};
+ r.en = true;
+
+ function gx(txt) {
+ return (
+ '\n' +
+ ''
+ );
+ }
+
+ r.upd = function () {
+ var i = QS('link[rel="icon"]'), b64;
+ if (!r.txt)
+ return;
+
+ try {
+ b64 = btoa(gx(r.txt));
+ }
+ catch (ex) {
+ b64 = encodeURIComponent(r.txt).replace(/%([0-9A-F]{2})/g,
+ function x(m, v) { return String.fromCharCode('0x' + v); });
+
+ b64 = btoa(gx(unescape(encodeURIComponent(r.txt))));
+ }
+
+ if (!i) {
+ i = mknod('link');
+ i.rel = 'icon';
+ document.head.appendChild(i);
+ }
+ i.href = 'data:image/svg+xml;base64,' + b64;
+ };
+
+ r.init = function () {
+ clearTimeout(r.to);
+ scfg_bind(r, 'txt', 'icot', '', r.upd);
+ scfg_bind(r, 'fg', 'icof', 'fc5', r.upd);
+ scfg_bind(r, 'bg', 'icob', '333', r.upd);
+ r.upd();
+ };
+
+ r.to = setTimeout(r.init, 100);
+ return r;
+})();