More fixes
Still no header or posts, but no errors either. :D
This commit is contained in:
parent
872612ad9f
commit
54c5b59946
@ -3872,15 +3872,22 @@
|
||||
};
|
||||
|
||||
DataBoard.prototype["delete"] = function(_arg) {
|
||||
var boardID, postID, threadID;
|
||||
var boardID, postID, threadID, _ref;
|
||||
boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID;
|
||||
$.forceSync(this.key);
|
||||
if (postID) {
|
||||
if (!((_ref = this.data.boards[boardID]) != null ? _ref[threadID] : void 0)) {
|
||||
return;
|
||||
}
|
||||
delete this.data.boards[boardID][threadID][postID];
|
||||
this.deleteIfEmpty({
|
||||
boardID: boardID,
|
||||
threadID: threadID
|
||||
});
|
||||
} else if (threadID) {
|
||||
if (!this.data.boards[boardID]) {
|
||||
return;
|
||||
}
|
||||
delete this.data.boards[boardID][threadID];
|
||||
this.deleteIfEmpty({
|
||||
boardID: boardID
|
||||
@ -3894,6 +3901,7 @@
|
||||
DataBoard.prototype.deleteIfEmpty = function(_arg) {
|
||||
var boardID, threadID;
|
||||
boardID = _arg.boardID, threadID = _arg.threadID;
|
||||
$.forceSync(this.key);
|
||||
if (threadID) {
|
||||
if (!Object.keys(this.data.boards[boardID][threadID]).length) {
|
||||
delete this.data.boards[boardID][threadID];
|
||||
@ -3909,6 +3917,7 @@
|
||||
DataBoard.prototype.set = function(_arg) {
|
||||
var boardID, postID, threadID, val, _base, _base1, _base2;
|
||||
boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID, val = _arg.val;
|
||||
$.forceSync(this.key);
|
||||
if (postID !== void 0) {
|
||||
((_base = ((_base1 = this.data.boards)[boardID] || (_base1[boardID] = {})))[threadID] || (_base[threadID] = {}))[postID] = val;
|
||||
} else if (threadID !== void 0) {
|
||||
@ -3942,70 +3951,47 @@
|
||||
return val || defaultValue;
|
||||
};
|
||||
|
||||
DataBoard.prototype.forceSync = function() {
|
||||
return $.forceSync(this.key);
|
||||
};
|
||||
|
||||
DataBoard.prototype.clean = function() {
|
||||
var boardID, keys, now, _i, _len;
|
||||
now = Date.now();
|
||||
if ((this.data.lastChecked || 0) > now - 2 * $.HOUR) {
|
||||
return;
|
||||
}
|
||||
keys = Object.keys(this.data.boards);
|
||||
if (!keys.length) {
|
||||
return;
|
||||
}
|
||||
for (_i = 0, _len = keys.length; _i < _len; _i++) {
|
||||
boardID = keys[_i];
|
||||
var boardID, now, threadID, val, _ref;
|
||||
$.forceSync(this.key);
|
||||
_ref = this.data.boards;
|
||||
for (boardID in _ref) {
|
||||
val = _ref[boardID];
|
||||
this.deleteIfEmpty({
|
||||
boardID: boardID
|
||||
});
|
||||
if (boardID in this.data.boards) {
|
||||
this.ajaxClean(boardID);
|
||||
}
|
||||
now = Date.now();
|
||||
if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) {
|
||||
this.data.lastChecked = now;
|
||||
for (boardID in this.data.boards) {
|
||||
for (threadID in this.data.boards[boardID]) {
|
||||
this.ajaxClean(boardID, threadID);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.data.lastChecked = now;
|
||||
return this.save();
|
||||
};
|
||||
|
||||
DataBoard.prototype.ajaxClean = function(boardID) {
|
||||
return $.cache("//a.4cdn.org/" + boardID + "/threads.json", (function(_this) {
|
||||
return function(e) {
|
||||
var board, count, page, thread, threads, _i, _j, _len, _len1, _ref, _ref1;
|
||||
if (e.target.status !== 200) {
|
||||
DataBoard.prototype.ajaxClean = function(boardID, threadID) {
|
||||
return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", {
|
||||
onloadend: (function(_this) {
|
||||
return function(e) {
|
||||
if (e.target.status === 404) {
|
||||
_this["delete"]({
|
||||
boardID: boardID
|
||||
return _this["delete"]({
|
||||
boardID: boardID,
|
||||
threadID: threadID
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
board = _this.data.boards[boardID];
|
||||
threads = {};
|
||||
_ref = e.target.response;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
page = _ref[_i];
|
||||
_ref1 = page.threads;
|
||||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||||
thread = _ref1[_j];
|
||||
if (thread.no in board) {
|
||||
threads[thread.no] = board[thread.no];
|
||||
}
|
||||
}
|
||||
}
|
||||
count = Object.keys(threads).length;
|
||||
if (count === Object.keys(board).length) {
|
||||
return;
|
||||
}
|
||||
if (count) {
|
||||
return _this.set({
|
||||
boardID: boardID,
|
||||
val: threads
|
||||
});
|
||||
} else {
|
||||
return _this["delete"]({
|
||||
boardID: boardID
|
||||
});
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
};
|
||||
})(this)
|
||||
}, {
|
||||
type: 'head'
|
||||
});
|
||||
};
|
||||
|
||||
DataBoard.prototype.onSync = function(data) {
|
||||
@ -4053,7 +4039,7 @@
|
||||
return;
|
||||
}
|
||||
$.off(d, 'visibilitychange', this.add);
|
||||
$.add(Header.noticesRoot, this.el);
|
||||
$.add(doc, this.el);
|
||||
this.el.clientHeight;
|
||||
this.el.style.opacity = 1;
|
||||
if (this.timeout) {
|
||||
@ -4319,7 +4305,7 @@
|
||||
className: 'menu-button a-icon',
|
||||
id: 'main-menu'
|
||||
});
|
||||
box = UI.checkbox.bind(UI);
|
||||
box = UI.checkbox;
|
||||
barFixedToggler = box('Fixed Header', 'Fixed Header');
|
||||
headerToggler = box('Header auto-hide', ' Auto-hide header');
|
||||
scrollHeaderToggler = box('Header auto-hide on scroll', ' Auto-hide header on scroll');
|
||||
@ -6211,43 +6197,21 @@
|
||||
};
|
||||
|
||||
/* File Info */
|
||||
if (file != null ? file.isDeleted : void 0) {
|
||||
fileCont = {
|
||||
innerHTML: "<span class=\"fileThumb\"><img src=\"" + E(staticPath) + "filedeleted-res" + E(gifIcon) + "\" alt=\"File deleted.\" class=\"fileDeletedRes retina\"></span>"
|
||||
};
|
||||
} else if (file && boardID === 'f') {
|
||||
fileCont = {
|
||||
innerHTML: "<div class=\"fileInfo\"><span class=\"fileText\" id=\"fT" + E(postID) + "\">File: <a data-width=\"" + E(file.width) + "\" data-height=\"" + E(file.height) + "\" href=\"" + E(file.url) + "\" target=\"_blank\">" + E(file.name) + "</a>-(" + E($.bytesToString(file.size)) + ", " + E(file.width) + "x" + E(file.height) + ", " + E(file.tag) + ")</span></div>"
|
||||
};
|
||||
} else if (file) {
|
||||
if (file.isSpoiler) {
|
||||
shortFilename = 'Spoiler Image';
|
||||
if (spoilerRange = Build.spoilerRange[boardID]) {
|
||||
fileThumb = "//s.4cdn.org/image/spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png";
|
||||
} else {
|
||||
fileThumb = '//s.4cdn.org/image/spoiler.png';
|
||||
}
|
||||
file.twidth = file.theight = 100;
|
||||
} else {
|
||||
shortFilename = Build.shortFilename(file.name, !isOP);
|
||||
fileThumb = file.turl;
|
||||
}
|
||||
fileSize = $.bytesToString(file.size);
|
||||
fileDims = file.url.slice(-4) === '.pdf' ? 'PDF' : "" + file.width + "x" + file.height;
|
||||
fileLink = file.isSpoiler || file.name === shortFilename ? {
|
||||
innerHTML: "<a href=\"" + E(file.url) + "\" target=\"_blank\">" + E(shortFilename) + "</a>"
|
||||
} : {
|
||||
innerHTML: "<a title=\"" + E(file.name) + "\" href=\"" + E(file.url) + "\" target=\"_blank\">" + E(shortFilename) + "</a>"
|
||||
};
|
||||
fileText = file.isSpoiler ? {
|
||||
innerHTML: "<div class=\"fileText\" id=\"fT" + E(postID) + "\" title=\"" + E(file.name) + "\">File: " + fileLink.innerHTML + " (" + E(fileSize) + ", " + E(fileDims) + ")</div>"
|
||||
} : {
|
||||
innerHTML: "<div class=\"fileText\" id=\"fT" + E(postID) + "\">File: " + fileLink.innerHTML + " (" + E(fileSize) + ", " + E(fileDims) + ")</div>"
|
||||
};
|
||||
({
|
||||
innerHTML: fileText.innerHTML + "<a class=\"fileThumb" + E(file.isSpoiler ? " imgspoiler" : "") + "\" href=\"" + E(file.url) + "\" target=\"_blank\"><img src=\"" + E(fileThumb) + "\" alt=\"" + E(fileSize) + "\" data-md5=\"" + E(file.MD5) + "\" style=\"height: " + E(file.theight) + "px; width: " + E(file.twidth) + "px;\"></a>"
|
||||
});
|
||||
}
|
||||
fileCont = (file != null ? file.isDeleted : void 0) ? {
|
||||
innerHTML: "<span class=\"fileThumb\"><img src=\"" + E(staticPath) + "filedeleted-res" + E(gifIcon) + "\" alt=\"File deleted.\" class=\"fileDeletedRes retina\"></span>"
|
||||
} : file && boardID === 'f' ? {
|
||||
innerHTML: "<div class=\"fileInfo\"><span class=\"fileText\" id=\"fT" + E(postID) + "\">File: <a data-width=\"" + E(file.width) + "\" data-height=\"" + E(file.height) + "\" href=\"" + E(file.url) + "\" target=\"_blank\">" + E(file.name) + "</a>-(" + E($.bytesToString(file.size)) + ", " + E(file.width) + "x" + E(file.height) + ", " + E(file.tag) + ")</span></div>"
|
||||
} : file ? (file.isSpoiler ? (shortFilename = 'Spoiler Image', (spoilerRange = Build.spoilerRange[boardID]) ? fileThumb = "//s.4cdn.org/image/spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png" : fileThumb = '//s.4cdn.org/image/spoiler.png', file.twidth = file.theight = 100) : (shortFilename = Build.shortFilename(file.name, !isOP), fileThumb = file.turl), fileSize = $.bytesToString(file.size), fileDims = file.url.slice(-4) === '.pdf' ? 'PDF' : "" + file.width + "x" + file.height, fileLink = file.isSpoiler || file.name === shortFilename ? {
|
||||
innerHTML: "<a href=\"" + E(file.url) + "\" target=\"_blank\">" + E(shortFilename) + "</a>"
|
||||
} : {
|
||||
innerHTML: "<a title=\"" + E(file.name) + "\" href=\"" + E(file.url) + "\" target=\"_blank\">" + E(shortFilename) + "</a>"
|
||||
}, fileText = file.isSpoiler ? {
|
||||
innerHTML: "<div class=\"fileText\" id=\"fT" + E(postID) + "\" title=\"" + E(file.name) + "\">File: " + fileLink.innerHTML + " (" + E(fileSize) + ", " + E(fileDims) + ")</div>"
|
||||
} : {
|
||||
innerHTML: "<div class=\"fileText\" id=\"fT" + E(postID) + "\">File: " + fileLink.innerHTML + " (" + E(fileSize) + ", " + E(fileDims) + ")</div>"
|
||||
}, {
|
||||
innerHTML: fileText.innerHTML + "<a class=\"fileThumb" + E(file.isSpoiler ? " imgspoiler" : "") + "\" href=\"" + E(file.url) + "\" target=\"_blank\"><img src=\"" + E(fileThumb) + "\" alt=\"" + E(fileSize) + "\" data-md5=\"" + E(file.MD5) + "\" style=\"height: " + E(file.theight) + "px; width: " + E(file.twidth) + "px;\"></a>"
|
||||
}) : void 0;
|
||||
fileBlock = file ? {
|
||||
innerHTML: "<div class=\"file\" id=\"f" + E(postID) + "\">" + fileCont.innerHTML + "</div>"
|
||||
} : {
|
||||
@ -6765,20 +6729,30 @@
|
||||
};
|
||||
|
||||
UI = (function() {
|
||||
var Menu, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove;
|
||||
dialog = function(id, position, html) {
|
||||
var el, move;
|
||||
var Menu, checkbox, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove;
|
||||
dialog = function(id, position, properties) {
|
||||
var child, el, move, _i, _len, _ref;
|
||||
el = $.el('div', {
|
||||
className: 'dialog',
|
||||
innerHTML: html,
|
||||
id: id
|
||||
});
|
||||
$.extend(el, properties);
|
||||
el.style.cssText = position;
|
||||
$.get("" + id + ".position", position, function(item) {
|
||||
return el.style.cssText = item["" + id + ".position"];
|
||||
});
|
||||
move = $('.move', el);
|
||||
$.on(move, 'touchstart mousedown', dragstart);
|
||||
_ref = move.children;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
child = _ref[_i];
|
||||
if (!child.tagName) {
|
||||
continue;
|
||||
}
|
||||
$.on(child, 'touchstart mousedown', function(e) {
|
||||
return e.stopPropagation();
|
||||
});
|
||||
}
|
||||
return el;
|
||||
};
|
||||
Menu = (function() {
|
||||
@ -6788,11 +6762,24 @@
|
||||
|
||||
lastToggledButton = null;
|
||||
|
||||
function Menu() {
|
||||
function Menu(type) {
|
||||
this.type = type;
|
||||
this.rmEntry = __bind(this.rmEntry, this);
|
||||
this.addEntry = __bind(this.addEntry, this);
|
||||
this.onFocus = __bind(this.onFocus, this);
|
||||
this.keybinds = __bind(this.keybinds, this);
|
||||
this.close = __bind(this.close, this);
|
||||
$.on(d, 'AddMenuEntry', (function(_this) {
|
||||
return function(_arg) {
|
||||
var detail;
|
||||
detail = _arg.detail;
|
||||
if (detail.type !== _this.type) {
|
||||
return;
|
||||
}
|
||||
delete detail.open;
|
||||
return _this.addEntry(detail);
|
||||
};
|
||||
})(this));
|
||||
this.entries = [];
|
||||
}
|
||||
|
||||
@ -6832,7 +6819,6 @@
|
||||
menu = this.makeMenu();
|
||||
currentMenu = menu;
|
||||
lastToggledButton = button;
|
||||
$.addClass(button, 'open');
|
||||
this.entries.sort(function(first, second) {
|
||||
return first.order - second.order;
|
||||
});
|
||||
@ -6870,12 +6856,7 @@
|
||||
Menu.prototype.insertEntry = function(entry, parent, data) {
|
||||
var subEntry, submenu, _i, _len, _ref;
|
||||
if (typeof entry.open === 'function') {
|
||||
if (!entry.open(data, (function(_this) {
|
||||
return function(subEntry) {
|
||||
_this.parseEntry(subEntry);
|
||||
return entry.subEntries.push(subEntry);
|
||||
};
|
||||
})(this))) {
|
||||
if (!entry.open(data)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -6899,7 +6880,7 @@
|
||||
|
||||
Menu.prototype.close = function() {
|
||||
$.rm(currentMenu);
|
||||
$.rmClass(lastToggledButton, 'open');
|
||||
$.rmClass(lastToggledButton, 'active');
|
||||
currentMenu = null;
|
||||
lastToggledButton = null;
|
||||
return $.off(d, 'click CloseMenu', this.close);
|
||||
@ -7014,7 +6995,6 @@
|
||||
return;
|
||||
}
|
||||
$.addClass(el, 'has-submenu');
|
||||
$.addClass(el, 'pfa');
|
||||
for (_i = 0, _len = subEntries.length; _i < _len; _i++) {
|
||||
subEntry = subEntries[_i];
|
||||
this.parseEntry(subEntry);
|
||||
@ -7025,13 +7005,13 @@
|
||||
|
||||
})();
|
||||
dragstart = function(e) {
|
||||
var el, isTouching, o, rect, screenHeight, screenWidth, _ref, _ref1;
|
||||
var el, isTouching, o, rect, screenHeight, screenWidth, _ref;
|
||||
if (e.type === 'mousedown' && e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
if (isTouching = e.type === 'touchstart') {
|
||||
_ref = e.changedTouches, e = _ref[_ref.length - 1];
|
||||
e = e.changedTouches[e.changedTouches.length - 1];
|
||||
}
|
||||
el = $.x('ancestor::div[contains(@class,"dialog")][1]', this);
|
||||
rect = el.getBoundingClientRect();
|
||||
@ -7048,7 +7028,7 @@
|
||||
screenWidth: screenWidth,
|
||||
isTouching: isTouching
|
||||
};
|
||||
_ref1 = Conf['Header auto-hide'] || !Conf['Fixed Header'] ? [0, 0] : Conf['Bottom Header'] ? [0, Header.bar.getBoundingClientRect().height] : [Header.bar.getBoundingClientRect().height, 0], o.topBorder = _ref1[0], o.bottomBorder = _ref1[1];
|
||||
_ref = Conf['Header auto-hide'] || !Conf['Fixed Header'] ? [0, 0] : Conf['Bottom Header'] ? [0, Header.bar.getBoundingClientRect().height] : [Header.bar.getBoundingClientRect().height, 0], o.topBorder = _ref[0], o.bottomBorder = _ref[1];
|
||||
if (isTouching) {
|
||||
o.identifier = e.identifier;
|
||||
o.move = touchmove.bind(o);
|
||||
@ -7110,33 +7090,29 @@
|
||||
return $.set("" + this.id + ".position", this.style.cssText);
|
||||
};
|
||||
hoverstart = function(_arg) {
|
||||
var asapTest, cb, el, endEvents, latestEvent, noRemove, o, offsetX, offsetY, root;
|
||||
root = _arg.root, el = _arg.el, latestEvent = _arg.latestEvent, endEvents = _arg.endEvents, asapTest = _arg.asapTest, cb = _arg.cb, offsetX = _arg.offsetX, offsetY = _arg.offsetY, noRemove = _arg.noRemove;
|
||||
var asapTest, cb, el, endEvents, height, latestEvent, noRemove, o, root, _ref;
|
||||
root = _arg.root, el = _arg.el, latestEvent = _arg.latestEvent, endEvents = _arg.endEvents, asapTest = _arg.asapTest, height = _arg.height, cb = _arg.cb, noRemove = _arg.noRemove;
|
||||
o = {
|
||||
root: root,
|
||||
el: el,
|
||||
style: el.style,
|
||||
isImage: (_ref = el.nodeName) === 'IMG' || _ref === 'VIDEO',
|
||||
cb: cb,
|
||||
close: close,
|
||||
endEvents: endEvents,
|
||||
latestEvent: latestEvent,
|
||||
clientHeight: doc.clientHeight,
|
||||
clientWidth: doc.clientWidth,
|
||||
offsetX: offsetX || 45,
|
||||
offsetY: offsetY || -120,
|
||||
noRemove: noRemove
|
||||
};
|
||||
o.hover = hover.bind(o);
|
||||
o.hoverend = hoverend.bind(o);
|
||||
if (asapTest) {
|
||||
$.asap(function() {
|
||||
return !el.parentNode || asapTest();
|
||||
}, function() {
|
||||
if (el.parentNode) {
|
||||
return o.hover(o.latestEvent);
|
||||
}
|
||||
});
|
||||
}
|
||||
$.asap(function() {
|
||||
return !el.parentNode || asapTest();
|
||||
}, function() {
|
||||
if (el.parentNode) {
|
||||
return o.hover(o.latestEvent);
|
||||
}
|
||||
});
|
||||
$.on(root, endEvents, o.hoverend);
|
||||
if ($.x('ancestor::div[contains(@class,"inline")][1]', root)) {
|
||||
$.on(d, 'keydown', o.hoverend);
|
||||
@ -7150,22 +7126,28 @@
|
||||
return $.on(doc, 'mousemove', o.workaround);
|
||||
};
|
||||
hover = function(e) {
|
||||
var clientX, clientY, height, left, right, top, _ref;
|
||||
var clientX, clientY, height, left, right, style, threshold, top, _ref;
|
||||
this.latestEvent = e;
|
||||
height = this.el.offsetHeight + 25;
|
||||
height = this.height || this.el.offsetHeight;
|
||||
clientX = e.clientX, clientY = e.clientY;
|
||||
top = clientY + this.offsetY;
|
||||
top = this.clientHeight <= height || top <= 0 ? 0 : top + height >= this.clientHeight ? this.clientHeight - height : top;
|
||||
_ref = clientX <= this.clientWidth / 2 ? [clientX + this.offsetX + 'px', null] : [null, this.clientWidth - clientX + this.offsetX + 'px'], left = _ref[0], right = _ref[1];
|
||||
this.style.top = top + 'px';
|
||||
this.style.left = left;
|
||||
return this.style.right = right;
|
||||
top = this.isImage ? Math.max(0, clientY * (this.clientHeight - height) / this.clientHeight) : Math.max(0, Math.min(this.clientHeight - height, clientY - 120));
|
||||
threshold = this.clientWidth / 2;
|
||||
if (!this.isImage) {
|
||||
threshold = Math.max(threshold, this.clientWidth - 400);
|
||||
}
|
||||
_ref = clientX <= threshold ? [clientX + 45 + 'px', null] : [null, this.clientWidth - clientX + 45 + 'px'], left = _ref[0], right = _ref[1];
|
||||
style = this.style;
|
||||
style.top = top + 'px';
|
||||
style.left = left;
|
||||
return style.right = right;
|
||||
};
|
||||
hoverend = function(e) {
|
||||
if (e.type === 'keydown' && e.keyCode !== 13 || e.target.nodeName === "TEXTAREA") {
|
||||
return;
|
||||
}
|
||||
$.rm(this.el);
|
||||
if (!this.noRemove) {
|
||||
$.rm(this.el);
|
||||
}
|
||||
$.off(this.root, this.endEvents, this.hoverend);
|
||||
$.off(d, 'keydown', this.hoverend);
|
||||
$.off(this.root, 'mousemove', this.hover);
|
||||
@ -7174,10 +7156,25 @@
|
||||
return this.cb.call(this);
|
||||
}
|
||||
};
|
||||
checkbox = function(name, text, checked) {
|
||||
var input, label;
|
||||
if (checked == null) {
|
||||
checked = Conf[name];
|
||||
}
|
||||
label = $.el('label');
|
||||
input = $.el('input', {
|
||||
type: 'checkbox',
|
||||
name: name,
|
||||
checked: checked
|
||||
});
|
||||
$.add(label, [input, $.tn(text)]);
|
||||
return label;
|
||||
};
|
||||
return {
|
||||
dialog: dialog,
|
||||
Menu: Menu,
|
||||
hover: hoverstart
|
||||
hover: hoverstart,
|
||||
checkbox: checkbox
|
||||
};
|
||||
})();
|
||||
|
||||
@ -9730,11 +9727,10 @@
|
||||
dialog: function() {
|
||||
var dialog, event, i, items, match_max, match_min, name, node, nodes, rules, save, setNode;
|
||||
QR.nodes = nodes = {
|
||||
el: dialog = UI.dialog('qr', 'top:0;right:0;')
|
||||
el: dialog = UI.dialog('qr', 'top:0;right:0;', {
|
||||
innerHTML: "<div id=qrtab class=move>\r<input type=checkbox id=autohide title=Auto-hide>\r<div id=qr-thread-select>\r<select data-name=thread title='Create a new thread / Reply'>\r<option value=new>New thread</option>\r</select>\r</div>\r<a href=javascript:; class='close fa' title=Close>\\uf00d</a>\r</div>\r<form>\r<div class=persona>\r<input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1>\r<input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1>\r<input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1> \r</div>\r<div class=textarea>\r<textarea data-name=com placeholder=Comment class=field></textarea>\r<span id=char-count></span>\r</div>\r<div id=dump-list-container>\r<div id=dump-list></div>\r<a id=add-post href=javascript:; title=\"Add a post\">+</a>\r</div>\r<div id=file-n-submit>\r<span id=qr-filename-container class=field tabindex=0>\r<span id=qr-no-file>No selected file</span>\r<input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\">\r<span id=qr-extras-container>\r<label id=qr-spoiler-label>\r<input type=checkbox id=qr-file-spoiler title='Spoiler image'>\r</label>\r<span class=description>Spoiler</span>\r<a id=url-button><i class=\"fa\">\\uf0c1</i></a>\r<span class=description>Post from URL</span>\r<a id=dump-button title='Dump list'>+</a>\r<span class=description>Dump</span>\r<a id=qr-filerm href=javascript:; title='Remove file' class=fa>\\uf00d</a>\r<span class=description>Remove File</span>\r</span>\r</span>\r<input type=submit>\r</div>\r<input type=file multiple>\r</form>\r<datalist id=\"list-name\"></datalist>\r<datalist id=\"list-email\"></datalist>\r<datalist id=\"list-sub\"></datalist>\r"
|
||||
})
|
||||
};
|
||||
$.extend(dialog, {
|
||||
innerHTML: "<div id=qrtab class=move>\r<input type=checkbox id=autohide title=Auto-hide>\r<div id=qr-thread-select>\r<select data-name=thread title='Create a new thread / Reply'>\r<option value=new>New thread</option>\r</select>\r</div>\r<a href=javascript:; class='close fa' title=Close>\\uf00d</a>\r</div>\r<form>\r<div class=persona>\r<input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1>\r<input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1>\r<input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1> \r</div>\r<div class=textarea>\r<textarea data-name=com placeholder=Comment class=field></textarea>\r<span id=char-count></span>\r</div>\r<div id=dump-list-container>\r<div id=dump-list></div>\r<a id=add-post href=javascript:; title=\"Add a post\">+</a>\r</div>\r<div id=file-n-submit>\r<span id=qr-filename-container class=field tabindex=0>\r<span id=qr-no-file>No selected file</span>\r<input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\">\r<span id=qr-extras-container>\r<label id=qr-spoiler-label>\r<input type=checkbox id=qr-file-spoiler title='Spoiler image'>\r</label>\r<span class=description>Spoiler</span>\r<a id=url-button><i class=\"fa\">\\uf0c1</i></a>\r<span class=description>Post from URL</span>\r<a id=dump-button title='Dump list'>+</a>\r<span class=description>Dump</span>\r<a id=qr-filerm href=javascript:; title='Remove file' class=fa>\\uf00d</a>\r<span class=description>Remove File</span>\r</span>\r</span>\r<input type=submit>\r</div>\r<input type=file multiple>\r</form>\r<datalist id=\"list-name\"></datalist>\r<datalist id=\"list-email\"></datalist>\r<datalist id=\"list-sub\"></datalist>\r"
|
||||
});
|
||||
setNode = function(name, query) {
|
||||
return nodes[name] = $(query, dialog);
|
||||
};
|
||||
@ -14099,6 +14095,7 @@
|
||||
this.status = $('#watcher-status', this.dialog);
|
||||
this.list = this.dialog.lastElementChild;
|
||||
this.refreshButton = $('.refresh', this.dialog);
|
||||
this.unreaddb = Unread.db || new DataBoard('lastReadPosts');
|
||||
$.on(d, 'QRPostSuccessful', this.cb.post);
|
||||
if (g.VIEW === 'thread') {
|
||||
$.on(d, 'ThreadUpdate', this.cb.threadUpdate);
|
||||
|
||||
@ -3899,15 +3899,22 @@
|
||||
};
|
||||
|
||||
DataBoard.prototype["delete"] = function(_arg) {
|
||||
var boardID, postID, threadID;
|
||||
var boardID, postID, threadID, _ref;
|
||||
boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID;
|
||||
$.forceSync(this.key);
|
||||
if (postID) {
|
||||
if (!((_ref = this.data.boards[boardID]) != null ? _ref[threadID] : void 0)) {
|
||||
return;
|
||||
}
|
||||
delete this.data.boards[boardID][threadID][postID];
|
||||
this.deleteIfEmpty({
|
||||
boardID: boardID,
|
||||
threadID: threadID
|
||||
});
|
||||
} else if (threadID) {
|
||||
if (!this.data.boards[boardID]) {
|
||||
return;
|
||||
}
|
||||
delete this.data.boards[boardID][threadID];
|
||||
this.deleteIfEmpty({
|
||||
boardID: boardID
|
||||
@ -3921,6 +3928,7 @@
|
||||
DataBoard.prototype.deleteIfEmpty = function(_arg) {
|
||||
var boardID, threadID;
|
||||
boardID = _arg.boardID, threadID = _arg.threadID;
|
||||
$.forceSync(this.key);
|
||||
if (threadID) {
|
||||
if (!Object.keys(this.data.boards[boardID][threadID]).length) {
|
||||
delete this.data.boards[boardID][threadID];
|
||||
@ -3936,6 +3944,7 @@
|
||||
DataBoard.prototype.set = function(_arg) {
|
||||
var boardID, postID, threadID, val, _base, _base1, _base2;
|
||||
boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID, val = _arg.val;
|
||||
$.forceSync(this.key);
|
||||
if (postID !== void 0) {
|
||||
((_base = ((_base1 = this.data.boards)[boardID] || (_base1[boardID] = {})))[threadID] || (_base[threadID] = {}))[postID] = val;
|
||||
} else if (threadID !== void 0) {
|
||||
@ -3969,70 +3978,47 @@
|
||||
return val || defaultValue;
|
||||
};
|
||||
|
||||
DataBoard.prototype.forceSync = function() {
|
||||
return $.forceSync(this.key);
|
||||
};
|
||||
|
||||
DataBoard.prototype.clean = function() {
|
||||
var boardID, keys, now, _i, _len;
|
||||
now = Date.now();
|
||||
if ((this.data.lastChecked || 0) > now - 2 * $.HOUR) {
|
||||
return;
|
||||
}
|
||||
keys = Object.keys(this.data.boards);
|
||||
if (!keys.length) {
|
||||
return;
|
||||
}
|
||||
for (_i = 0, _len = keys.length; _i < _len; _i++) {
|
||||
boardID = keys[_i];
|
||||
var boardID, now, threadID, val, _ref;
|
||||
$.forceSync(this.key);
|
||||
_ref = this.data.boards;
|
||||
for (boardID in _ref) {
|
||||
val = _ref[boardID];
|
||||
this.deleteIfEmpty({
|
||||
boardID: boardID
|
||||
});
|
||||
if (boardID in this.data.boards) {
|
||||
this.ajaxClean(boardID);
|
||||
}
|
||||
now = Date.now();
|
||||
if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) {
|
||||
this.data.lastChecked = now;
|
||||
for (boardID in this.data.boards) {
|
||||
for (threadID in this.data.boards[boardID]) {
|
||||
this.ajaxClean(boardID, threadID);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.data.lastChecked = now;
|
||||
return this.save();
|
||||
};
|
||||
|
||||
DataBoard.prototype.ajaxClean = function(boardID) {
|
||||
return $.cache("//a.4cdn.org/" + boardID + "/threads.json", (function(_this) {
|
||||
return function(e) {
|
||||
var board, count, page, thread, threads, _i, _j, _len, _len1, _ref, _ref1;
|
||||
if (e.target.status !== 200) {
|
||||
DataBoard.prototype.ajaxClean = function(boardID, threadID) {
|
||||
return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", {
|
||||
onloadend: (function(_this) {
|
||||
return function(e) {
|
||||
if (e.target.status === 404) {
|
||||
_this["delete"]({
|
||||
boardID: boardID
|
||||
return _this["delete"]({
|
||||
boardID: boardID,
|
||||
threadID: threadID
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
board = _this.data.boards[boardID];
|
||||
threads = {};
|
||||
_ref = e.target.response;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
page = _ref[_i];
|
||||
_ref1 = page.threads;
|
||||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||||
thread = _ref1[_j];
|
||||
if (thread.no in board) {
|
||||
threads[thread.no] = board[thread.no];
|
||||
}
|
||||
}
|
||||
}
|
||||
count = Object.keys(threads).length;
|
||||
if (count === Object.keys(board).length) {
|
||||
return;
|
||||
}
|
||||
if (count) {
|
||||
return _this.set({
|
||||
boardID: boardID,
|
||||
val: threads
|
||||
});
|
||||
} else {
|
||||
return _this["delete"]({
|
||||
boardID: boardID
|
||||
});
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
};
|
||||
})(this)
|
||||
}, {
|
||||
type: 'head'
|
||||
});
|
||||
};
|
||||
|
||||
DataBoard.prototype.onSync = function(data) {
|
||||
@ -4080,7 +4066,7 @@
|
||||
return;
|
||||
}
|
||||
$.off(d, 'visibilitychange', this.add);
|
||||
$.add(Header.noticesRoot, this.el);
|
||||
$.add(doc, this.el);
|
||||
this.el.clientHeight;
|
||||
this.el.style.opacity = 1;
|
||||
if (this.timeout) {
|
||||
@ -4348,7 +4334,7 @@
|
||||
className: 'menu-button a-icon',
|
||||
id: 'main-menu'
|
||||
});
|
||||
box = UI.checkbox.bind(UI);
|
||||
box = UI.checkbox;
|
||||
barFixedToggler = box('Fixed Header', 'Fixed Header');
|
||||
headerToggler = box('Header auto-hide', ' Auto-hide header');
|
||||
scrollHeaderToggler = box('Header auto-hide on scroll', ' Auto-hide header on scroll');
|
||||
@ -6240,43 +6226,21 @@
|
||||
};
|
||||
|
||||
/* File Info */
|
||||
if (file != null ? file.isDeleted : void 0) {
|
||||
fileCont = {
|
||||
innerHTML: "<span class=\"fileThumb\"><img src=\"" + E(staticPath) + "filedeleted-res" + E(gifIcon) + "\" alt=\"File deleted.\" class=\"fileDeletedRes retina\"></span>"
|
||||
};
|
||||
} else if (file && boardID === 'f') {
|
||||
fileCont = {
|
||||
innerHTML: "<div class=\"fileInfo\"><span class=\"fileText\" id=\"fT" + E(postID) + "\">File: <a data-width=\"" + E(file.width) + "\" data-height=\"" + E(file.height) + "\" href=\"" + E(file.url) + "\" target=\"_blank\">" + E(file.name) + "</a>-(" + E($.bytesToString(file.size)) + ", " + E(file.width) + "x" + E(file.height) + ", " + E(file.tag) + ")</span></div>"
|
||||
};
|
||||
} else if (file) {
|
||||
if (file.isSpoiler) {
|
||||
shortFilename = 'Spoiler Image';
|
||||
if (spoilerRange = Build.spoilerRange[boardID]) {
|
||||
fileThumb = "//s.4cdn.org/image/spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png";
|
||||
} else {
|
||||
fileThumb = '//s.4cdn.org/image/spoiler.png';
|
||||
}
|
||||
file.twidth = file.theight = 100;
|
||||
} else {
|
||||
shortFilename = Build.shortFilename(file.name, !isOP);
|
||||
fileThumb = file.turl;
|
||||
}
|
||||
fileSize = $.bytesToString(file.size);
|
||||
fileDims = file.url.slice(-4) === '.pdf' ? 'PDF' : "" + file.width + "x" + file.height;
|
||||
fileLink = file.isSpoiler || file.name === shortFilename ? {
|
||||
innerHTML: "<a href=\"" + E(file.url) + "\" target=\"_blank\">" + E(shortFilename) + "</a>"
|
||||
} : {
|
||||
innerHTML: "<a title=\"" + E(file.name) + "\" href=\"" + E(file.url) + "\" target=\"_blank\">" + E(shortFilename) + "</a>"
|
||||
};
|
||||
fileText = file.isSpoiler ? {
|
||||
innerHTML: "<div class=\"fileText\" id=\"fT" + E(postID) + "\" title=\"" + E(file.name) + "\">File: " + fileLink.innerHTML + " (" + E(fileSize) + ", " + E(fileDims) + ")</div>"
|
||||
} : {
|
||||
innerHTML: "<div class=\"fileText\" id=\"fT" + E(postID) + "\">File: " + fileLink.innerHTML + " (" + E(fileSize) + ", " + E(fileDims) + ")</div>"
|
||||
};
|
||||
({
|
||||
innerHTML: fileText.innerHTML + "<a class=\"fileThumb" + E(file.isSpoiler ? " imgspoiler" : "") + "\" href=\"" + E(file.url) + "\" target=\"_blank\"><img src=\"" + E(fileThumb) + "\" alt=\"" + E(fileSize) + "\" data-md5=\"" + E(file.MD5) + "\" style=\"height: " + E(file.theight) + "px; width: " + E(file.twidth) + "px;\"></a>"
|
||||
});
|
||||
}
|
||||
fileCont = (file != null ? file.isDeleted : void 0) ? {
|
||||
innerHTML: "<span class=\"fileThumb\"><img src=\"" + E(staticPath) + "filedeleted-res" + E(gifIcon) + "\" alt=\"File deleted.\" class=\"fileDeletedRes retina\"></span>"
|
||||
} : file && boardID === 'f' ? {
|
||||
innerHTML: "<div class=\"fileInfo\"><span class=\"fileText\" id=\"fT" + E(postID) + "\">File: <a data-width=\"" + E(file.width) + "\" data-height=\"" + E(file.height) + "\" href=\"" + E(file.url) + "\" target=\"_blank\">" + E(file.name) + "</a>-(" + E($.bytesToString(file.size)) + ", " + E(file.width) + "x" + E(file.height) + ", " + E(file.tag) + ")</span></div>"
|
||||
} : file ? (file.isSpoiler ? (shortFilename = 'Spoiler Image', (spoilerRange = Build.spoilerRange[boardID]) ? fileThumb = "//s.4cdn.org/image/spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png" : fileThumb = '//s.4cdn.org/image/spoiler.png', file.twidth = file.theight = 100) : (shortFilename = Build.shortFilename(file.name, !isOP), fileThumb = file.turl), fileSize = $.bytesToString(file.size), fileDims = file.url.slice(-4) === '.pdf' ? 'PDF' : "" + file.width + "x" + file.height, fileLink = file.isSpoiler || file.name === shortFilename ? {
|
||||
innerHTML: "<a href=\"" + E(file.url) + "\" target=\"_blank\">" + E(shortFilename) + "</a>"
|
||||
} : {
|
||||
innerHTML: "<a title=\"" + E(file.name) + "\" href=\"" + E(file.url) + "\" target=\"_blank\">" + E(shortFilename) + "</a>"
|
||||
}, fileText = file.isSpoiler ? {
|
||||
innerHTML: "<div class=\"fileText\" id=\"fT" + E(postID) + "\" title=\"" + E(file.name) + "\">File: " + fileLink.innerHTML + " (" + E(fileSize) + ", " + E(fileDims) + ")</div>"
|
||||
} : {
|
||||
innerHTML: "<div class=\"fileText\" id=\"fT" + E(postID) + "\">File: " + fileLink.innerHTML + " (" + E(fileSize) + ", " + E(fileDims) + ")</div>"
|
||||
}, {
|
||||
innerHTML: fileText.innerHTML + "<a class=\"fileThumb" + E(file.isSpoiler ? " imgspoiler" : "") + "\" href=\"" + E(file.url) + "\" target=\"_blank\"><img src=\"" + E(fileThumb) + "\" alt=\"" + E(fileSize) + "\" data-md5=\"" + E(file.MD5) + "\" style=\"height: " + E(file.theight) + "px; width: " + E(file.twidth) + "px;\"></a>"
|
||||
}) : void 0;
|
||||
fileBlock = file ? {
|
||||
innerHTML: "<div class=\"file\" id=\"f" + E(postID) + "\">" + fileCont.innerHTML + "</div>"
|
||||
} : {
|
||||
@ -6794,20 +6758,30 @@
|
||||
};
|
||||
|
||||
UI = (function() {
|
||||
var Menu, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove;
|
||||
dialog = function(id, position, html) {
|
||||
var el, move;
|
||||
var Menu, checkbox, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove;
|
||||
dialog = function(id, position, properties) {
|
||||
var child, el, move, _i, _len, _ref;
|
||||
el = $.el('div', {
|
||||
className: 'dialog',
|
||||
innerHTML: html,
|
||||
id: id
|
||||
});
|
||||
$.extend(el, properties);
|
||||
el.style.cssText = position;
|
||||
$.get("" + id + ".position", position, function(item) {
|
||||
return el.style.cssText = item["" + id + ".position"];
|
||||
});
|
||||
move = $('.move', el);
|
||||
$.on(move, 'touchstart mousedown', dragstart);
|
||||
_ref = move.children;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
child = _ref[_i];
|
||||
if (!child.tagName) {
|
||||
continue;
|
||||
}
|
||||
$.on(child, 'touchstart mousedown', function(e) {
|
||||
return e.stopPropagation();
|
||||
});
|
||||
}
|
||||
return el;
|
||||
};
|
||||
Menu = (function() {
|
||||
@ -6817,11 +6791,24 @@
|
||||
|
||||
lastToggledButton = null;
|
||||
|
||||
function Menu() {
|
||||
function Menu(type) {
|
||||
this.type = type;
|
||||
this.rmEntry = __bind(this.rmEntry, this);
|
||||
this.addEntry = __bind(this.addEntry, this);
|
||||
this.onFocus = __bind(this.onFocus, this);
|
||||
this.keybinds = __bind(this.keybinds, this);
|
||||
this.close = __bind(this.close, this);
|
||||
$.on(d, 'AddMenuEntry', (function(_this) {
|
||||
return function(_arg) {
|
||||
var detail;
|
||||
detail = _arg.detail;
|
||||
if (detail.type !== _this.type) {
|
||||
return;
|
||||
}
|
||||
delete detail.open;
|
||||
return _this.addEntry(detail);
|
||||
};
|
||||
})(this));
|
||||
this.entries = [];
|
||||
}
|
||||
|
||||
@ -6861,7 +6848,6 @@
|
||||
menu = this.makeMenu();
|
||||
currentMenu = menu;
|
||||
lastToggledButton = button;
|
||||
$.addClass(button, 'open');
|
||||
this.entries.sort(function(first, second) {
|
||||
return first.order - second.order;
|
||||
});
|
||||
@ -6899,12 +6885,7 @@
|
||||
Menu.prototype.insertEntry = function(entry, parent, data) {
|
||||
var subEntry, submenu, _i, _len, _ref;
|
||||
if (typeof entry.open === 'function') {
|
||||
if (!entry.open(data, (function(_this) {
|
||||
return function(subEntry) {
|
||||
_this.parseEntry(subEntry);
|
||||
return entry.subEntries.push(subEntry);
|
||||
};
|
||||
})(this))) {
|
||||
if (!entry.open(data)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -6928,7 +6909,7 @@
|
||||
|
||||
Menu.prototype.close = function() {
|
||||
$.rm(currentMenu);
|
||||
$.rmClass(lastToggledButton, 'open');
|
||||
$.rmClass(lastToggledButton, 'active');
|
||||
currentMenu = null;
|
||||
lastToggledButton = null;
|
||||
return $.off(d, 'click CloseMenu', this.close);
|
||||
@ -7043,7 +7024,6 @@
|
||||
return;
|
||||
}
|
||||
$.addClass(el, 'has-submenu');
|
||||
$.addClass(el, 'pfa');
|
||||
for (_i = 0, _len = subEntries.length; _i < _len; _i++) {
|
||||
subEntry = subEntries[_i];
|
||||
this.parseEntry(subEntry);
|
||||
@ -7054,13 +7034,13 @@
|
||||
|
||||
})();
|
||||
dragstart = function(e) {
|
||||
var el, isTouching, o, rect, screenHeight, screenWidth, _ref, _ref1;
|
||||
var el, isTouching, o, rect, screenHeight, screenWidth, _ref;
|
||||
if (e.type === 'mousedown' && e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
if (isTouching = e.type === 'touchstart') {
|
||||
_ref = e.changedTouches, e = _ref[_ref.length - 1];
|
||||
e = e.changedTouches[e.changedTouches.length - 1];
|
||||
}
|
||||
el = $.x('ancestor::div[contains(@class,"dialog")][1]', this);
|
||||
rect = el.getBoundingClientRect();
|
||||
@ -7077,7 +7057,7 @@
|
||||
screenWidth: screenWidth,
|
||||
isTouching: isTouching
|
||||
};
|
||||
_ref1 = Conf['Header auto-hide'] || !Conf['Fixed Header'] ? [0, 0] : Conf['Bottom Header'] ? [0, Header.bar.getBoundingClientRect().height] : [Header.bar.getBoundingClientRect().height, 0], o.topBorder = _ref1[0], o.bottomBorder = _ref1[1];
|
||||
_ref = Conf['Header auto-hide'] || !Conf['Fixed Header'] ? [0, 0] : Conf['Bottom Header'] ? [0, Header.bar.getBoundingClientRect().height] : [Header.bar.getBoundingClientRect().height, 0], o.topBorder = _ref[0], o.bottomBorder = _ref[1];
|
||||
if (isTouching) {
|
||||
o.identifier = e.identifier;
|
||||
o.move = touchmove.bind(o);
|
||||
@ -7139,33 +7119,29 @@
|
||||
return $.set("" + this.id + ".position", this.style.cssText);
|
||||
};
|
||||
hoverstart = function(_arg) {
|
||||
var asapTest, cb, el, endEvents, latestEvent, noRemove, o, offsetX, offsetY, root;
|
||||
root = _arg.root, el = _arg.el, latestEvent = _arg.latestEvent, endEvents = _arg.endEvents, asapTest = _arg.asapTest, cb = _arg.cb, offsetX = _arg.offsetX, offsetY = _arg.offsetY, noRemove = _arg.noRemove;
|
||||
var asapTest, cb, el, endEvents, height, latestEvent, noRemove, o, root, _ref;
|
||||
root = _arg.root, el = _arg.el, latestEvent = _arg.latestEvent, endEvents = _arg.endEvents, asapTest = _arg.asapTest, height = _arg.height, cb = _arg.cb, noRemove = _arg.noRemove;
|
||||
o = {
|
||||
root: root,
|
||||
el: el,
|
||||
style: el.style,
|
||||
isImage: (_ref = el.nodeName) === 'IMG' || _ref === 'VIDEO',
|
||||
cb: cb,
|
||||
close: close,
|
||||
endEvents: endEvents,
|
||||
latestEvent: latestEvent,
|
||||
clientHeight: doc.clientHeight,
|
||||
clientWidth: doc.clientWidth,
|
||||
offsetX: offsetX || 45,
|
||||
offsetY: offsetY || -120,
|
||||
noRemove: noRemove
|
||||
};
|
||||
o.hover = hover.bind(o);
|
||||
o.hoverend = hoverend.bind(o);
|
||||
if (asapTest) {
|
||||
$.asap(function() {
|
||||
return !el.parentNode || asapTest();
|
||||
}, function() {
|
||||
if (el.parentNode) {
|
||||
return o.hover(o.latestEvent);
|
||||
}
|
||||
});
|
||||
}
|
||||
$.asap(function() {
|
||||
return !el.parentNode || asapTest();
|
||||
}, function() {
|
||||
if (el.parentNode) {
|
||||
return o.hover(o.latestEvent);
|
||||
}
|
||||
});
|
||||
$.on(root, endEvents, o.hoverend);
|
||||
if ($.x('ancestor::div[contains(@class,"inline")][1]', root)) {
|
||||
$.on(d, 'keydown', o.hoverend);
|
||||
@ -7173,22 +7149,28 @@
|
||||
return $.on(root, 'mousemove', o.hover);
|
||||
};
|
||||
hover = function(e) {
|
||||
var clientX, clientY, height, left, right, top, _ref;
|
||||
var clientX, clientY, height, left, right, style, threshold, top, _ref;
|
||||
this.latestEvent = e;
|
||||
height = this.el.offsetHeight + 25;
|
||||
height = this.height || this.el.offsetHeight;
|
||||
clientX = e.clientX, clientY = e.clientY;
|
||||
top = clientY + this.offsetY;
|
||||
top = this.clientHeight <= height || top <= 0 ? 0 : top + height >= this.clientHeight ? this.clientHeight - height : top;
|
||||
_ref = clientX <= this.clientWidth / 2 ? [clientX + this.offsetX + 'px', null] : [null, this.clientWidth - clientX + this.offsetX + 'px'], left = _ref[0], right = _ref[1];
|
||||
this.style.top = top + 'px';
|
||||
this.style.left = left;
|
||||
return this.style.right = right;
|
||||
top = this.isImage ? Math.max(0, clientY * (this.clientHeight - height) / this.clientHeight) : Math.max(0, Math.min(this.clientHeight - height, clientY - 120));
|
||||
threshold = this.clientWidth / 2;
|
||||
if (!this.isImage) {
|
||||
threshold = Math.max(threshold, this.clientWidth - 400);
|
||||
}
|
||||
_ref = clientX <= threshold ? [clientX + 45 + 'px', null] : [null, this.clientWidth - clientX + 45 + 'px'], left = _ref[0], right = _ref[1];
|
||||
style = this.style;
|
||||
style.top = top + 'px';
|
||||
style.left = left;
|
||||
return style.right = right;
|
||||
};
|
||||
hoverend = function(e) {
|
||||
if (e.type === 'keydown' && e.keyCode !== 13 || e.target.nodeName === "TEXTAREA") {
|
||||
return;
|
||||
}
|
||||
$.rm(this.el);
|
||||
if (!this.noRemove) {
|
||||
$.rm(this.el);
|
||||
}
|
||||
$.off(this.root, this.endEvents, this.hoverend);
|
||||
$.off(d, 'keydown', this.hoverend);
|
||||
$.off(this.root, 'mousemove', this.hover);
|
||||
@ -7196,10 +7178,25 @@
|
||||
return this.cb.call(this);
|
||||
}
|
||||
};
|
||||
checkbox = function(name, text, checked) {
|
||||
var input, label;
|
||||
if (checked == null) {
|
||||
checked = Conf[name];
|
||||
}
|
||||
label = $.el('label');
|
||||
input = $.el('input', {
|
||||
type: 'checkbox',
|
||||
name: name,
|
||||
checked: checked
|
||||
});
|
||||
$.add(label, [input, $.tn(text)]);
|
||||
return label;
|
||||
};
|
||||
return {
|
||||
dialog: dialog,
|
||||
Menu: Menu,
|
||||
hover: hoverstart
|
||||
hover: hoverstart,
|
||||
checkbox: checkbox
|
||||
};
|
||||
})();
|
||||
|
||||
@ -9784,11 +9781,10 @@
|
||||
dialog: function() {
|
||||
var dialog, event, i, items, match_max, match_min, name, node, nodes, rules, save, setNode;
|
||||
QR.nodes = nodes = {
|
||||
el: dialog = UI.dialog('qr', 'top:0;right:0;')
|
||||
el: dialog = UI.dialog('qr', 'top:0;right:0;', {
|
||||
innerHTML: "<div id=qrtab class=move>\r<input type=checkbox id=autohide title=Auto-hide>\r<div id=qr-thread-select>\r<select data-name=thread title='Create a new thread / Reply'>\r<option value=new>New thread</option>\r</select>\r</div>\r<a href=javascript:; class='close fa' title=Close>\\uf00d</a>\r</div>\r<form>\r<div class=persona>\r<input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1>\r<input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1>\r<input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1> \r</div>\r<div class=textarea>\r<textarea data-name=com placeholder=Comment class=field></textarea>\r<span id=char-count></span>\r</div>\r<div id=dump-list-container>\r<div id=dump-list></div>\r<a id=add-post href=javascript:; title=\"Add a post\">+</a>\r</div>\r<div id=file-n-submit>\r<span id=qr-filename-container class=field tabindex=0>\r<span id=qr-no-file>No selected file</span>\r<input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\">\r<span id=qr-extras-container>\r<label id=qr-spoiler-label>\r<input type=checkbox id=qr-file-spoiler title='Spoiler image'>\r</label>\r<span class=description>Spoiler</span>\r<a id=url-button><i class=\"fa\">\\uf0c1</i></a>\r<span class=description>Post from URL</span>\r<a id=dump-button title='Dump list'>+</a>\r<span class=description>Dump</span>\r<a id=qr-filerm href=javascript:; title='Remove file' class=fa>\\uf00d</a>\r<span class=description>Remove File</span>\r</span>\r</span>\r<input type=submit>\r</div>\r<input type=file multiple>\r</form>\r<datalist id=\"list-name\"></datalist>\r<datalist id=\"list-email\"></datalist>\r<datalist id=\"list-sub\"></datalist>\r"
|
||||
})
|
||||
};
|
||||
$.extend(dialog, {
|
||||
innerHTML: "<div id=qrtab class=move>\r<input type=checkbox id=autohide title=Auto-hide>\r<div id=qr-thread-select>\r<select data-name=thread title='Create a new thread / Reply'>\r<option value=new>New thread</option>\r</select>\r</div>\r<a href=javascript:; class='close fa' title=Close>\\uf00d</a>\r</div>\r<form>\r<div class=persona>\r<input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1>\r<input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1>\r<input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1> \r</div>\r<div class=textarea>\r<textarea data-name=com placeholder=Comment class=field></textarea>\r<span id=char-count></span>\r</div>\r<div id=dump-list-container>\r<div id=dump-list></div>\r<a id=add-post href=javascript:; title=\"Add a post\">+</a>\r</div>\r<div id=file-n-submit>\r<span id=qr-filename-container class=field tabindex=0>\r<span id=qr-no-file>No selected file</span>\r<input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\">\r<span id=qr-extras-container>\r<label id=qr-spoiler-label>\r<input type=checkbox id=qr-file-spoiler title='Spoiler image'>\r</label>\r<span class=description>Spoiler</span>\r<a id=url-button><i class=\"fa\">\\uf0c1</i></a>\r<span class=description>Post from URL</span>\r<a id=dump-button title='Dump list'>+</a>\r<span class=description>Dump</span>\r<a id=qr-filerm href=javascript:; title='Remove file' class=fa>\\uf00d</a>\r<span class=description>Remove File</span>\r</span>\r</span>\r<input type=submit>\r</div>\r<input type=file multiple>\r</form>\r<datalist id=\"list-name\"></datalist>\r<datalist id=\"list-email\"></datalist>\r<datalist id=\"list-sub\"></datalist>\r"
|
||||
});
|
||||
setNode = function(name, query) {
|
||||
return nodes[name] = $(query, dialog);
|
||||
};
|
||||
@ -14126,6 +14122,7 @@
|
||||
this.status = $('#watcher-status', this.dialog);
|
||||
this.list = this.dialog.lastElementChild;
|
||||
this.refreshButton = $('.refresh', this.dialog);
|
||||
this.unreaddb = Unread.db || new DataBoard('lastReadPosts');
|
||||
$.on(d, 'QRPostSuccessful', this.cb.post);
|
||||
if (g.VIEW === 'thread') {
|
||||
$.on(d, 'ThreadUpdate', this.cb.threadUpdate);
|
||||
|
||||
@ -181,14 +181,14 @@ Build =
|
||||
|
||||
### File Info ###
|
||||
|
||||
if file?.isDeleted
|
||||
fileCont = <%= html(
|
||||
fileCont = if file?.isDeleted
|
||||
<%= html(
|
||||
'<span class="fileThumb">' +
|
||||
'<img src="${staticPath}filedeleted-res${gifIcon}" alt="File deleted." class="fileDeletedRes retina">' +
|
||||
'</span>'
|
||||
) %>
|
||||
else if file and boardID is 'f'
|
||||
fileCont = <%= html(
|
||||
<%= html(
|
||||
'<div class="fileInfo"><span class="fileText" id="fT${postID}">' +
|
||||
'File: <a data-width="${file.width}" data-height="${file.height}" href="${file.url}" target="_blank">${file.name}</a>' +
|
||||
'-(${$.bytesToString(file.size)}, ${file.width}x${file.height}, ${file.tag})' +
|
||||
|
||||
@ -6,7 +6,7 @@ Header =
|
||||
className: 'menu-button a-icon'
|
||||
id: 'main-menu'
|
||||
|
||||
box = UI.checkbox.bind UI
|
||||
box = UI.checkbox
|
||||
|
||||
barFixedToggler = box 'Fixed Header', 'Fixed Header'
|
||||
headerToggler = box 'Header auto-hide', ' Auto-hide header'
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
UI = do ->
|
||||
dialog = (id, position, html) ->
|
||||
dialog = (id, position, properties) ->
|
||||
el = $.el 'div',
|
||||
className: 'dialog'
|
||||
innerHTML: html
|
||||
id: id
|
||||
$.extend el, properties
|
||||
el.style.cssText = position
|
||||
$.get "#{id}.position", position, (item) ->
|
||||
el.style.cssText = item["#{id}.position"]
|
||||
|
||||
move = $ '.move', el
|
||||
$.on move, 'touchstart mousedown', dragstart
|
||||
for child in move.children
|
||||
continue unless child.tagName
|
||||
$.on child, 'touchstart mousedown', (e) ->
|
||||
e.stopPropagation()
|
||||
|
||||
el
|
||||
|
||||
@ -17,7 +21,12 @@ UI = do ->
|
||||
currentMenu = null
|
||||
lastToggledButton = null
|
||||
|
||||
constructor: ->
|
||||
constructor: (@type) ->
|
||||
# XXX AddMenuEntry event is deprecated
|
||||
$.on d, 'AddMenuEntry', ({detail}) =>
|
||||
return if detail.type isnt @type
|
||||
delete detail.open
|
||||
@addEntry detail
|
||||
@entries = []
|
||||
|
||||
makeMenu: ->
|
||||
@ -47,7 +56,6 @@ UI = do ->
|
||||
menu = @makeMenu()
|
||||
currentMenu = menu
|
||||
lastToggledButton = button
|
||||
$.addClass button, 'open'
|
||||
|
||||
@entries.sort (first, second) ->
|
||||
first.order - second.order
|
||||
@ -95,9 +103,7 @@ UI = do ->
|
||||
|
||||
insertEntry: (entry, parent, data) ->
|
||||
if typeof entry.open is 'function'
|
||||
return unless entry.open data, (subEntry) =>
|
||||
@parseEntry subEntry
|
||||
entry.subEntries.push subEntry
|
||||
return unless entry.open data
|
||||
$.add parent, entry.el
|
||||
|
||||
return unless entry.subEntries
|
||||
@ -113,7 +119,7 @@ UI = do ->
|
||||
|
||||
close: =>
|
||||
$.rm currentMenu
|
||||
$.rmClass lastToggledButton, 'open'
|
||||
$.rmClass lastToggledButton, 'active'
|
||||
currentMenu = null
|
||||
lastToggledButton = null
|
||||
$.off d, 'click CloseMenu', @close
|
||||
@ -184,7 +190,7 @@ UI = do ->
|
||||
style.left = left
|
||||
style.right = right
|
||||
|
||||
addEntry: (entry) ->
|
||||
addEntry: (entry) =>
|
||||
@parseEntry entry
|
||||
@entries.push entry
|
||||
|
||||
@ -199,7 +205,6 @@ UI = do ->
|
||||
el.style.order = entry.order or 100
|
||||
return unless subEntries
|
||||
$.addClass el, 'has-submenu'
|
||||
$.addClass el, 'pfa'
|
||||
for subEntry in subEntries
|
||||
@parseEntry subEntry
|
||||
return
|
||||
@ -209,7 +214,7 @@ UI = do ->
|
||||
# prevent text selection
|
||||
e.preventDefault()
|
||||
if isTouching = e.type is 'touchstart'
|
||||
[..., e] = e.changedTouches
|
||||
e = e.changedTouches[e.changedTouches.length - 1]
|
||||
# distance from pointer to el edge is constant; calculate it here.
|
||||
el = $.x 'ancestor::div[contains(@class,"dialog")][1]', @
|
||||
rect = el.getBoundingClientRect()
|
||||
@ -302,76 +307,80 @@ UI = do ->
|
||||
$.off d, 'mouseup', @up
|
||||
$.set "#{@id}.position", @style.cssText
|
||||
|
||||
hoverstart = ({root, el, latestEvent, endEvents, asapTest, cb, offsetX, offsetY, noRemove}) ->
|
||||
hoverstart = ({root, el, latestEvent, endEvents, asapTest, height, cb, noRemove}) ->
|
||||
o = {
|
||||
root
|
||||
el
|
||||
style: el.style
|
||||
isImage: el.nodeName in ['IMG', 'VIDEO']
|
||||
cb
|
||||
close: close
|
||||
endEvents
|
||||
latestEvent
|
||||
clientHeight: doc.clientHeight
|
||||
clientWidth: doc.clientWidth
|
||||
offsetX: offsetX or 45
|
||||
offsetY: offsetY or -120
|
||||
noRemove
|
||||
}
|
||||
o.hover = hover.bind o
|
||||
o.hoverend = hoverend.bind o
|
||||
|
||||
if asapTest
|
||||
$.asap ->
|
||||
!el.parentNode or asapTest()
|
||||
, ->
|
||||
o.hover o.latestEvent if el.parentNode
|
||||
$.asap ->
|
||||
!el.parentNode or asapTest()
|
||||
, ->
|
||||
o.hover o.latestEvent if el.parentNode
|
||||
|
||||
$.on root, endEvents, o.hoverend
|
||||
if $.x 'ancestor::div[contains(@class,"inline")][1]', root
|
||||
$.on d, 'keydown', o.hoverend
|
||||
$.on root, 'mousemove', o.hover
|
||||
<% if (type === 'userscript') { %>
|
||||
# Workaround for https://github.com/MayhemYDG/4chan-x/issues/377
|
||||
# Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=674955
|
||||
o.workaround = (e) -> o.hoverend(e) unless root.contains e.target
|
||||
$.on doc, 'mousemove', o.workaround
|
||||
<% } %>
|
||||
|
||||
hover = (e) ->
|
||||
@latestEvent = e
|
||||
height = @el.offsetHeight + 25
|
||||
height = @height or @el.offsetHeight
|
||||
{clientX, clientY} = e
|
||||
|
||||
top = clientY + @offsetY
|
||||
top = if @clientHeight <= height or top <= 0
|
||||
0
|
||||
else if top + height >= @clientHeight
|
||||
@clientHeight - height
|
||||
top = if @isImage
|
||||
Math.max 0, clientY * (@clientHeight - height) / @clientHeight
|
||||
else
|
||||
top
|
||||
Math.max 0, Math.min(@clientHeight - height, clientY - 120)
|
||||
|
||||
[left, right] = if clientX <= @clientWidth / 2
|
||||
[clientX + @offsetX + 'px', null]
|
||||
threshold = @clientWidth / 2
|
||||
threshold = Math.max threshold, @clientWidth - 400 unless @isImage
|
||||
[left, right] = if clientX <= threshold
|
||||
[clientX + 45 + 'px', null]
|
||||
else
|
||||
[null, @clientWidth - clientX + @offsetX + 'px']
|
||||
[null, @clientWidth - clientX + 45 + 'px']
|
||||
|
||||
@style.top = top + 'px'
|
||||
@style.left = left
|
||||
@style.right = right
|
||||
{style} = @
|
||||
style.top = top + 'px'
|
||||
style.left = left
|
||||
style.right = right
|
||||
|
||||
hoverend = (e) ->
|
||||
return if e.type is 'keydown' and e.keyCode isnt 13 or e.target.nodeName is "TEXTAREA"
|
||||
$.rm @el
|
||||
$.rm @el unless @noRemove
|
||||
$.off @root, @endEvents, @hoverend
|
||||
$.off d, 'keydown', @hoverend
|
||||
$.off @root, 'mousemove', @hover
|
||||
<% if (type === 'userscript') { %>
|
||||
# Workaround for https://github.com/MayhemYDG/4chan-x/issues/377
|
||||
# Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=674955
|
||||
$.off doc, 'mousemove', @workaround
|
||||
<% } %>
|
||||
@cb.call @ if @cb
|
||||
|
||||
checkbox = (name, text, checked) ->
|
||||
checked = Conf[name] unless checked?
|
||||
label = $.el 'label'
|
||||
input = $.el 'input', {type: 'checkbox', name, checked}
|
||||
$.add label, [input, $.tn text]
|
||||
label
|
||||
|
||||
return {
|
||||
dialog: dialog
|
||||
Menu: Menu
|
||||
hover: hoverstart
|
||||
dialog: dialog
|
||||
Menu: Menu
|
||||
hover: hoverstart
|
||||
checkbox: checkbox
|
||||
}
|
||||
|
||||
28
src/General/eventPage/eventPage.coffee
Normal file
28
src/General/eventPage/eventPage.coffee
Normal file
@ -0,0 +1,28 @@
|
||||
requestID = 0
|
||||
|
||||
chrome.runtime.onMessage.addListener (request, sender, sendResponse) ->
|
||||
id = requestID
|
||||
requestID++
|
||||
sendResponse id
|
||||
|
||||
xhr = new XMLHttpRequest()
|
||||
xhr.open 'GET', request.url, true
|
||||
xhr.responseType = request.responseType
|
||||
xhr.addEventListener 'load', ->
|
||||
if @readyState is @DONE && xhr.status is 200
|
||||
contentType = @getResponseHeader 'Content-Type'
|
||||
contentDisposition = @getResponseHeader 'Content-Disposition'
|
||||
{response} = @
|
||||
if request.responseType is 'arraybuffer'
|
||||
response = [new Uint8Array(response)...]
|
||||
chrome.tabs.sendMessage sender.tab.id, {id, response, contentType, contentDisposition}
|
||||
else
|
||||
chrome.tabs.sendMessage sender.tab.id, {id, error: true}
|
||||
, false
|
||||
xhr.addEventListener 'error', ->
|
||||
chrome.tabs.sendMessage sender.tab.id, {id, error: true}
|
||||
, false
|
||||
xhr.addEventListener 'abort', ->
|
||||
chrome.tabs.sendMessage sender.tab.id, {id, error: true}
|
||||
, false
|
||||
xhr.send()
|
||||
@ -16,10 +16,13 @@ class DataBoard
|
||||
save: -> $.set @key, @data
|
||||
|
||||
delete: ({boardID, threadID, postID}) ->
|
||||
$.forceSync @key
|
||||
if postID
|
||||
return unless @data.boards[boardID]?[threadID]
|
||||
delete @data.boards[boardID][threadID][postID]
|
||||
@deleteIfEmpty {boardID, threadID}
|
||||
else if threadID
|
||||
return unless @data.boards[boardID]
|
||||
delete @data.boards[boardID][threadID]
|
||||
@deleteIfEmpty {boardID}
|
||||
else
|
||||
@ -27,6 +30,7 @@ class DataBoard
|
||||
@save()
|
||||
|
||||
deleteIfEmpty: ({boardID, threadID}) ->
|
||||
$.forceSync @key
|
||||
if threadID
|
||||
unless Object.keys(@data.boards[boardID][threadID]).length
|
||||
delete @data.boards[boardID][threadID]
|
||||
@ -35,6 +39,7 @@ class DataBoard
|
||||
delete @data.boards[boardID]
|
||||
|
||||
set: ({boardID, threadID, postID, val}) ->
|
||||
$.forceSync @key
|
||||
if postID isnt undefined
|
||||
((@data.boards[boardID] or= {})[threadID] or= {})[postID] = val
|
||||
else if threadID isnt undefined
|
||||
@ -60,39 +65,28 @@ class DataBoard
|
||||
thread
|
||||
val or defaultValue
|
||||
|
||||
forceSync: ->
|
||||
$.forceSync @key
|
||||
clean: ->
|
||||
now = Date.now()
|
||||
return if (@data.lastChecked or 0) > now - 2 * $.HOUR
|
||||
|
||||
# Don't even bother writing unless we have data to write
|
||||
keys = Object.keys @data.boards
|
||||
return unless keys.length
|
||||
|
||||
# Since we generated the keys anyways, use them to avoid the slow ``Object::hasOwnProperty`` method
|
||||
# Not that ``Object.keys`` is fast
|
||||
for boardID in keys
|
||||
$.forceSync @key
|
||||
for boardID, val of @data.boards
|
||||
@deleteIfEmpty {boardID}
|
||||
@ajaxClean boardID if boardID of @data.boards
|
||||
|
||||
@data.lastChecked = now
|
||||
now = Date.now()
|
||||
if (@data.lastChecked or 0) < now - 2 * $.HOUR
|
||||
@data.lastChecked = now
|
||||
for boardID of @data.boards
|
||||
for threadID of @data.boards[boardID]
|
||||
@ajaxClean boardID, threadID
|
||||
@save()
|
||||
|
||||
ajaxClean: (boardID) ->
|
||||
$.cache "//a.4cdn.org/#{boardID}/threads.json", (e) =>
|
||||
if e.target.status isnt 200
|
||||
@delete {boardID} if e.target.status is 404
|
||||
return
|
||||
board = @data.boards[boardID]
|
||||
threads = {}
|
||||
for page in e.target.response
|
||||
for thread in page.threads when thread.no of board
|
||||
threads[thread.no] = board[thread.no]
|
||||
count = Object.keys(threads).length
|
||||
return if count is Object.keys(board).length # Nothing changed.
|
||||
if count
|
||||
@set {boardID, val: threads}
|
||||
else
|
||||
@delete {boardID}
|
||||
ajaxClean: (boardID, threadID) ->
|
||||
$.ajax "//a.4cdn.org/#{boardID}/thread/#{threadID}.json",
|
||||
onloadend: (e) =>
|
||||
if e.target.status is 404
|
||||
@delete {boardID, threadID}
|
||||
,
|
||||
type: 'head'
|
||||
|
||||
onSync: (data) =>
|
||||
@data = data or boards: {}
|
||||
|
||||
@ -19,7 +19,7 @@ class Notice
|
||||
$.on d, 'visibilitychange', @add
|
||||
return
|
||||
$.off d, 'visibilitychange', @add
|
||||
$.add Header.noticesRoot, @el
|
||||
$.add doc, @el
|
||||
@el.clientHeight # force reflow
|
||||
@el.style.opacity = 1
|
||||
setTimeout @close, @timeout * $.SECOND if @timeout
|
||||
|
||||
@ -8,6 +8,7 @@ ThreadWatcher =
|
||||
@status = $ '#watcher-status', @dialog
|
||||
@list = @dialog.lastElementChild
|
||||
@refreshButton = $ '.refresh', @dialog
|
||||
@unreaddb = Unread.db or new DataBoard 'lastReadPosts'
|
||||
|
||||
$.on d, 'QRPostSuccessful', @cb.post
|
||||
$.on d, 'ThreadUpdate', @cb.threadUpdate if g.VIEW is 'thread'
|
||||
|
||||
@ -387,7 +387,7 @@ QR =
|
||||
dialog: ->
|
||||
QR.nodes = nodes =
|
||||
el: dialog = UI.dialog 'qr', 'top:0;right:0;',
|
||||
$.extend dialog, <%= importHTML('Features/QuickReply') %>
|
||||
<%= importHTML('Features/QuickReply') %>
|
||||
|
||||
setNode = (name, query) ->
|
||||
nodes[name] = $ query, dialog
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user