Header.coffee

This commit is contained in:
Zixaphir 2015-01-08 22:00:59 -07:00
parent 2461036a4e
commit 2dd17b5803
3 changed files with 259 additions and 177 deletions

View File

@ -4241,27 +4241,18 @@
Header = { Header = {
init: function() { init: function() {
var barFixedToggler, barPositionToggler, customNavToggler, editCustomNav, headerToggler, menuButton, scrollHeaderToggler; var barFixedToggler, barPositionToggler, box, customNavToggler, editCustomNav, headerToggler, menuButton, scrollHeaderToggler;
this.menu = new UI.Menu(); this.menu = new UI.Menu('header');
menuButton = $.el('a', { menuButton = $.el('a', {
className: 'menu-button a-icon', className: 'menu-button a-icon',
id: 'main-menu' id: 'main-menu'
}); });
barFixedToggler = $.el('label', { box = UI.checkbox.bind(UI);
innerHTML: '<input type=checkbox name="Fixed Header"> Fixed Header' barFixedToggler = box('Fixed Header', 'Fixed Header');
}); headerToggler = box('Header auto-hide', ' Auto-hide header');
headerToggler = $.el('label', { scrollHeaderToggler = box('Header auto-hide on scroll', ' Auto-hide header on scroll');
innerHTML: '<input type=checkbox name="Header auto-hide"> Auto-hide header' barPositionToggler = box('Bottom Header', ' Bottom header');
}); customNavToggler = box('Custom Board Navigation', ' Custom board navigation');
scrollHeaderToggler = $.el('label', {
innerHTML: '<input type=checkbox name="Header auto-hide on scroll"> Auto-hide header on scroll'
});
barPositionToggler = $.el('label', {
innerHTML: '<input type=checkbox name="Bottom Header"> Bottom header'
});
customNavToggler = $.el('label', {
innerHTML: '<input type=checkbox name="Custom Board Navigation"> Custom board navigation'
});
editCustomNav = $.el('a', { editCustomNav = $.el('a', {
textContent: 'Edit custom board navigation', textContent: 'Edit custom board navigation',
href: 'javascript:;' href: 'javascript:;'
@ -4274,9 +4265,8 @@
$.on(menuButton, 'click', this.menuToggle); $.on(menuButton, 'click', this.menuToggle);
$.on(this.headerToggler, 'change', this.toggleBarVisibility); $.on(this.headerToggler, 'change', this.toggleBarVisibility);
$.on(this.barFixedToggler, 'change', this.toggleBarFixed); $.on(this.barFixedToggler, 'change', this.toggleBarFixed);
$.on(this.scrollHeaderToggler, 'change', this.setHideBarOnScroll);
$.on(this.barPositionToggler, 'change', this.toggleBarPosition); $.on(this.barPositionToggler, 'change', this.toggleBarPosition);
$.on(this.headerToggler, 'change', this.toggleBarVisibility); $.on(this.scrollHeaderToggler, 'change', this.setHideBarOnScroll);
$.on(this.customNavToggler, 'change', this.toggleCustomNav); $.on(this.customNavToggler, 'change', this.toggleCustomNav);
$.on(editCustomNav, 'click', this.editCustomNav); $.on(editCustomNav, 'click', this.editCustomNav);
this.setBarFixed(Conf['Fixed Header']); this.setBarFixed(Conf['Fixed Header']);
@ -4368,23 +4358,42 @@
return Header.addNav(); return Header.addNav();
}, },
setBoardList: function() { setBoardList: function() {
var a, boardList, btn, fourchannav, fullBoardList, shortcuts, _i, _len, _ref; var a, boardList, btn, chr, fourchannav, fullBoardList, node, nodes, shortcuts, _i, _j, _len, _len1, _ref, _ref1;
fourchannav = $.id('boardNavDesktop'); fourchannav = $.id('boardNavDesktop');
Header.boardList = boardList = $.el('span', { Header.boardList = boardList = $.el('span', {
id: 'board-list', id: 'board-list'
innerHTML: "<span id=custom-board-list></span><span id=full-board-list hidden><span class='hide-board-list-container brackets-wrap'><a href=javascript:; class='hide-board-list-button'>&nbsp;-&nbsp;</a></span> " + fourchannav.innerHTML + "</span>"
}); });
_ref = $$('a', boardList); $.extend(boardList, {
innerHTML: "<span id=\"custom-board-list\"></span><span id=\"full-board-list\" hidden><span class=\"hide-board-list-container brackets-wrap\"><a href=\"javascript:;\" class=\"hide-board-list-button\">&nbsp;-&nbsp;</a></span></span>"
});
fullBoardList = $('#full-board-list', boardList);
nodes = [];
_ref = $('#boardNavDesktop > .boardList').childNodes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
a = _ref[_i]; node = _ref[_i];
switch (node.nodeName) {
case '#text':
_ref1 = node.nodeValue;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
chr = _ref1[_j];
if (chr !== ' ') {
nodes.push($.tn(chr));
}
}
break;
case 'A':
a = node.cloneNode(true);
if (Conf['JSON Navigation']) { if (Conf['JSON Navigation']) {
$.on(a, 'click', Navigate.navigate); $.on(a, 'click', Navigate.navigate);
} }
if (a.pathname.split('/')[1] === g.BOARD.ID) { if (a.pathname.split('/')[1] === g.BOARD.ID) {
a.className = 'current'; a.className = 'current';
} }
nodes.push(a);
} }
fullBoardList = $('#full-board-list', boardList); }
$.add(fullBoardList, nodes);
fullBoardList.normalize();
btn = $('.hide-board-list-button', fullBoardList); btn = $('.hide-board-list-button', fullBoardList);
$.on(btn, 'click', Header.toggleBoardList); $.on(btn, 'click', Header.toggleBoardList);
$.rm($('#navtopright', fullBoardList)); $.rm($('#navtopright', fullBoardList));
@ -4396,47 +4405,51 @@
$.add(boardList, fullBoardList); $.add(boardList, fullBoardList);
$.add(Header.bar, [Header.boardList, Header.toggle]); $.add(Header.bar, [Header.boardList, Header.toggle]);
Header.setCustomNav(Conf['Custom Board Navigation']); Header.setCustomNav(Conf['Custom Board Navigation']);
Header.generateBoardList(Conf['boardnav'].replace(/(\r\n|\n|\r)/g, ' ')); Header.generateBoardList(Conf['boardnav']);
$.sync('Custom Board Navigation', Header.setCustomNav); $.sync('Custom Board Navigation', Header.setCustomNav);
return $.sync('boardnav', Header.generateBoardList); return $.sync('boardnav', Header.generateBoardList);
}, },
generateBoardList: function(text) { generateBoardList: function(boardnav) {
var as, list, nodes, re; var as, list, nodes, re;
list = $('#custom-board-list', Header.boardList); list = $('#custom-board-list', Header.boardList);
$.rmAll(list); $.rmAll(list);
if (!text) { if (!boardnav) {
return; return;
} }
boardnav = boardnav.replace(/(\r\n|\n|\r)/g, ' ');
as = $$('#full-board-list a[title]', Header.boardList); as = $$('#full-board-list a[title]', Header.boardList);
re = /[\w@]+(-(all|title|replace|full|archive|(mode|sort|text|url):"[^"]+"(\,"[^"]+[^"]")?))*|[^\w@]+/g; re = /[\w@]+(-(all|title|replace|full|archive|(mode|sort|text|url):"[^"]+"(\,"[^"]+[^"]")?))*|[^\w@]+/g;
nodes = text.match(re).map(function(t) { nodes = boardnav.match(re).map(function(t) {
var a, board, boardID, href, m, match, type, url, _i, _len; var a, boardID, href, m, text, type, url, _i, _len;
if (/^[^\w@]/.test(t)) { if (/^[^\w@]/.test(t)) {
return $.tn(t); return $.tn(t);
} }
text = url = null;
t = t.replace(/-text:"([^"]+)"(?:,"([^"]+)")?/g, function(m0, m1, m2) {
text = m1;
url = m2;
return '';
});
if (/^toggle-all/.test(t)) { if (/^toggle-all/.test(t)) {
a = $.el('a', { a = $.el('a', {
className: 'show-board-list-button', className: 'show-board-list-button',
textContent: (match = t.match(/-text:"(.+)"/)) ? match[1] : '+', textContent: text || '+',
href: 'javascript:;' href: 'javascript:;'
}); });
$.on(a, 'click', Header.toggleBoardList); $.on(a, 'click', Header.toggleBoardList);
return a; return a;
} }
if (/^external/.test(t)) { if (/^external/.test(t)) {
if (url = t.match(/\,"(.+)"/)) {
a = $.el('a', { a = $.el('a', {
textContent: (match = t.match(/-text:"(.+)"\,/)) ? match[1] : '+', href: url || 'javascript:;',
className: 'external', textContent: text || '+',
href: url[1] className: 'external'
}); });
if (a.hostname === 'boards.4chan.org' && a.pathname.split('/')[1] === g.BOARD.ID) { if (a.hostname === 'boards.4chan.org' && a.pathname.split('/')[1] === g.BOARD.ID) {
a.className += ' current'; a.className += ' current';
} }
return a; return a;
} }
}
board = /^current/.test(t) ? g.BOARD.ID : t.match(/^[^-]+/)[0];
boardID = t.split('-')[0]; boardID = t.split('-')[0];
if (boardID === 'current') { if (boardID === 'current') {
boardID = g.BOARD.ID; boardID = g.BOARD.ID;
@ -4449,9 +4462,6 @@
a = a.cloneNode(); a = a.cloneNode();
break; break;
} }
if (a.parentNode) {
return $.tn(boardID);
}
if (Conf['JSON Navigation']) { if (Conf['JSON Navigation']) {
$.on(a, 'click', Navigate.navigate); $.on(a, 'click', Navigate.navigate);
} }
@ -4503,7 +4513,8 @@
} }
return a; return a;
}); });
return $.add(list, nodes); $.add(list, nodes);
return $.ready(CatalogLinks.initBoardList);
}, },
toggleBoardList: function() { toggleBoardList: function() {
var bar, custom, full, showBoardList; var bar, custom, full, showBoardList;
@ -4532,14 +4543,24 @@
}, },
setBarVisibility: function(hide) { setBarVisibility: function(hide) {
Header.headerToggler.checked = hide; Header.headerToggler.checked = hide;
return (hide ? $.addClass : $.rmClass)(Header.bar, 'autohide'); $.event('CloseMenu');
if (hide) {
$.addClass(Header.bar, 'autohide');
return $.addClass(doc, 'autohide');
} else {
$.rmClass(Header.bar, 'autohide');
return $.rmClass(doc, 'autohide');
}
}, },
toggleBarVisibility: function(e) { toggleBarVisibility: function() {
var hide; var hide, message;
hide = this.checked; hide = this.nodeName === 'INPUT' ? this.checked : !$.hasClass(Header.bar, 'autohide');
Conf['Header auto-hide'] = hide; Conf['Header auto-hide'] = hide;
$.set('Header auto-hide', hide); $.set('Header auto-hide', hide);
return Header.setBarVisibility(hide); Header.setBarVisibility(hide);
Header.headerToggler = hide;
message = "The header bar will " + (hide ? 'automatically hide itself.' : 'remain visible.');
return new Notice('info', message, 2);
}, },
setHideBarOnScroll: function(hide) { setHideBarOnScroll: function(hide) {
Header.scrollHeaderToggler.checked = hide; Header.scrollHeaderToggler.checked = hide;
@ -4588,8 +4609,8 @@
Header.customNavToggler.checked = show; Header.customNavToggler.checked = show;
cust = $('#custom-board-list', Header.bar); cust = $('#custom-board-list', Header.bar);
full = $('#full-board-list', Header.bar); full = $('#full-board-list', Header.bar);
btn = $('.hide-board-list-button', full); btn = $('.hide-board-list-container', full);
return _ref = show ? [false, true] : [true, false], cust.hidden = _ref[0], full.hidden = _ref[1], _ref; return _ref = show ? [false, true, false] : [true, false, true], cust.hidden = _ref[0], full.hidden = _ref[1], btn.hidden = _ref[2], _ref;
}, },
toggleCustomNav: function() { toggleCustomNav: function() {
$.cb.checked.call(this); $.cb.checked.call(this);
@ -4599,7 +4620,7 @@
var settings; var settings;
Settings.open('Advanced'); Settings.open('Advanced');
settings = $.id('fourchanx-settings'); settings = $.id('fourchanx-settings');
return $('input[name=boardnav]', settings).focus(); return $('[name=boardnav]', settings).focus();
}, },
hashScroll: function() { hashScroll: function() {
var hash, post; var hash, post;
@ -4607,7 +4628,7 @@
if (!(/^p\d+$/.test(hash) && (post = $.id(hash)))) { if (!(/^p\d+$/.test(hash) && (post = $.id(hash)))) {
return; return;
} }
if ((Get.postFromNode(post)).isHidden) { if ((Get.postFromRoot(post)).isHidden) {
return; return;
} }
return Header.scrollTo(post); return Header.scrollTo(post);
@ -4674,6 +4695,9 @@
}, },
isNodeVisible: function(node) { isNodeVisible: function(node) {
var height; var height;
if (d.hidden || !doc.contains(node)) {
return false;
}
height = node.getBoundingClientRect().height; height = node.getBoundingClientRect().height;
return Header.getTopOf(node) + height >= 0 && Header.getBottomOf(node) + height >= 0; return Header.getTopOf(node) + height >= 0 && Header.getBottomOf(node) + height >= 0;
}, },
@ -4715,7 +4739,7 @@
return; return;
} }
el = $.el('span', { el = $.el('span', {
innerHTML: "Desktop notification permissions are not granted.\n[<a href='https://github.com/MayhemYDG/4chan-x/wiki/FAQ#desktop-notifications' target=_blank>FAQ</a>]<br>\n<button>Authorize</button> or <button>Disable</button>" innerHTML: E(g.NAME) + " needs your permission to show desktop notifications. [<a href=\"" + E(g.FAQ) + "#why-is-4chan-x-asking-for-permission-to-show-desktop-notifications\" target=\"_blank\">FAQ</a>]<br><button>Authorize</button> or <button>Disable</button>"
}); });
_ref = $$('button', el), authorize = _ref[0], disable = _ref[1]; _ref = $$('button', el), authorize = _ref[0], disable = _ref[1];
$.on(authorize, 'click', function() { $.on(authorize, 'click', function() {

View File

@ -4270,27 +4270,18 @@
Header = { Header = {
init: function() { init: function() {
var barFixedToggler, barPositionToggler, customNavToggler, editCustomNav, headerToggler, menuButton, scrollHeaderToggler; var barFixedToggler, barPositionToggler, box, customNavToggler, editCustomNav, headerToggler, menuButton, scrollHeaderToggler;
this.menu = new UI.Menu(); this.menu = new UI.Menu('header');
menuButton = $.el('a', { menuButton = $.el('a', {
className: 'menu-button a-icon', className: 'menu-button a-icon',
id: 'main-menu' id: 'main-menu'
}); });
barFixedToggler = $.el('label', { box = UI.checkbox.bind(UI);
innerHTML: '<input type=checkbox name="Fixed Header"> Fixed Header' barFixedToggler = box('Fixed Header', 'Fixed Header');
}); headerToggler = box('Header auto-hide', ' Auto-hide header');
headerToggler = $.el('label', { scrollHeaderToggler = box('Header auto-hide on scroll', ' Auto-hide header on scroll');
innerHTML: '<input type=checkbox name="Header auto-hide"> Auto-hide header' barPositionToggler = box('Bottom Header', ' Bottom header');
}); customNavToggler = box('Custom Board Navigation', ' Custom board navigation');
scrollHeaderToggler = $.el('label', {
innerHTML: '<input type=checkbox name="Header auto-hide on scroll"> Auto-hide header on scroll'
});
barPositionToggler = $.el('label', {
innerHTML: '<input type=checkbox name="Bottom Header"> Bottom header'
});
customNavToggler = $.el('label', {
innerHTML: '<input type=checkbox name="Custom Board Navigation"> Custom board navigation'
});
editCustomNav = $.el('a', { editCustomNav = $.el('a', {
textContent: 'Edit custom board navigation', textContent: 'Edit custom board navigation',
href: 'javascript:;' href: 'javascript:;'
@ -4303,9 +4294,8 @@
$.on(menuButton, 'click', this.menuToggle); $.on(menuButton, 'click', this.menuToggle);
$.on(this.headerToggler, 'change', this.toggleBarVisibility); $.on(this.headerToggler, 'change', this.toggleBarVisibility);
$.on(this.barFixedToggler, 'change', this.toggleBarFixed); $.on(this.barFixedToggler, 'change', this.toggleBarFixed);
$.on(this.scrollHeaderToggler, 'change', this.setHideBarOnScroll);
$.on(this.barPositionToggler, 'change', this.toggleBarPosition); $.on(this.barPositionToggler, 'change', this.toggleBarPosition);
$.on(this.headerToggler, 'change', this.toggleBarVisibility); $.on(this.scrollHeaderToggler, 'change', this.setHideBarOnScroll);
$.on(this.customNavToggler, 'change', this.toggleCustomNav); $.on(this.customNavToggler, 'change', this.toggleCustomNav);
$.on(editCustomNav, 'click', this.editCustomNav); $.on(editCustomNav, 'click', this.editCustomNav);
this.setBarFixed(Conf['Fixed Header']); this.setBarFixed(Conf['Fixed Header']);
@ -4397,23 +4387,42 @@
return Header.addNav(); return Header.addNav();
}, },
setBoardList: function() { setBoardList: function() {
var a, boardList, btn, fourchannav, fullBoardList, shortcuts, _i, _len, _ref; var a, boardList, btn, chr, fourchannav, fullBoardList, node, nodes, shortcuts, _i, _j, _len, _len1, _ref, _ref1;
fourchannav = $.id('boardNavDesktop'); fourchannav = $.id('boardNavDesktop');
Header.boardList = boardList = $.el('span', { Header.boardList = boardList = $.el('span', {
id: 'board-list', id: 'board-list'
innerHTML: "<span id=custom-board-list></span><span id=full-board-list hidden><span class='hide-board-list-container brackets-wrap'><a href=javascript:; class='hide-board-list-button'>&nbsp;-&nbsp;</a></span> " + fourchannav.innerHTML + "</span>"
}); });
_ref = $$('a', boardList); $.extend(boardList, {
innerHTML: "<span id=\"custom-board-list\"></span><span id=\"full-board-list\" hidden><span class=\"hide-board-list-container brackets-wrap\"><a href=\"javascript:;\" class=\"hide-board-list-button\">&nbsp;-&nbsp;</a></span></span>"
});
fullBoardList = $('#full-board-list', boardList);
nodes = [];
_ref = $('#boardNavDesktop > .boardList').childNodes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
a = _ref[_i]; node = _ref[_i];
switch (node.nodeName) {
case '#text':
_ref1 = node.nodeValue;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
chr = _ref1[_j];
if (chr !== ' ') {
nodes.push($.tn(chr));
}
}
break;
case 'A':
a = node.cloneNode(true);
if (Conf['JSON Navigation']) { if (Conf['JSON Navigation']) {
$.on(a, 'click', Navigate.navigate); $.on(a, 'click', Navigate.navigate);
} }
if (a.pathname.split('/')[1] === g.BOARD.ID) { if (a.pathname.split('/')[1] === g.BOARD.ID) {
a.className = 'current'; a.className = 'current';
} }
nodes.push(a);
} }
fullBoardList = $('#full-board-list', boardList); }
$.add(fullBoardList, nodes);
fullBoardList.normalize();
btn = $('.hide-board-list-button', fullBoardList); btn = $('.hide-board-list-button', fullBoardList);
$.on(btn, 'click', Header.toggleBoardList); $.on(btn, 'click', Header.toggleBoardList);
$.rm($('#navtopright', fullBoardList)); $.rm($('#navtopright', fullBoardList));
@ -4425,47 +4434,51 @@
$.add(boardList, fullBoardList); $.add(boardList, fullBoardList);
$.add(Header.bar, [Header.boardList, Header.toggle]); $.add(Header.bar, [Header.boardList, Header.toggle]);
Header.setCustomNav(Conf['Custom Board Navigation']); Header.setCustomNav(Conf['Custom Board Navigation']);
Header.generateBoardList(Conf['boardnav'].replace(/(\r\n|\n|\r)/g, ' ')); Header.generateBoardList(Conf['boardnav']);
$.sync('Custom Board Navigation', Header.setCustomNav); $.sync('Custom Board Navigation', Header.setCustomNav);
return $.sync('boardnav', Header.generateBoardList); return $.sync('boardnav', Header.generateBoardList);
}, },
generateBoardList: function(text) { generateBoardList: function(boardnav) {
var as, list, nodes, re; var as, list, nodes, re;
list = $('#custom-board-list', Header.boardList); list = $('#custom-board-list', Header.boardList);
$.rmAll(list); $.rmAll(list);
if (!text) { if (!boardnav) {
return; return;
} }
boardnav = boardnav.replace(/(\r\n|\n|\r)/g, ' ');
as = $$('#full-board-list a[title]', Header.boardList); as = $$('#full-board-list a[title]', Header.boardList);
re = /[\w@]+(-(all|title|replace|full|archive|(mode|sort|text|url):"[^"]+"(\,"[^"]+[^"]")?))*|[^\w@]+/g; re = /[\w@]+(-(all|title|replace|full|archive|(mode|sort|text|url):"[^"]+"(\,"[^"]+[^"]")?))*|[^\w@]+/g;
nodes = text.match(re).map(function(t) { nodes = boardnav.match(re).map(function(t) {
var a, board, boardID, href, m, match, type, url, _i, _len; var a, boardID, href, m, text, type, url, _i, _len;
if (/^[^\w@]/.test(t)) { if (/^[^\w@]/.test(t)) {
return $.tn(t); return $.tn(t);
} }
text = url = null;
t = t.replace(/-text:"([^"]+)"(?:,"([^"]+)")?/g, function(m0, m1, m2) {
text = m1;
url = m2;
return '';
});
if (/^toggle-all/.test(t)) { if (/^toggle-all/.test(t)) {
a = $.el('a', { a = $.el('a', {
className: 'show-board-list-button', className: 'show-board-list-button',
textContent: (match = t.match(/-text:"(.+)"/)) ? match[1] : '+', textContent: text || '+',
href: 'javascript:;' href: 'javascript:;'
}); });
$.on(a, 'click', Header.toggleBoardList); $.on(a, 'click', Header.toggleBoardList);
return a; return a;
} }
if (/^external/.test(t)) { if (/^external/.test(t)) {
if (url = t.match(/\,"(.+)"/)) {
a = $.el('a', { a = $.el('a', {
textContent: (match = t.match(/-text:"(.+)"\,/)) ? match[1] : '+', href: url || 'javascript:;',
className: 'external', textContent: text || '+',
href: url[1] className: 'external'
}); });
if (a.hostname === 'boards.4chan.org' && a.pathname.split('/')[1] === g.BOARD.ID) { if (a.hostname === 'boards.4chan.org' && a.pathname.split('/')[1] === g.BOARD.ID) {
a.className += ' current'; a.className += ' current';
} }
return a; return a;
} }
}
board = /^current/.test(t) ? g.BOARD.ID : t.match(/^[^-]+/)[0];
boardID = t.split('-')[0]; boardID = t.split('-')[0];
if (boardID === 'current') { if (boardID === 'current') {
boardID = g.BOARD.ID; boardID = g.BOARD.ID;
@ -4478,9 +4491,6 @@
a = a.cloneNode(); a = a.cloneNode();
break; break;
} }
if (a.parentNode) {
return $.tn(boardID);
}
if (Conf['JSON Navigation']) { if (Conf['JSON Navigation']) {
$.on(a, 'click', Navigate.navigate); $.on(a, 'click', Navigate.navigate);
} }
@ -4532,7 +4542,8 @@
} }
return a; return a;
}); });
return $.add(list, nodes); $.add(list, nodes);
return $.ready(CatalogLinks.initBoardList);
}, },
toggleBoardList: function() { toggleBoardList: function() {
var bar, custom, full, showBoardList; var bar, custom, full, showBoardList;
@ -4561,14 +4572,24 @@
}, },
setBarVisibility: function(hide) { setBarVisibility: function(hide) {
Header.headerToggler.checked = hide; Header.headerToggler.checked = hide;
return (hide ? $.addClass : $.rmClass)(Header.bar, 'autohide'); $.event('CloseMenu');
if (hide) {
$.addClass(Header.bar, 'autohide');
return $.addClass(doc, 'autohide');
} else {
$.rmClass(Header.bar, 'autohide');
return $.rmClass(doc, 'autohide');
}
}, },
toggleBarVisibility: function(e) { toggleBarVisibility: function() {
var hide; var hide, message;
hide = this.checked; hide = this.nodeName === 'INPUT' ? this.checked : !$.hasClass(Header.bar, 'autohide');
Conf['Header auto-hide'] = hide; Conf['Header auto-hide'] = hide;
$.set('Header auto-hide', hide); $.set('Header auto-hide', hide);
return Header.setBarVisibility(hide); Header.setBarVisibility(hide);
Header.headerToggler = hide;
message = "The header bar will " + (hide ? 'automatically hide itself.' : 'remain visible.');
return new Notice('info', message, 2);
}, },
setHideBarOnScroll: function(hide) { setHideBarOnScroll: function(hide) {
Header.scrollHeaderToggler.checked = hide; Header.scrollHeaderToggler.checked = hide;
@ -4617,8 +4638,8 @@
Header.customNavToggler.checked = show; Header.customNavToggler.checked = show;
cust = $('#custom-board-list', Header.bar); cust = $('#custom-board-list', Header.bar);
full = $('#full-board-list', Header.bar); full = $('#full-board-list', Header.bar);
btn = $('.hide-board-list-button', full); btn = $('.hide-board-list-container', full);
return _ref = show ? [false, true] : [true, false], cust.hidden = _ref[0], full.hidden = _ref[1], _ref; return _ref = show ? [false, true, false] : [true, false, true], cust.hidden = _ref[0], full.hidden = _ref[1], btn.hidden = _ref[2], _ref;
}, },
toggleCustomNav: function() { toggleCustomNav: function() {
$.cb.checked.call(this); $.cb.checked.call(this);
@ -4628,7 +4649,7 @@
var settings; var settings;
Settings.open('Advanced'); Settings.open('Advanced');
settings = $.id('fourchanx-settings'); settings = $.id('fourchanx-settings');
return $('input[name=boardnav]', settings).focus(); return $('[name=boardnav]', settings).focus();
}, },
hashScroll: function() { hashScroll: function() {
var hash, post; var hash, post;
@ -4636,7 +4657,7 @@
if (!(/^p\d+$/.test(hash) && (post = $.id(hash)))) { if (!(/^p\d+$/.test(hash) && (post = $.id(hash)))) {
return; return;
} }
if ((Get.postFromNode(post)).isHidden) { if ((Get.postFromRoot(post)).isHidden) {
return; return;
} }
return Header.scrollTo(post); return Header.scrollTo(post);
@ -4703,6 +4724,9 @@
}, },
isNodeVisible: function(node) { isNodeVisible: function(node) {
var height; var height;
if (d.hidden || !doc.contains(node)) {
return false;
}
height = node.getBoundingClientRect().height; height = node.getBoundingClientRect().height;
return Header.getTopOf(node) + height >= 0 && Header.getBottomOf(node) + height >= 0; return Header.getTopOf(node) + height >= 0 && Header.getBottomOf(node) + height >= 0;
}, },
@ -4744,7 +4768,7 @@
return; return;
} }
el = $.el('span', { el = $.el('span', {
innerHTML: "Desktop notification permissions are not granted.\n[<a href='https://github.com/MayhemYDG/4chan-x/wiki/FAQ#desktop-notifications' target=_blank>FAQ</a>]<br>\n<button>Authorize</button> or <button>Disable</button>" innerHTML: E(g.NAME) + " needs your permission to show desktop notifications. [<a href=\"" + E(g.FAQ) + "#why-is-4chan-x-asking-for-permission-to-show-desktop-notifications\" target=\"_blank\">FAQ</a>]<br><button>Authorize</button> or <button>Disable</button>"
}); });
_ref = $$('button', el), authorize = _ref[0], disable = _ref[1]; _ref = $$('button', el), authorize = _ref[0], disable = _ref[1];
$.on(authorize, 'click', function() { $.on(authorize, 'click', function() {

View File

@ -1,21 +1,19 @@
Header = Header =
init: -> init: ->
@menu = new UI.Menu() @menu = new UI.Menu 'header'
menuButton = $.el 'a', menuButton = $.el 'a',
className: 'menu-button a-icon' className: 'menu-button a-icon'
id: 'main-menu' id: 'main-menu'
barFixedToggler = $.el 'label', box = UI.checkbox.bind UI
innerHTML: '<input type=checkbox name="Fixed Header"> Fixed Header'
headerToggler = $.el 'label', barFixedToggler = box 'Fixed Header', 'Fixed Header'
innerHTML: '<input type=checkbox name="Header auto-hide"> Auto-hide header' headerToggler = box 'Header auto-hide', ' Auto-hide header'
scrollHeaderToggler = $.el 'label', scrollHeaderToggler = box 'Header auto-hide on scroll', ' Auto-hide header on scroll'
innerHTML: '<input type=checkbox name="Header auto-hide on scroll"> Auto-hide header on scroll' barPositionToggler = box 'Bottom Header', ' Bottom header'
barPositionToggler = $.el 'label', customNavToggler = box 'Custom Board Navigation', ' Custom board navigation'
innerHTML: '<input type=checkbox name="Bottom Header"> Bottom header'
customNavToggler = $.el 'label',
innerHTML: '<input type=checkbox name="Custom Board Navigation"> Custom board navigation'
editCustomNav = $.el 'a', editCustomNav = $.el 'a',
textContent: 'Edit custom board navigation' textContent: 'Edit custom board navigation'
href: 'javascript:;' href: 'javascript:;'
@ -29,9 +27,8 @@ Header =
$.on menuButton, 'click', @menuToggle $.on menuButton, 'click', @menuToggle
$.on @headerToggler, 'change', @toggleBarVisibility $.on @headerToggler, 'change', @toggleBarVisibility
$.on @barFixedToggler, 'change', @toggleBarFixed $.on @barFixedToggler, 'change', @toggleBarFixed
$.on @scrollHeaderToggler, 'change', @setHideBarOnScroll
$.on @barPositionToggler, 'change', @toggleBarPosition $.on @barPositionToggler, 'change', @toggleBarPosition
$.on @headerToggler, 'change', @toggleBarVisibility $.on @scrollHeaderToggler, 'change', @setHideBarOnScroll
$.on @customNavToggler, 'change', @toggleCustomNav $.on @customNavToggler, 'change', @toggleCustomNav
$.on editCustomNav, 'click', @editCustomNav $.on editCustomNav, 'click', @editCustomNav
@ -47,7 +44,8 @@ Header =
@addShortcut menuButton @addShortcut menuButton
@menu.addEntry @menu.addEntry
el: $.el 'span', textContent: 'Header' el: $.el 'span',
textContent: 'Header'
order: 107 order: 107
subEntries: [ subEntries: [
el: barFixedToggler el: barFixedToggler
@ -110,14 +108,32 @@ Header =
fourchannav = $.id 'boardNavDesktop' fourchannav = $.id 'boardNavDesktop'
Header.boardList = boardList = $.el 'span', Header.boardList = boardList = $.el 'span',
id: 'board-list' id: 'board-list'
innerHTML: "<span id=custom-board-list></span><span id=full-board-list hidden><span class='hide-board-list-container brackets-wrap'><a href=javascript:; class='hide-board-list-button'>&nbsp;-&nbsp;</a></span> #{fourchannav.innerHTML}</span>" $.extend boardList, <%= html(
'<span id="custom-board-list"></span>' +
'<span id="full-board-list" hidden>' +
'<span class="hide-board-list-container brackets-wrap">' +
'<a href="javascript:;" class="hide-board-list-button">&nbsp;-&nbsp;</a>' +
'</span>' +
'</span>'
) %>
for a in $$ 'a', boardList
fullBoardList = $ '#full-board-list', boardList
nodes = []
for node in $('#boardNavDesktop > .boardList').childNodes
switch node.nodeName
when '#text'
for chr in node.nodeValue when chr isnt ' '
nodes.push $.tn chr
when 'A'
a = node.cloneNode true
if Conf['JSON Navigation'] if Conf['JSON Navigation']
$.on a, 'click', Navigate.navigate $.on a, 'click', Navigate.navigate
if a.pathname.split('/')[1] is g.BOARD.ID a.className = 'current' if a.pathname.split('/')[1] is g.BOARD.ID
a.className = 'current' nodes.push a
fullBoardList = $ '#full-board-list', boardList $.add fullBoardList, nodes
fullBoardList.normalize()
btn = $ '.hide-board-list-button', fullBoardList btn = $ '.hide-board-list-button', fullBoardList
$.on btn, 'click', Header.toggleBoardList $.on btn, 'click', Header.toggleBoardList
@ -134,50 +150,50 @@ Header =
$.add Header.bar, [Header.boardList, Header.toggle] $.add Header.bar, [Header.boardList, Header.toggle]
Header.setCustomNav Conf['Custom Board Navigation'] Header.setCustomNav Conf['Custom Board Navigation']
Header.generateBoardList Conf['boardnav'].replace /(\r\n|\n|\r)/g, ' ' Header.generateBoardList Conf['boardnav']
$.sync 'Custom Board Navigation', Header.setCustomNav $.sync 'Custom Board Navigation', Header.setCustomNav
$.sync 'boardnav', Header.generateBoardList $.sync 'boardnav', Header.generateBoardList
generateBoardList: (text) -> generateBoardList: (boardnav) ->
list = $ '#custom-board-list', Header.boardList list = $ '#custom-board-list', Header.boardList
$.rmAll list $.rmAll list
return unless text return unless boardnav
boardnav = boardnav.replace /(\r\n|\n|\r)/g, ' '
as = $$ '#full-board-list a[title]', Header.boardList as = $$ '#full-board-list a[title]', Header.boardList
re = /[\w@]+(-(all|title|replace|full|archive|(mode|sort|text|url):"[^"]+"(\,"[^"]+[^"]")?))*|[^\w@]+/g re = /[\w@]+(-(all|title|replace|full|archive|(mode|sort|text|url):"[^"]+"(\,"[^"]+[^"]")?))*|[^\w@]+/g
nodes = text.match(re).map (t) -> nodes = boardnav.match(re).map (t) ->
if /^[^\w@]/.test t if /^[^\w@]/.test t
return $.tn t return $.tn t
text = url = null
t = t.replace /-text:"([^"]+)"(?:,"([^"]+)")?/g, (m0, m1, m2) ->
text = m1
url = m2
''
if /^toggle-all/.test t if /^toggle-all/.test t
a = $.el 'a', a = $.el 'a',
className: 'show-board-list-button' className: 'show-board-list-button'
textContent: if match = t.match /-text:"(.+)"/ then match[1] else '+' textContent: text or '+'
href: 'javascript:;' href: 'javascript:;'
$.on a, 'click', Header.toggleBoardList $.on a, 'click', Header.toggleBoardList
return a return a
if /^external/.test t if /^external/.test t
if url = t.match /\,"(.+)"/
a = $.el 'a', a = $.el 'a',
textContent: if match = t.match /-text:"(.+)"\,/ then match[1] else '+' href: url or 'javascript:;'
textContent: text or '+'
className: 'external' className: 'external'
href: url[1]
if a.hostname is 'boards.4chan.org' and a.pathname.split('/')[1] is g.BOARD.ID if a.hostname is 'boards.4chan.org' and a.pathname.split('/')[1] is g.BOARD.ID
a.className += ' current' a.className += ' current'
return a return a
board = if /^current/.test t
g.BOARD.ID
else
t.match(/^[^-]+/)[0]
boardID = t.split('-')[0] boardID = t.split('-')[0]
boardID = g.BOARD.ID if boardID is 'current' boardID = g.BOARD.ID if boardID is 'current'
for a in as when a.textContent is boardID for a in as when a.textContent is boardID
a = a.cloneNode() a = a.cloneNode()
break break
return $.tn boardID if a.parentNode # Not a clone.
if Conf['JSON Navigation'] if Conf['JSON Navigation']
$.on a, 'click', Navigate.navigate $.on a, 'click', Navigate.navigate
@ -218,6 +234,7 @@ Header =
a a
$.add list, nodes $.add list, nodes
$.ready CatalogLinks.initBoardList
toggleBoardList: -> toggleBoardList: ->
{bar} = Header {bar} = Header
@ -246,13 +263,29 @@ Header =
setBarVisibility: (hide) -> setBarVisibility: (hide) ->
Header.headerToggler.checked = hide Header.headerToggler.checked = hide
(if hide then $.addClass else $.rmClass) Header.bar, 'autohide' $.event 'CloseMenu'
if hide
$.addClass Header.bar, 'autohide'
$.addClass doc, 'autohide'
else
$.rmClass Header.bar, 'autohide'
$.rmClass doc, 'autohide'
toggleBarVisibility: (e) -> toggleBarVisibility: ->
hide = @checked hide = if @nodeName is 'INPUT'
@checked
else
!$.hasClass Header.bar, 'autohide'
Conf['Header auto-hide'] = hide Conf['Header auto-hide'] = hide
$.set 'Header auto-hide', hide $.set 'Header auto-hide', hide
Header.setBarVisibility hide Header.setBarVisibility hide
# set checked status if called from keybind
Header.headerToggler = hide
message = "The header bar will #{if hide
'automatically hide itself.'
else
'remain visible.'}"
new Notice 'info', message, 2
setHideBarOnScroll: (hide) -> setHideBarOnScroll: (hide) ->
Header.scrollHeaderToggler.checked = hide Header.scrollHeaderToggler.checked = hide
@ -304,11 +337,11 @@ Header =
Header.customNavToggler.checked = show Header.customNavToggler.checked = show
cust = $ '#custom-board-list', Header.bar cust = $ '#custom-board-list', Header.bar
full = $ '#full-board-list', Header.bar full = $ '#full-board-list', Header.bar
btn = $ '.hide-board-list-button', full btn = $ '.hide-board-list-container', full
[cust.hidden, full.hidden] = if show [cust.hidden, full.hidden, btn.hidden] = if show
[false, true] [false, true, false]
else else
[true, false] [true, false, true]
toggleCustomNav: -> toggleCustomNav: ->
$.cb.checked.call @ $.cb.checked.call @
@ -317,12 +350,12 @@ Header =
editCustomNav: -> editCustomNav: ->
Settings.open 'Advanced' Settings.open 'Advanced'
settings = $.id 'fourchanx-settings' settings = $.id 'fourchanx-settings'
$('input[name=boardnav]', settings).focus() $('[name=boardnav]', settings).focus()
hashScroll: -> hashScroll: ->
hash = @location.hash[1..] hash = @location.hash[1..]
return unless /^p\d+$/.test(hash) and post = $.id hash return unless /^p\d+$/.test(hash) and post = $.id hash
return if (Get.postFromNode post).isHidden return if (Get.postFromRoot post).isHidden
Header.scrollTo post Header.scrollTo post
scrollTo: (root, down, needed) -> scrollTo: (root, down, needed) ->
@ -364,6 +397,7 @@ Header =
bottom bottom
isNodeVisible: (node) -> isNodeVisible: (node) ->
return false if d.hidden or !doc.contains node
{height} = node.getBoundingClientRect() {height} = node.getBoundingClientRect()
Header.getTopOf(node) + height >= 0 and Header.getBottomOf(node) + height >= 0 Header.getTopOf(node) + height >= 0 and Header.getBottomOf(node) + height >= 0
@ -401,11 +435,11 @@ Header =
return return
el = $.el 'span', el = $.el 'span',
innerHTML: """ <%= html(
Desktop notification permissions are not granted. '${g.NAME} needs your permission to show desktop notifications. ' +
[<a href='https://github.com/MayhemYDG/4chan-x/wiki/FAQ#desktop-notifications' target=_blank>FAQ</a>]<br> '[<a href="${g.FAQ}#why-is-4chan-x-asking-for-permission-to-show-desktop-notifications" target="_blank">FAQ</a>]<br>' +
<button>Authorize</button> or <button>Disable</button> '<button>Authorize</button> or <button>Disable</button>'
""" ) %>
[authorize, disable] = $$ 'button', el [authorize, disable] = $$ 'button', el
$.on authorize, 'click', -> $.on authorize, 'click', ->
Notification.requestPermission (status) -> Notification.requestPermission (status) ->