3874 lines
131 KiB
JavaScript
3874 lines
131 KiB
JavaScript
'use strict';
|
||
|
||
var style_cookie;
|
||
var style_cookie_txt;
|
||
var style_cookie_site;
|
||
var kumod_set=false;
|
||
var ispage;
|
||
var is_entering=false;
|
||
|
||
var _messages = {
|
||
en: {
|
||
noLocalStorage: "Your browser does not support LocalStorage",
|
||
oops: "Something went wrong...",
|
||
blankResponse: "blank response",
|
||
watchlistAdd: "Тред добавлен в список избранных.",
|
||
expandingThread: "Expanding thread...",
|
||
newThread: "new thread",
|
||
NewThread: "New thread",
|
||
replyTo: "reply to",
|
||
cancel: "Cancel",
|
||
update: "Update",
|
||
updatingCounts: "Updating...",
|
||
couldntFetch: "Cold not fetch this post",
|
||
noNewPosts: "No new posts",
|
||
replies: "Replies",
|
||
settings_fxEnabled: "Animation effects",
|
||
settings_showReplies: "Show replies inside posts",
|
||
settings_sfwMode: "NSFW mode",
|
||
settings_expandImgFull: "Expand images to full size",
|
||
settings_constrainWidth: "Constrain content width",
|
||
delete: "Delete post",
|
||
deleteAndBan: "Delete post and ban poster",
|
||
enterCaptcha: "Please enter captcha.",
|
||
selectText: "Select some text",
|
||
dcls: "Double click to show source",
|
||
watchOn: "Watch on",
|
||
captcharot: "Captcha has rotted",
|
||
threadUpdationAutomatically: "Tread is being updated automatically.",
|
||
stopFuckingDolls: "<b>Отключите AJAX-отправку постов и AJAX-обновление треда.</b><br />(Кликните, чтобы закрыть)",
|
||
del: "Delete",
|
||
delandban: "Delete and ban",
|
||
ban: "Ban",
|
||
stickthread: "Stick thread",
|
||
unstickthread: "Unstick thread",
|
||
lockthread: "Lock thread",
|
||
unlockthread: "Unlock thread",
|
||
returnDesktop: "Switch to desktop interface",
|
||
returnTouch: "Switch to touch interface",
|
||
forceDesktop: "Force Desktop interface",
|
||
okay: "Okay",
|
||
captchalang: "Captcha language",
|
||
reply: "Reply",
|
||
imageDownscaledBy: "Image was downscaled by",
|
||
videoDownscaledBy: "Video was downscaled by",
|
||
toFit: "to feet screen",
|
||
newReplies: "New replies",
|
||
newThreadsAvailable: "New threads available.",
|
||
loading: "Loading",
|
||
anonymous: "Anonymous",
|
||
sortBy: "Sort by",
|
||
bumpOrder: "Bump order",
|
||
lastReply: "Last reply",
|
||
creationDate: "Creation date",
|
||
replyCount: "Reply count",
|
||
doStick: "Respect stickied",
|
||
showHidden: "Show hidden",
|
||
doNotStick: "Ignore stickied",
|
||
hideHidden: "Hide hidden",
|
||
search: "Search",
|
||
threadOnPage: "Thread is on page",
|
||
goToThread: "Go to thread",
|
||
smallPics: "Small pictures",
|
||
largePics: "Large pictures",
|
||
legacyMode: "Legacy mode",
|
||
threads: "Threads",
|
||
comments: "Replies",
|
||
active_since: "Active since",
|
||
last_active: "Last seen",
|
||
active_on: "Active on",
|
||
tryAgain: "Try again",
|
||
xhrError: "XHR error",
|
||
details: "details",
|
||
post: 'Post',
|
||
posts: "Posts",
|
||
deleted:'has been deleted',
|
||
deletedMulti: 'have been deleted',
|
||
reported:'has been reported',
|
||
reportedMulti: 'have been reported',
|
||
fileRemoved: 'File<br>removed.',
|
||
file: 'File',
|
||
collapse: 'Collapse',
|
||
deleteAsMod: 'Delete as Mod',
|
||
deleteAsModVerbose: 'If the password does not match, delete posts using Moderator privelege'
|
||
},
|
||
ru: {
|
||
noLocalStorage: "localStorage не поддерживается браузером",
|
||
oops: "Что-то пошло не так...",
|
||
blankResponse: "пустой ответ",
|
||
watchlistAdd: "Тред добавлен в список избранных.",
|
||
watchlistRemove: "Тред удален из списка избранных.",
|
||
expandingThread: "Разворачиваем тред...",
|
||
newThread: "новый тред",
|
||
NewThread: "Создать тред",
|
||
replyTo: "ответ на",
|
||
cancel: "Отмена",
|
||
update: "Обновить",
|
||
updatingCounts: "Ищем новые посты...",
|
||
couldntFetch: "Не удалось загрузить этот пост",
|
||
noNewPosts: "Нет новых постов",
|
||
replies: "Ответы",
|
||
settings_fxEnabled: "Анимированные эффекты",
|
||
settings_showReplies: "Показывать ответы внутри поста",
|
||
settings_sfwMode: "Мамка в комнате",
|
||
settings_expandImgFull: "Разворачивать картинки до исходного размера",
|
||
settings_constrainWidth: "Ограничивать ширину контента",
|
||
delete: "Удалить пост",
|
||
deleteAndBan: "Удалить пост и забанить постера",
|
||
enterCaptcha: "Пожалуйста, введите капчу.",
|
||
selectText: "Текст не выделен",
|
||
dcls: "Double click to show source",
|
||
watchOn: "Смотреть на",
|
||
odc: "javascript:LatexIT.replaceWithSrc(this);",
|
||
captcharot: "Капча протухла",
|
||
threadUpdationAutomatically: "Тред обновляется автоматически",
|
||
stopFuckingDolls: "<b>Отключите AJAX-отправку постов и AJAX-обновление треда.</b><br />(Кликните, чтобы закрыть)",
|
||
del: "Удалить",
|
||
delandban: "Удалить и забанить",
|
||
ban: "Забанить",
|
||
stickthread: "Прикрепить тред",
|
||
unstickthread: "Отлепить тред",
|
||
lockthread: "Закрыть тред",
|
||
unlockthread: "Открыть тред",
|
||
returnDesktop: "Переключиться на десктопный интерфейс",
|
||
returnTouch: "Переключиться на тач-интерфейс",
|
||
forceDesktop: "Force Desktop interface",
|
||
okay: "Ясно",
|
||
captchalang: "Язык капчи",
|
||
reply: "Ответить",
|
||
imageDownscaledBy: "Картинка ужата на",
|
||
videoDownscaledBy: "Видео ужато на",
|
||
toFit: "по размеру окна",
|
||
newReplies: "Новых ответов",
|
||
newThreadsAvailable: "Доступны новые треды.",
|
||
loading: "Загружаем",
|
||
anonymous: "Аноним",
|
||
sortBy: "Сортировать по",
|
||
bumpOrder: "бампам",
|
||
lastReply: "дате ответов",
|
||
creationDate: "дате создания",
|
||
replyCount: "числу ответов",
|
||
doStick: "Прикреплять",
|
||
showHidden: "Показывать скрытые",
|
||
doNotStick: "Не прикреплять",
|
||
hideHidden: "Скрывать скрытые",
|
||
search: "Поиск",
|
||
threadOnPage: "Тред располагается на странице",
|
||
goToThread: "Перейти в тред",
|
||
smallPics: "Мелкие картинки",
|
||
largePics: "Большие картинки",
|
||
legacyMode: "Олдфажный режим",
|
||
threads: "Тредов",
|
||
comments: "Ответов",
|
||
active_since: "Присоединился",
|
||
last_active: "Был активен",
|
||
active_on: "Активен на",
|
||
tryAgain: "Попробовать снова",
|
||
xhrError: "Ошибка XHR",
|
||
details: "подробности",
|
||
post: 'Пост',
|
||
posts: 'Посты',
|
||
deleted:'удален',
|
||
deletedMulti: 'удалены',
|
||
reported:': жалоба отправлена',
|
||
reportedMulti: ': жалобы отправлены',
|
||
fileRemoved: 'Файл<br>удален.',
|
||
file: 'Файл',
|
||
collapse: 'Свернуть',
|
||
deleteAsMod: 'Удалять от лица модератора',
|
||
deleteAsModVerbose: 'Если пароль не совпадает, удалять чужие посты с использованием административных привелегий'
|
||
}
|
||
}
|
||
|
||
var _l = (typeof locale !== 'undefined' && _messages.hasOwnProperty(locale)) ? _messages[locale] : _messages.ru;
|
||
|
||
function trace() {
|
||
if (!console.log) return;
|
||
|
||
var f = arguments.callee.caller;
|
||
var path = arguments[0];
|
||
if (path == '') path += "trace()";
|
||
|
||
while (f != null) {
|
||
var re = /function ([^\(]+)/;
|
||
var fname = re.exec(f.toString());
|
||
if (fname == null) fname = ''; else fname = fname[1];
|
||
var args = [];
|
||
for (var i = 0; i < f.arguments.length; i++) args.push(f.arguments[i]);
|
||
fname += "(" + args.join(', ') + ")";
|
||
path += ' <- ' + fname;
|
||
f = f.caller;
|
||
}
|
||
console.log(path);
|
||
}
|
||
|
||
/* IE/Opera fix, because they need to go learn a book on how to use indexOf with arrays */
|
||
if (!Array.prototype.indexOf) {
|
||
Array.prototype.indexOf = function(elt /*, from*/) {
|
||
var len = this.length;
|
||
|
||
var from = Number(arguments[1]) || 0;
|
||
from = (from < 0)
|
||
? Math.ceil(from)
|
||
: Math.floor(from);
|
||
if (from < 0)
|
||
from += len;
|
||
|
||
for (; from < len; from++) {
|
||
if (from in this &&
|
||
this[from] === elt)
|
||
return from;
|
||
}
|
||
return -1;
|
||
};
|
||
}
|
||
|
||
/* Utf8 strings de-/encoder */
|
||
var Utf8 = {
|
||
// public method for url encoding
|
||
encode : function (string) {
|
||
string = string.replace(/\r\n/g,"\n");
|
||
var utftext = "";
|
||
for (var n = 0; n < string.length; n++) {
|
||
var c = string.charCodeAt(n);
|
||
if (c < 128) {
|
||
utftext += String.fromCharCode(c);
|
||
}
|
||
else if((c > 127) && (c < 2048)) {
|
||
utftext += String.fromCharCode((c >> 6) | 192);
|
||
utftext += String.fromCharCode((c & 63) | 128);
|
||
}
|
||
else {
|
||
utftext += String.fromCharCode((c >> 12) | 224);
|
||
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
||
utftext += String.fromCharCode((c & 63) | 128);
|
||
}
|
||
}
|
||
return utftext;
|
||
},
|
||
// public method for url decoding
|
||
decode : function (utftext) {
|
||
var string = "", i = 0, c = 0, c1 = 0, c2 = 0, c3 = 0
|
||
while ( i < utftext.length ) {
|
||
c = utftext.charCodeAt(i);
|
||
if (c < 128) {
|
||
string += String.fromCharCode(c);
|
||
i++;
|
||
}
|
||
else if((c > 191) && (c < 224)) {
|
||
c2 = utftext.charCodeAt(i+1);
|
||
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
||
i += 2;
|
||
}
|
||
else {
|
||
c2 = utftext.charCodeAt(i+1);
|
||
c3 = utftext.charCodeAt(i+2);
|
||
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
||
i += 3;
|
||
}
|
||
}
|
||
return string;
|
||
}
|
||
}
|
||
|
||
function Cookie(name) {
|
||
if (arguments.length == 1) {
|
||
// with(document.cookie) {
|
||
var regexp=new RegExp("(^|;\\s+)"+name+"=(.*?)(;|$)");
|
||
var hit=regexp.exec(document.cookie);
|
||
if(hit&&hit.length>2) return Utf8.decode(unescape(replaceAll(hit[2],'+','%20')));
|
||
else return '';
|
||
// }
|
||
} else {
|
||
var value = arguments[1]
|
||
, days = arguments[2]
|
||
, expires=""
|
||
if(days) {
|
||
var date=new Date();
|
||
date.setTime(date.getTime()+(days*24*60*60*1000));
|
||
expires="; expires="+date.toGMTString();
|
||
}
|
||
document.cookie=name+"="+value+expires+"; path=/";
|
||
}
|
||
}
|
||
|
||
|
||
function replaceAll(str, from, to) {
|
||
var idx = str.indexOf( from );
|
||
while ( idx > -1 ) {
|
||
str = str.replace( from, to );
|
||
idx = str.indexOf( from );
|
||
}
|
||
return str;
|
||
}
|
||
|
||
|
||
function insert(text) {
|
||
var textarea = (($('#postclone').length && $('#postclone').css('display') !== 'none') ? $('#postclone') : $('#postform')).find('textarea')[0];
|
||
if(textarea) {
|
||
if(textarea.createTextRange && textarea.caretPos) { // IE
|
||
var caretPos=textarea.caretPos;
|
||
caretPos.text=caretPos.text.charAt(caretPos.text.length-1)==" "?text+" ":text;
|
||
} else if(textarea.setSelectionRange) { // Firefox
|
||
var start=textarea.selectionStart;
|
||
var end=textarea.selectionEnd;
|
||
textarea.value=textarea.value.substr(0,start)+text+textarea.value.substr(end);
|
||
textarea.setSelectionRange(start+text.length,start+text.length);
|
||
} else {
|
||
textarea.value+=text+" ";
|
||
}
|
||
textarea.focus();
|
||
}
|
||
if($('#postclone').css('display') !== 'none') return false;
|
||
}
|
||
|
||
function markup($target, start, end, istart, iend) {
|
||
let element = $target.find('textarea').get(0);
|
||
if (element.selectionStart || element.selectionStart == '0') {
|
||
element.focus();
|
||
let startPos = element.selectionStart
|
||
, endPos = element.selectionEnd
|
||
, selected = element.value.substring(startPos, endPos);
|
||
if(selected.indexOf('\n') === (-1) && typeof istart !== "undefined" && typeof iend !== "undefined") {
|
||
start = istart; end = iend;
|
||
}
|
||
element.value = element.value.substring(0, startPos) + start + element.value.substring(startPos, endPos) + end + element.value.substring(endPos, element.value.length);
|
||
} else {
|
||
element.value += start + end;
|
||
}
|
||
}
|
||
|
||
function bullets($target, bullet, istart, iend) {
|
||
let $area = $target.find('textarea')
|
||
, element = $area.get(0)
|
||
, startPos = element.selectionStart
|
||
, endPos = element.selectionEnd
|
||
, selected = $area.val().substring(startPos, endPos)
|
||
if(selected.indexOf('\n') === (-1) && typeof istart !== "undefined" && typeof iend !== "undefined") {
|
||
element.value = element.value.substring(0, startPos) + istart + element.value.substring(startPos, endPos) + iend + element.value.substring(endPos, element.value.length);
|
||
}
|
||
else {
|
||
selected = $area.val().substring(startPos, endPos).split('\n');
|
||
var newtxt = "";
|
||
for(var i=0; i<selected.length; i++) {
|
||
newtxt += (bullet + selected[i]);
|
||
if(i < (selected.length - 1)) newtxt += '\n';
|
||
}
|
||
$area.val(
|
||
$area.val().substring(0, startPos)
|
||
+ newtxt +
|
||
$area.val().substring(endPos)
|
||
);
|
||
}
|
||
}
|
||
|
||
function quote(b, a) {
|
||
var v = eval("document." + a + ".message");
|
||
v.value += ">>" + b + "\n";
|
||
v.focus();
|
||
}
|
||
|
||
function checkhighlight() {
|
||
var match;
|
||
if(match=/#i([0-9]+)/.exec(document.location.toString()))
|
||
if(!$('#postform textarea').val())
|
||
insert(">>"+match[1]);
|
||
if(match=/#([0-9]+)/.exec(document.location.toString()))
|
||
highlight(match[1]);
|
||
}
|
||
|
||
function highlight(id, offTimeout=0) {
|
||
$('.highlight').removeClass('highlight');
|
||
let $post = $(`#delform a[name="${id}"]`).parents('.reply, .op')
|
||
, post = $post[0]
|
||
if (! post) return 'not-found';
|
||
$post.addClass('highlight');
|
||
if (offTimeout) {
|
||
setTimeout(() => $post.removeClass('highlight'), offTimeout)
|
||
}
|
||
// Scroll to post
|
||
let bcr = post.getBoundingClientRect()
|
||
, docHeight = document.documentElement.clientHeight
|
||
if (bcr.bottom > docHeight || bcr.top < 0) {
|
||
let postX = bcr.top + document.documentElement.scrollTop
|
||
, spaceAround = docHeight - bcr.height
|
||
window.scrollTo(0, postX - (spaceAround ? Math.ceil(spaceAround/2) : 0))
|
||
}
|
||
}
|
||
|
||
function get_password(name) {
|
||
var pass = getCookie(name);
|
||
if(pass) return pass;
|
||
|
||
var chars="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||
pass='';
|
||
|
||
for(var i=0;i<8;i++) {
|
||
var rnd = Math.floor(Math.random()*chars.length);
|
||
pass += chars.substring(rnd, rnd+1);
|
||
}
|
||
Cookie(name, pass, 365);
|
||
return(pass);
|
||
}
|
||
|
||
function togglePassword() {
|
||
var passwordbox_html = $("#passwordbox").html().toLowerCase();
|
||
var newhtml = '<td></td><td></td>';
|
||
if (passwordbox_html == newhtml) {
|
||
newhtml = '<td class="postblock">Mod</td><td><input type="text" name="modpassword" size="28" maxlength="75"> <acronym title="Display staff status (Mod/Admin)">D</acronym>: <input type="checkbox" name="displaystaffstatus" checked> <acronym title="Lock">L</acronym>: <input type="checkbox" name="lockonpost"> <acronym title="Sticky">S</acronym>: <input type="checkbox" name="stickyonpost"> <acronym title="Raw HTML">RH</acronym>: <input type="checkbox" name="rawhtml"> <acronym title="Name">N</acronym>: <input type="checkbox" name="usestaffname"></td>';
|
||
}
|
||
$("#passwordbox").html(newhtml).show();
|
||
return false;
|
||
}
|
||
|
||
/* used for textboards only, deleted, src in clean */
|
||
function toggleOptions(D,C,B){ trace('deprecated!') }
|
||
|
||
// proxied functions
|
||
function getCookie(name) { return Cookie(name) }
|
||
function set_cookie(name,value,days) { return Cookie(name,value,days) }
|
||
|
||
var Styles = {
|
||
all: [], titles: [],
|
||
init: function() {
|
||
_.each(document.getElementsByTagName("link"), function(link) {
|
||
if(link.getAttribute("rel").indexOf("style")!=-1 && link.getAttribute("title")) {
|
||
this.all.push(link);
|
||
this.titles.push(link.getAttribute("title"));
|
||
if(link.getAttribute("rel").indexOf("alternate")===-1) {
|
||
this._default = link.getAttribute("title");
|
||
}
|
||
if(link.hasAttribute("data-custom")) {
|
||
this.custom = link.getAttribute("title");
|
||
}
|
||
}
|
||
}, this);
|
||
this.current = this._default;
|
||
var customBypass = getCookie('bypasscustom');
|
||
this.customBypass = (customBypass.length && typeof this_board_dir !== 'undefined' && in_array(this_board_dir, customBypass.split('|'))) ? true : false;
|
||
this.initiated = true
|
||
},
|
||
decide: function() {
|
||
this.init();
|
||
var testingCSS = localStorage['testing-css'] || null
|
||
if(testingCSS) {
|
||
var title = this.addStyle(testingCSS)
|
||
this.setStyle(title)
|
||
var $clink = $('<a href="#">Отключить тестирование '+title+'.css</a>')
|
||
$clink.click(function(ev) {
|
||
ev.preventDefault()
|
||
Styles.quitTest()
|
||
$(this).parent().slideUp()
|
||
})
|
||
this.$cancelLink = $('<div style="font-weight: bold"></div>').append($clink)
|
||
return
|
||
}
|
||
if(this.hasOwnProperty('custom') && !this.customBypass)
|
||
return this.setCustom();
|
||
var sc = getCookie(style_cookie);
|
||
if(sc && in_array(sc, this.titles))
|
||
this.setStyle(sc);
|
||
else {
|
||
this.setDefault();
|
||
set_cookie("kustyle_site",this._default,365);
|
||
set_cookie("kustyle",this._default,365);
|
||
}
|
||
},
|
||
change: function(stylename) {
|
||
if(!in_array(stylename, this.titles) || this.current === stylename) return;
|
||
this.setStyle(stylename);
|
||
if(this.hasOwnProperty('custom') && this.custom === stylename) {
|
||
this.removeBypass();
|
||
}
|
||
else {
|
||
if(this.hasOwnProperty('custom'))
|
||
this.addBypass();
|
||
set_cookie("kustyle_site",stylename,365);
|
||
set_cookie("kustyle",stylename,365);
|
||
}
|
||
},
|
||
removeBypass: function() {
|
||
if(!this.customBypass || typeof this_board_dir === 'undefined') return;
|
||
this.customBypass = false;
|
||
var oldcookie = getCookie('bypasscustom').split('|'), newcookie = [];
|
||
_.each(oldcookie, function(brd) {
|
||
if(brd !== this_board_dir) newcookie.push(brd);
|
||
});
|
||
newcookie = newcookie.length ? newcookie.join('|') : '';
|
||
set_cookie("bypasscustom",newcookie,365);
|
||
},
|
||
addBypass: function() {
|
||
if(this.customBypass || typeof this_board_dir === 'undefined') return;
|
||
this.customBypass = true;
|
||
var cookie = getCookie('bypasscustom').split('|');
|
||
if(!in_array(this_board_dir, cookie)) {
|
||
cookie.push(this_board_dir);
|
||
set_cookie("bypasscustom",cookie.join('|'),365);
|
||
}
|
||
},
|
||
setDefault: function() {
|
||
if(this.hasOwnProperty('_default') && this.current !== this._default)
|
||
this.setStyle(this._default);
|
||
},
|
||
setCustom: function() {
|
||
if(this.hasOwnProperty('custom'))
|
||
this.setStyle(this.custom);
|
||
},
|
||
setStyle: function(stylename) {
|
||
if(!in_array(stylename, this.titles)) return;
|
||
if (scrollAnchor && scrollAnchor.save)
|
||
scrollAnchor.save('setstyle', '.postnode', window, 'v');
|
||
_.each(this.all, function(sheet) {
|
||
sheet.disabled=true; // Hello IE
|
||
if(sheet.getAttribute("title") === stylename)
|
||
sheet.disabled=false;
|
||
});
|
||
if (scrollAnchor && scrollAnchor.restore)
|
||
scrollAnchor.restore('setstyle');
|
||
this.current = stylename;
|
||
},
|
||
onTest: null,
|
||
addStyle: function(url) {
|
||
var m = /(?:.+\/)?(.+)\.css/i.exec(url);
|
||
if(!m) return;
|
||
var title = _.capitalize(_.escape(m[1]))
|
||
if(!in_array(title, this.titles)) {
|
||
var $link = $('<link rel="stylesheet" type="text/css" href="'+url+'" title="'+title+'" disabled>')
|
||
$('head').append($link);
|
||
this.titles.push(title)
|
||
this.all.push($link[0])
|
||
}
|
||
return title
|
||
},
|
||
testStyle: function(url) {
|
||
this.onTest = url
|
||
var title = this.addStyle(url)
|
||
this.setStyle(title)
|
||
popupMessage('Установлен стиль '+title+'.', 'none');
|
||
var $confirm = $('<button>OK</button>').click(this.confirmLongTermTest.bind(this))
|
||
, $reject = $('<button>'+_l.cancel+'</button>').click(this.quitTest.bind(this))
|
||
, $btns = $('<div class="pmsg-form"></div>').append($confirm, $reject)
|
||
$('#popupMessage').append($btns)
|
||
},
|
||
confirmLongTermTest: function() {
|
||
if(this.onTest)
|
||
localStorage.setItem('testing-css', this.onTest)
|
||
},
|
||
quitTest: function() {
|
||
localStorage.removeItem('testing-css')
|
||
this.decide()
|
||
}
|
||
}
|
||
|
||
if(style_cookie) Styles.decide();
|
||
|
||
function moddelcheckbox() {
|
||
$('.userdelete').append(`<label for="delasmod" title="${_l.deleteAsModVerbose}"><input${(+localStorage['deleteasmod']) ? ' checked' : ''} id="delasmod" type="checkbox" name="moddelete" val="1"> ${_l.deleteAsMod}</label>`)
|
||
$('#delasmod').change(function() {
|
||
let enabled = $(this).is(':checked')
|
||
localStorage['deleteasmod'] = +enabled
|
||
})
|
||
}
|
||
|
||
function delandbanlinks($scope=$('body')) {
|
||
$scope.find('span[id^=dnb]').each(function(index,element) {
|
||
let dnbinfo = $(this).attr('id').split('-')
|
||
/*, newhtml = `
|
||
<span class="btngroup">
|
||
<a href="${ku_cgipath}/manage_page.php?action=delposts&boarddir=${dnbinfo[1]}&del${dnbinfo[3] == 'y' ? 'thread' : 'post'}id=${dnbinfo[2]}" title="${_l.del}"
|
||
onclick="return confirm('${_l.delPost}?');">
|
||
<svg class="icon b-icon sb-l">
|
||
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-x"></use>
|
||
</svg>
|
||
</a>
|
||
<a href="${ku_cgipath}/manage_page.php?action=delposts&boarddir=${dnbinfo[1]}&del${dnbinfo[3] == 'y' ? 'thread' : 'post'}id=${dnbinfo[2]}&postid=${dnbinfo[2]}"
|
||
title="Удалить и забанить" onclick="return confirm('${_l.delAndBan}?');">
|
||
<svg class="icon b-icon sb-c">
|
||
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-and"></use>
|
||
</svg>
|
||
</a>
|
||
<a href="${ku_cgipath}/manage_page.php?action=bans&banboard=${dnbinfo[1]}&banpost=${dnbinfo[2]}" title="Забанить">
|
||
<svg class="icon b-icon sb-r">
|
||
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-ban"></use>
|
||
</svg>
|
||
</a>
|
||
</span>
|
||
`*/
|
||
, newhtml = `
|
||
<a href="${ku_cgipath}/manage_page.php?action=bans&banboard=${dnbinfo[1]}&banpost=${dnbinfo[2]}" title="${_l.ban}">
|
||
<svg class="icon b-icon">
|
||
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-ban"></use>
|
||
</svg>
|
||
</a>
|
||
`
|
||
|
||
if (dnbinfo[3] == 'y') {
|
||
newhtml += `
|
||
<a class="stickypost-btn" onclick="Ajax.modThread(this, 'stickypost'); return false"
|
||
href="${ku_cgipath}/manage_page.php?action=stickypost&board=${dnbinfo[1]}&postid=${dnbinfo[2]}" title="${_l.stickthread}">
|
||
<svg class="icon b-icon">
|
||
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-pin"></use>
|
||
</svg>
|
||
</a>
|
||
<a class="unstickypost-btn" onclick="Ajax.modThread(this, 'unstickypost'); return false"
|
||
href="${ku_cgipath}/manage_page.php?action=unstickypost&board=${dnbinfo[1]}&postid=${dnbinfo[2]}" title="${_l.unstickthread}">
|
||
<svg class="icon b-icon">
|
||
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-unpin"></use>
|
||
</svg>
|
||
</a>
|
||
<a class="lockpost-btn" onclick="Ajax.modThread(this, 'lockpost'); return false"
|
||
href="${ku_cgipath}/manage_page.php?action=lockpost&board=${dnbinfo[1]}&postid=${dnbinfo[2]}" title="${_l.lockthread}">
|
||
<svg class="icon b-icon">
|
||
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-lock"></use>
|
||
</svg>
|
||
</a>
|
||
<a class="unlockpost-btn" onclick="Ajax.modThread(this, 'unlockpost'); return false"
|
||
href="${ku_cgipath}/manage_page.php?action=unlockpost&board=${dnbinfo[1]}&postid=${dnbinfo[2]}" title="${_l.unlockthread}">
|
||
<svg class="icon b-icon">
|
||
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-unlock"></use>
|
||
</svg>
|
||
</a>
|
||
`
|
||
}
|
||
|
||
$(this).html(newhtml);
|
||
});
|
||
}
|
||
|
||
var HiddenThreads = {
|
||
list: function() {
|
||
if (localStorage == null) {
|
||
trace(_l.noLocalStorage);
|
||
return [];
|
||
}
|
||
var list = localStorage.getItem('hiddenThreads.' + this_board_dir);
|
||
if (list == null) return [];
|
||
return list.split(',');
|
||
},
|
||
isHidden: function(threadid) { return HiddenThreads.list().indexOf(threadid) != -1 },
|
||
hide: function(threadid) {
|
||
if (localStorage == null) alert(_l.noLocalStorage);
|
||
else {
|
||
var newlist = HiddenThreads.list();
|
||
newlist.push(threadid.toString());
|
||
localStorage.setItem('hiddenThreads.' + this_board_dir, newlist.join(','));
|
||
}
|
||
},
|
||
unhide: function(threadid) {
|
||
if (localStorage == null) alert(_l.noLocalStorage);
|
||
else {
|
||
var list = HiddenThreads.list();
|
||
var i = list.indexOf(threadid.toString());
|
||
if (i == -1) return;
|
||
var newlist = list.slice(0,i);
|
||
newlist = newlist.concat(list.slice(i+1));
|
||
localStorage.setItem('hiddenThreads.' + this_board_dir, newlist.join(','));
|
||
}
|
||
}
|
||
}
|
||
|
||
function togglethread(threadid) {
|
||
if (HiddenThreads.isHidden(threadid)) {
|
||
$('#unhidethread' + threadid + this_board_dir).slideUp();
|
||
$('#thread' + threadid + this_board_dir).slideDown();
|
||
HiddenThreads.unhide(threadid);
|
||
} else {
|
||
$('#unhidethread' + threadid + this_board_dir).slideDown();
|
||
$('#thread' + threadid + this_board_dir).slideUp();
|
||
HiddenThreads.hide(threadid);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
function toggleblotter() {
|
||
$('.blotter-entries').each(function(index,element) {
|
||
$(this).slideToggle(function() {
|
||
if($(this).is(":hidden")) {
|
||
Cookie('ku_showblotter', '0', 365);
|
||
} else {
|
||
Cookie('ku_showblotter', '1', 365);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
function hideblotter() {
|
||
$('.blotter-entries').each(function(index,element) {
|
||
$(this).hide();
|
||
});
|
||
}
|
||
|
||
function expandthread(threadid, board, ev) {
|
||
ev.preventDefault()
|
||
let $thread = $(`#thread${threadid}${board}`)
|
||
if ($thread.length) {
|
||
let expandFrom = + $thread.find('.postnode.op').find('input[type=checkbox]').val()
|
||
, expandTo = + $thread.find('.postnode:not(.op):first').find('input[type=checkbox]').val()
|
||
, $omitted = $thread.find('.omittedposts')
|
||
$omitted.find('a').hide()
|
||
let $msg = $omitted.find('span')
|
||
if (!$msg.length) {
|
||
$msg = $(`<span></span>`).prependTo($omitted)
|
||
}
|
||
$msg.text(`${_l.loading}...`)
|
||
HTMLoader.getThread(board, +threadid, [expandFrom, expandTo], (err, posts) => {
|
||
if (posts) {
|
||
$thread.find('.omittedposts').replaceWith(posts)
|
||
replyMap.showReplies()
|
||
}
|
||
else {
|
||
$msg.text(_l.oops + (err !== false ? ` (${err})` : ''))
|
||
$omitted.find('a').text(_l.tryAgain).show()
|
||
}
|
||
})
|
||
}
|
||
return false;
|
||
}
|
||
|
||
function getnewposts(threadid=null, scrollToID=null, onError = () => 'error') {
|
||
if(threadid===null) {
|
||
if (ispage) return onError();
|
||
threadid = $('input[name=replythread]').val()
|
||
}
|
||
let $lastQrl = $(`.qrl[data-parent="${threadid}"]`).last()
|
||
, lastpost = $lastQrl.data('postnum') || $lastQrl.data('parent')
|
||
if (! lastpost) return onError();
|
||
let replies_container, $newposts_get, $msg
|
||
if (!ispage) {
|
||
$newposts_get = $('#newposts_get')
|
||
$newposts_get.removeClass('upd-counting').addClass('upd-updating')
|
||
replies_container = document.querySelector('.replies')
|
||
}
|
||
else {
|
||
replies_container = document.querySelector(`#thread${threadid}${this_board_dir} .replies`)
|
||
if (!replies_container) return onError();
|
||
}
|
||
HTMLoader.getThread(this_board_dir, +threadid, [+lastpost,Infinity], (err, posts) => {
|
||
if (!ispage) {
|
||
$newposts_get.removeClass('upd-updating')
|
||
}
|
||
if (posts) {
|
||
replies_container.insertAdjacentHTML('beforeend', posts)
|
||
if (scrollToID) {
|
||
let allPosts = replies_container.querySelectorAll('.reply')
|
||
, targetReply = scrollToID=='last'
|
||
? allPosts[allPosts.length-1]
|
||
: Array.prototype.find.call(allPosts, post => post.querySelector(`a[name="${scrollToID}"]`))
|
||
if (! targetReply) {
|
||
return onError();
|
||
}
|
||
highlight(scrollToID, 5000)
|
||
}
|
||
replyMap.showReplies()
|
||
}
|
||
else {
|
||
if (scrollToID) {
|
||
return onError();
|
||
}
|
||
popupMessage(posts === '' ? _l.noNewPosts : _l.oops + (err !== false ? ` (${err})` : ''))
|
||
}
|
||
}, false, true)
|
||
return false;
|
||
}
|
||
|
||
function showLinks(ev) {
|
||
var href = $(this).attr('href');
|
||
$('#directLink').val(ku_boardspath+href);
|
||
$('#quoteLink').val('>>'+href.split('/res/')[0]+'/'+href.split('#')[1]);
|
||
$('#viewlink').css({
|
||
top: $(this).offset().top + $(this).height(),
|
||
left: $(this).offset().left
|
||
}).fadeIn('fast');
|
||
return false;
|
||
}
|
||
if(localStorage['pinPreference'] === 'pinned')
|
||
localStorage['pinForm'] = 0;
|
||
if(localStorage['pinPreference'] === 'unpinned')
|
||
localStorage['pinForm'] = 1;
|
||
localStorage.removeItem('pinPreference');
|
||
|
||
var goingExternal = false;
|
||
function quickreply(ev) {
|
||
var externalBoard = $(this).data('boardname');
|
||
if(externalBoard === this_board_dir) externalBoard = false;
|
||
var parent = $(this).data('parent'), current = $(this).data('postnum') || parent;
|
||
var preferUnpinned = !!+localStorage['pinForm'];
|
||
var appearsNew = ($('#postclone').css('display') === 'none');
|
||
$('#postclone').show();
|
||
if(isTouch) {
|
||
$('#postclone').css({
|
||
bottom: '0px',
|
||
left: '0px',
|
||
position: 'fixed',
|
||
opacity: 1
|
||
});
|
||
}
|
||
else {
|
||
if(preferUnpinned) {
|
||
$('#postclone').css({
|
||
top: $(this).offset().top + $(this).height(),
|
||
left: Math.round(($(window).width() / 2) - ($('#postclone').width() / 2)),
|
||
position: 'absolute'
|
||
});
|
||
}
|
||
else if(appearsNew) {
|
||
$('#postclone').css({
|
||
top: $(this).offset().top + $(this).height() - $(document).scrollTop(),
|
||
left: Math.round(($(window).width() / 2) - ($('#postclone').width() / 2)),
|
||
position: 'fixed'
|
||
});
|
||
}
|
||
}
|
||
$('#postclone input[name="replythread"]').val(parent);
|
||
if(externalBoard) {
|
||
$('#postclone input[name="board"]').val(externalBoard);
|
||
$('#postclone .posttypeindicator').html('<a href="'+ku_boardspath+'/'+externalBoard+'/res/'+parent+'.html?i#'+current+'"> >>/'+externalBoard+'/'+parent+'</a>');
|
||
}
|
||
else {
|
||
$('#postclone .posttypeindicator').html('<a class="xlink" href="#'+current+'"> >>'+parent+'</a>');
|
||
}
|
||
insert('>>'+current+'\n');
|
||
return false;
|
||
}
|
||
|
||
function getwatchedthreads(threadid, board) {
|
||
if ($('#watchedthreadlist').get()!='') {
|
||
$('#watchedthreadlist').html(_l.loading + '...');
|
||
$.ajax({
|
||
url: ku_boardspath + '/threadwatch.php?board=' + board + '&threadid=' + threadid,
|
||
success: function(data) {
|
||
$('#watchedthreadlist').html(data || (_l.oops + " ("+_l.blankResponse+")"));
|
||
},
|
||
error: function(xhr, status) {
|
||
$('#watchedthreadlist').html(_l.oops + " (" + status + ")");
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
function popupMessage(content, delay=1000) {
|
||
if ($('#popupMessage').get() == '') {
|
||
$('body').children().last().after('<div id="popupMessage" class="reply postername"></div>');
|
||
$('#popupMessage').hide()
|
||
}
|
||
$('#popupMessage').html(content.trim()).fadeIn(150)
|
||
if(delay !== 'none')
|
||
$('#popupMessage').delay(delay).fadeOut(300)
|
||
else
|
||
$('#popupMessage').click(function() {
|
||
$(this).fadeOut(300)
|
||
})
|
||
}
|
||
|
||
function addtowatchedthreads(threadid, board) {
|
||
if ($('#watchedthreadlist').get()!='') {
|
||
$.ajax({
|
||
url: ku_boardspath + '/threadwatch.php?do=addthread&board=' + board + '&threadid=' + threadid,
|
||
success: function(data) {
|
||
popupMessage(_l.watchlistAdd)
|
||
getwatchedthreads('0', board);
|
||
},
|
||
error: function(xhr, status) {
|
||
popupMessage(_l.oops + " (" + status + ")");
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
function removefromwatchedthreads(threadid, board) {
|
||
if ($('#watchedthreadlist').get()!='') {
|
||
$.ajax({
|
||
url: ku_boardspath + '/threadwatch.php?do=removethread&board=' + board + '&threadid=' + threadid,
|
||
success: function(data) {
|
||
popupMessage(_l.watchlistRemove)
|
||
getwatchedthreads('0', board);
|
||
},
|
||
error: function(xhr, status) {
|
||
popupMessage(_l.oops + " (" + status + ")");
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
function hidewatchedthreads() {
|
||
Cookie('showwatchedthreads','0',30);
|
||
$("#watchedthreads").fadeOut();
|
||
}
|
||
|
||
function showwatchedthreads() {
|
||
Cookie('showwatchedthreads','1',30);
|
||
window.location.reload(true);
|
||
}
|
||
|
||
var Captcha = {
|
||
init: function() {
|
||
$('.captchawrap').click(this.refresh.bind(this))
|
||
injector.inject('captcha-rotting',
|
||
`.cw-running .rotting-indicator {
|
||
-webkit-animation-duration: ${captchaTimeout}s;
|
||
-o-animation-duration: ${captchaTimeout}s;
|
||
animation-duration: ${captchaTimeout}s;
|
||
}
|
||
.cw-running .captchaimage,
|
||
.cw-running .rotten-msg {
|
||
-webkit-animation-delay: ${captchaTimeout}s;
|
||
-o-animation-delay: ${captchaTimeout}s;
|
||
animation-delay: ${captchaTimeout}s;}`)
|
||
},
|
||
refresh: function() {
|
||
if (!$('.captchawrap').length) return;
|
||
this.shownOnce = true
|
||
let cColor = $('.captchawrap').css('color').match(/([0-9]+(?:\.[0-9]+)?)/g)
|
||
cColor = (cColor.length >= 3) ? '&color='+cColor.slice(0, 3).join(',') : ''
|
||
$('.captchaimage').attr('src', ku_boardspath+'/captcha.php?'+Math.random()+cColor)
|
||
$('.captchawrap')
|
||
.removeClass('cw-initial cw-running')
|
||
.each(function() {void this.offsetWidth}) //trigger a reflow
|
||
.addClass('cw-running')
|
||
Array.prototype.forEach.call(document.querySelectorAll('input[name="captcha"]'), input => input.value = null)
|
||
},
|
||
refreshOnce: function() {
|
||
if (!this.shownOnce) {
|
||
this.refresh()
|
||
}
|
||
return false
|
||
},
|
||
shownOnce: false
|
||
}
|
||
|
||
function checkcaptcha(formid) {
|
||
if($('input[name=captcha]').length > 0) {
|
||
if($('#'+formid+' input[name=captcha]').val() =='') {
|
||
popupMessage(_l.enterCaptcha);
|
||
return false;
|
||
}
|
||
if(+$('.rotten-msg').css('opacity') > 0) {
|
||
popupMessage(_l.captcharot);
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
function handleSubmit(form) {
|
||
let captchafield = form.querySelector('input[name=captcha]')
|
||
if (captchafield && !captchafield.value.length)
|
||
return popupMessage(_l.enterCaptcha)
|
||
if (form.id === 'postclone')
|
||
ffdata.save()
|
||
Ajax.submitPost(form)
|
||
}
|
||
|
||
const Ajax = {
|
||
submitPost: function(form) {
|
||
form.classList.add('form-sending')
|
||
let fd = new FormData(form)
|
||
, xr = new XMLHttpRequest()
|
||
fd.append('AJAX', 1)
|
||
xr.open('POST', form.action)
|
||
xr.onload = e => {
|
||
form.classList.remove('form-sending')
|
||
if (xr.status !== 200) {
|
||
popupMessage(_l.xhrError)
|
||
return
|
||
}
|
||
;[].forEach.call(form.querySelectorAll('.error-in-attachment'), el => el.classList.remove('error-in-attachment'))
|
||
Captcha.refresh()
|
||
let res = null
|
||
try {
|
||
res = JSON.parse(xr.response)
|
||
}
|
||
catch(e) {
|
||
popupMessage(_l.xhrError)
|
||
console.error('Malformed response (JSON expected):', xr.response)
|
||
return
|
||
}
|
||
if (res.error) {
|
||
if (res.error_verbose)
|
||
res.error = `${res.error}<br>${res.error_verbose}`
|
||
if (res.error_type) {
|
||
if (res.error_type == 'ban') {
|
||
popupMessage(`${res.error} (<a href="${ku_cgipath}/banned.php" target="_blank">${_l.details}</a>)`, 'none')
|
||
}
|
||
if (res.error_type == 'duplicate_file') {
|
||
popupMessage(res.error, 'none')
|
||
form.querySelector('input[name="imagefile"]').value = null
|
||
}
|
||
if (res.error_type == 'upload_error') {
|
||
popupMessage(res.error, 'none')
|
||
let badatt = form.querySelector(`.multiembedwrap[data-pos="${res.error_data.attachmenttype}-${res.error_data.position+1}"]`)
|
||
if (badatt) {
|
||
badatt.classList.add('error-in-attachment')
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
popupMessage(res.error)
|
||
}
|
||
return
|
||
}
|
||
else {
|
||
resetForm(form)
|
||
if (form.id == "postclone") {
|
||
$(form).hide()
|
||
}
|
||
let noko = form.querySelector('input[name="redirecttothread"]').checked
|
||
if (res.thread_replyto != 0) {
|
||
getnewposts(ispage ? res.thread_replyto : null, +res.post_id, () => {
|
||
document.location.href = `${ku_boardspath}/${res.board}/res/${res.thread_replyto}.html#${res.post_id}`
|
||
if (! ispage)
|
||
document.location.reload()
|
||
})
|
||
}
|
||
else {
|
||
if (noko) {
|
||
document.location.href = `${ku_boardspath}/${res.board}/res/${res.post_id}.html`
|
||
}
|
||
else {
|
||
document.location.href = `${ku_boardspath}/${res.board}`
|
||
}
|
||
}
|
||
}
|
||
}
|
||
xr.send(fd)
|
||
},
|
||
deletePost: function(form) {
|
||
let fd = new FormData(form)
|
||
, xr = new XMLHttpRequest()
|
||
fd.append('AJAX', 1)
|
||
fd.append('deletepost', 1)
|
||
xr.open('POST', form.action)
|
||
xr.onload = e => {
|
||
if (xr.status !== 200) {
|
||
popupMessage(_l.xhrError)
|
||
return
|
||
}
|
||
let res = null
|
||
try {
|
||
res = JSON.parse(xr.response)
|
||
}
|
||
catch(e) {
|
||
popupMessage(_l.xhrError)
|
||
console.error('Malformed response (JSON expected):', xr.response)
|
||
return
|
||
}
|
||
if (res.error) {
|
||
if (res.error_verbose)
|
||
res.error = `${res.error}<br>${res.error_verbose}`
|
||
popupMessage(res.error, 'none')
|
||
return
|
||
}
|
||
else {
|
||
let postsDeleted = []
|
||
, postErrors = []
|
||
res.data.forEach(item => {
|
||
if (!item.success) {
|
||
postErrors.push(item)
|
||
return
|
||
}
|
||
let $thread = $(`#delform [id^=thread${item.id}]`)
|
||
, $reply = $(`#delform [id^=reply${item.id}]`)
|
||
if ($thread.length) {
|
||
$thread.prev().remove() //unhidethread
|
||
$thread.next().remove() //br
|
||
$thread.next().remove() //hr
|
||
$thread.remove()
|
||
}
|
||
else if ($reply.length) {
|
||
let $reply = $(`#delform [id^=reply${item.id}]`)
|
||
if ($reply.length) {
|
||
$reply.parents('.postnode').remove()
|
||
}
|
||
}
|
||
postsDeleted.push(item.id)
|
||
if (! $('input[name="post[]"]:checked').length)
|
||
$('.userdelete').removeClass('ud-active');
|
||
})
|
||
let msg = ''
|
||
if (postsDeleted.length) {
|
||
postsDeleted = postsDeleted.map(post => '#'+post)
|
||
msg += postsDeleted.length > 1 ?
|
||
`${_l.posts} ${postsDeleted.join(', ')} ${_l.deletedMulti}.`
|
||
:`${_l.post} ${postsDeleted[0]} ${_l.deleted}.`
|
||
}
|
||
postErrors.forEach(err => {
|
||
msg += `\n${_l.post} #${err.id}: ${err.message}`;
|
||
})
|
||
popupMessage(msg, 700 + 300*postsDeleted.length + 600*postErrors.length)
|
||
}
|
||
}
|
||
xr.send(fd)
|
||
},
|
||
reportPost: function(form) {
|
||
let fd = new FormData(form)
|
||
, xr = new XMLHttpRequest()
|
||
fd.append('AJAX', 1)
|
||
fd.append('reportpost', 1)
|
||
xr.open('POST', form.action)
|
||
xr.onload = e => {
|
||
if (xr.status !== 200) {
|
||
popupMessage(_l.xhrError)
|
||
return
|
||
}
|
||
let res = null
|
||
try {
|
||
res = JSON.parse(xr.response)
|
||
}
|
||
catch(e) {
|
||
popupMessage(_l.xhrError)
|
||
console.error('Malformed response (JSON expected):', xr.response)
|
||
return
|
||
}
|
||
if (res.error) {
|
||
if (res.error_verbose)
|
||
res.error = `${res.error}<br>${res.error_verbose}`
|
||
popupMessage(res.error, 'none')
|
||
return
|
||
}
|
||
else {
|
||
let postsReported = []
|
||
, postErrors = []
|
||
res.data.forEach(item => {
|
||
if (!item.success) {
|
||
postErrors.push(item)
|
||
return
|
||
}
|
||
postsReported.push(item.id)
|
||
if (! $('input[name="post[]"]:checked').length)
|
||
$('.userdelete').removeClass('ud-active');
|
||
})
|
||
let msg = ''
|
||
if (postsReported.length) {
|
||
postsReported = postsReported.map(post => '#'+post)
|
||
msg += postsReported.length > 1 ?
|
||
`${_l.posts} ${postsReported.join(', ')} ${_l.reportedMulti}.`
|
||
:`${_l.post} ${postsReported[0]} ${_l.reported}.`
|
||
}
|
||
postErrors.forEach(err => {
|
||
msg += `\n${_l.post} #${err.id}: ${err.message}`;
|
||
})
|
||
popupMessage(msg, 700 + 300*postsReported.length + 600*postErrors.length)
|
||
}
|
||
}
|
||
xr.send(fd)
|
||
},
|
||
deleteFile: function(id) {
|
||
let fd = new FormData()
|
||
, xr = new XMLHttpRequest()
|
||
fd.append('AJAX', 1)
|
||
fd.append('delete-file[]', id)
|
||
fd.append('moddelete', +$('input[name="moddelete"]').is(':checked'));
|
||
;['board', 'postpassword'].forEach(field => {
|
||
fd.append(field, $(`#delform input[name="${field}"]`).val())
|
||
})
|
||
xr.open('POST', $('#delform').attr('action'))
|
||
xr.onload = e => {
|
||
if (xr.status !== 200) {
|
||
popupMessage(_l.xhrError)
|
||
return
|
||
}
|
||
let res = null
|
||
try {
|
||
res = JSON.parse(xr.response)
|
||
}
|
||
catch(e) {
|
||
popupMessage(_l.xhrError)
|
||
console.error('Malformed response (JSON expected):', xr.response)
|
||
return
|
||
}
|
||
if (res.error) {
|
||
if (res.error_verbose)
|
||
res.error = `${res.error}<br>${res.error_verbose}`
|
||
popupMessage(res.error, 'none')
|
||
return
|
||
}
|
||
else {
|
||
let filesDeleted = []
|
||
, fileErrors = []
|
||
res.data.forEach(item => {
|
||
if (!item.success) {
|
||
fileErrors.push(item)
|
||
return
|
||
}
|
||
$(`figure[data-fileid=${item.id}]`)
|
||
.replaceWith(`<div class="nothumb">${_l.fileRemoved}</div>`)
|
||
})
|
||
let msg = ''
|
||
fileErrors.forEach(err => {
|
||
msg += `\n${_l.file} #${err.id}: ${err.message}`
|
||
})
|
||
if (msg)
|
||
popupMessage(msg, 700 + 600*fileErrors.length)
|
||
}
|
||
}
|
||
xr.send(fd)
|
||
},
|
||
modThread: function(a, action) {
|
||
let $a = $(a)
|
||
, fd = new FormData()
|
||
, xr = new XMLHttpRequest()
|
||
$a.addClass('spin-around')
|
||
fd.append('AJAX', 1)
|
||
xr.open('POST', a.getAttribute('href'))
|
||
xr.onload = e => {
|
||
$a.removeClass('spin-around')
|
||
if (xr.status !== 200) {
|
||
popupMessage(_l.xhrError)
|
||
return
|
||
}
|
||
let res = null
|
||
try {
|
||
res = JSON.parse(xr.response)
|
||
}
|
||
catch(e) {
|
||
popupMessage(_l.xhrError)
|
||
console.error('Malformed response (JSON expected):', xr.response)
|
||
return
|
||
}
|
||
if (res.error) {
|
||
if (res.error_verbose)
|
||
res.error = `${res.error}<br>${res.error_verbose}`
|
||
popupMessage(res.error, 'none')
|
||
return
|
||
}
|
||
else {
|
||
let $posthead = $a.parents('.posthead')
|
||
, $extrabtns = $posthead.find('.extrabtns')
|
||
if (action == 'stickypost') {
|
||
$extrabtns.prepend(`<svg class="icon i-icon i-pin"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-pin"></use></svg>`);
|
||
$posthead.addClass('thread-stickied')
|
||
}
|
||
if (action == 'unstickypost') {
|
||
$extrabtns.find('svg.i-icon.i-pin').remove()
|
||
$posthead.removeClass('thread-stickied')
|
||
}
|
||
if (action == 'lockpost') {
|
||
$extrabtns.prepend(`<svg class="icon i-icon i-lock"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-lock"></use></svg>`);
|
||
$posthead.addClass('thread-locked')
|
||
}
|
||
if (action == 'unlockpost') {
|
||
$extrabtns.find('svg.i-icon.i-lock').remove()
|
||
$posthead.removeClass('thread-locked')
|
||
}
|
||
popupMessage(res.message, 1000)
|
||
}
|
||
}
|
||
xr.send(fd)
|
||
}
|
||
}
|
||
|
||
function inspectFormData(formData) {
|
||
for (var pair of formData.entries()) {
|
||
console.log(pair[0]+ ', ' + pair[1]);
|
||
}
|
||
}
|
||
|
||
function expandimg(postnum, imgurl, thumburl, imgw, imgh, thumbw, thumbh) {
|
||
let element = document.getElementById("thumb" + postnum);
|
||
if (element == null) return false;
|
||
let $element = $(element)
|
||
, $postbody = $element.parents('.postbody')
|
||
, $fc_filename = $element.parents('figure').find('.fc-filename')
|
||
, fc_width
|
||
if(typeof event !== 'undefined' && event.which === 2) return true;
|
||
if (element.getElementsByTagName('img')[0].getAttribute('alt').substring(0,4)!='full') {
|
||
$element.html('<img src="'+imgurl+'" alt="full'+postnum+'" class="thumb" height="'+imgh+'" width="'+imgw+'">');
|
||
if (! Settings.expandImgFull()) {
|
||
let img = element.getElementsByTagName('img')[0]
|
||
, max_w = document.documentElement?document.documentElement.clientWidth : document.body.clientWidth
|
||
, offset = 50
|
||
, offset_el = img
|
||
|
||
while (offset_el != null) {
|
||
offset += offset_el.offsetLeft;
|
||
offset_el = offset_el.offsetParent;
|
||
}
|
||
var new_w = max_w - offset;
|
||
if (img.width > new_w) {
|
||
var ratio = img.width / img.height;
|
||
var zoom = 1 - new_w / img.width;
|
||
var new_h = new_w / ratio;
|
||
var notice = document.createElement('div');
|
||
notice.setAttribute('class', 'filesize');
|
||
notice.style.textDecoration = 'underline';
|
||
var textNode = document.createTextNode(_l.imageDownscaledBy + " " + Math.round(zoom*100) + "% "+_l.toFit);
|
||
notice.appendChild(textNode);
|
||
element.insertBefore(notice, img);
|
||
$(img).width(new_w);
|
||
$(img).height(new_h);
|
||
}
|
||
fc_width = new_w
|
||
}
|
||
else
|
||
fc_width = imgw
|
||
if ($postbody) $postbody.addClass('postbody-expanded')
|
||
}
|
||
else {
|
||
element.innerHTML = '<img src="' + thumburl + '" alt="' + postnum + '" class="thumb" height="' + thumbh + '" width="' + thumbw + '">';
|
||
fc_width = thumbw
|
||
if ($postbody) $postbody.removeClass('postbody-expanded')
|
||
}
|
||
$fc_filename[0].style.maxWidth = `${fc_width - 50}px`
|
||
return false;
|
||
}
|
||
|
||
// YOBA previews w/#snivystuff
|
||
var PostPreviews = {
|
||
zindex: 3,
|
||
cached: {},
|
||
parent: {},
|
||
|
||
_parseURL: function(url) {
|
||
let matches = url.match(/\/(.+)\/res\/([0-9]+)\.html#([0-9]+)|postbynumber\.php\?b=(.+)&p=([0-9]+)/i)
|
||
if (!matches) return null;
|
||
return {
|
||
board: matches[1] || matches[4],
|
||
parent: matches[2] || '?',
|
||
post: matches[3] || matches[5],
|
||
}
|
||
},
|
||
|
||
_mouseover: function(e) {
|
||
e.stopPropagation();
|
||
var href = this.getAttribute("href")
|
||
, isCatalog = $(this).hasClass('catalog-entry')
|
||
, parsedURL = PostPreviews._parseURL(href)
|
||
if (!parsedURL) return false;
|
||
let board = parsedURL['board']
|
||
, parentid = parsedURL['parent']
|
||
, postid = parsedURL['post']
|
||
, previewid = 'preview_'+board+'_'+postid
|
||
, preview = $('#' + previewid)
|
||
if (preview.length == 0) {
|
||
$('body').children().first().before('<div id="'+previewid+'"></div>');
|
||
preview = $('#' + previewid);
|
||
preview.addClass('reflinkpreview content-background pre-hidden actual-reflinkpreview');
|
||
preview.mouseleave(PostPreviews._mouseout);
|
||
preview.mouseover(PostPreviews.onMouseOver);
|
||
}
|
||
var parent = $(this).parents('div[id^=preview]');
|
||
if (parent.length > 0) {
|
||
if (previewid == parent.attr('id')) return; // anti-recursion
|
||
for (var id in PostPreviews.parent) { if (id == previewid || PostPreviews.parent[id] == previewid) return }
|
||
PostPreviews.parent[previewid] = parent.attr('id');
|
||
}
|
||
else {
|
||
PostPreviews.parent = [];
|
||
}
|
||
let transformOrigin;
|
||
if(e.clientY < ($(window).height() / 1.5)) {
|
||
preview.css({top:e.pageY+5});
|
||
transformOrigin = "top "
|
||
} else {
|
||
preview.css({bottom:$(window).height()-e.pageY+5});
|
||
transformOrigin = "bottom "
|
||
}
|
||
if(e.clientX < ($(window).width() / 1.5)) {
|
||
preview.css({left:e.pageX+15});
|
||
transformOrigin += "left"
|
||
} else {
|
||
preview.css({right:$(window).width()-e.pageX+15});
|
||
transformOrigin += "right"
|
||
}
|
||
preview.css({zIndex: PostPreviews.zindex++, "transform-origin": transformOrigin});
|
||
this.style.cursor = "progress"
|
||
HTMLoader.getPost(board, parentid, postid, (err, post) => {
|
||
window.setTimeout(() => {
|
||
preview.html(post ? post : (_l.oops + (err !== false ? ` (${err})` : '')))
|
||
.removeClass('pre-hidden')
|
||
this.style.cursor = "pointer"
|
||
}, 0)
|
||
})
|
||
e.preventDefault();
|
||
},
|
||
|
||
onMouseOver: function() {
|
||
var preview = $(this);
|
||
if ($(this).is('a')) {
|
||
let parsedURL = PostPreviews._parseURL(this.getAttribute("href"))
|
||
if (!parsedURL) return;
|
||
let board = parsedURL['board']
|
||
, postid = parsedURL['post']
|
||
preview = $('#preview_'+board+"_"+postid).first();
|
||
}
|
||
while (preview.length > 0) {
|
||
clearTimeout(preview[0].fadeout)
|
||
preview = $('#' + PostPreviews.parent[preview.attr('id')]);
|
||
}
|
||
},
|
||
|
||
_mouseout: function() {
|
||
var preview = $(this);
|
||
if ($(this).is('a')) {
|
||
if (this.predelay) {
|
||
clearTimeout(this.predelay)
|
||
}
|
||
let parsedURL = PostPreviews._parseURL(this.getAttribute("href"))
|
||
if (!parsedURL) return;
|
||
let board = parsedURL['board']
|
||
, postid = parsedURL['post']
|
||
preview = $('#preview_'+board+"_"+postid).first();
|
||
}
|
||
while (preview.length > 0) {
|
||
clearTimeout(preview[0].fadeout)
|
||
let pre = preview
|
||
preview[0].fadeout = setTimeout(() => {
|
||
pre.addClass('pre-hidden')
|
||
setTimeout(() => {
|
||
delete PostPreviews.parent[pre.attr('id')];
|
||
pre.remove();
|
||
}, PostPreviews._timings.transition)
|
||
}, PostPreviews._timings.fade)
|
||
preview = $('#' + PostPreviews.parent[preview.attr('id')]);
|
||
}
|
||
},
|
||
|
||
_timings: {
|
||
predelay: 50,
|
||
transition: 200,
|
||
fade: 400
|
||
}
|
||
}
|
||
|
||
/* txt only. deleted. src in clean */
|
||
function postpreview(D,A,C,B){}
|
||
|
||
function set_inputs(id) {
|
||
let form = document.getElementById(id)
|
||
if (form) {
|
||
let name = form.querySelector('input[name=name]')
|
||
if(name && !name.value) name.value = getCookie("name");
|
||
if(!form.em.value) form.em.value = getCookie("email");
|
||
if(!form.postpassword.value) form.postpassword.value = get_password("postpassword");
|
||
}
|
||
}
|
||
|
||
function set_delpass(id) {
|
||
let form = document.getElementById(id)
|
||
if (! form) return;
|
||
let postpassword = form.postpassword
|
||
if (postpassword && !postpassword.value) {
|
||
postpassword.value = get_password("postpassword");
|
||
}
|
||
}
|
||
|
||
(function ($) {
|
||
$.event.special.load = {
|
||
add: function (callback) {
|
||
if ( this.nodeType === 1 && this.tagName.toLowerCase() === 'img' && this.src !== '' ) {
|
||
if ( this.complete || this.readyState === 4 ) {
|
||
callback.handler.apply(this);
|
||
}
|
||
else if ( this.readyState === 'uninitialized' && this.src.indexOf('data:') === 0 ) {
|
||
$(this).trigger('error');
|
||
}
|
||
|
||
else {
|
||
$(this).bind('load', callback.handler);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
}(jQuery));
|
||
|
||
var Settings = {
|
||
_checkbox: function(clicked, settingName, defaultValue) {
|
||
if (localStorage == null) {
|
||
trace(_l.noLocalStorage);
|
||
return;
|
||
}
|
||
if (localStorage[settingName] == null) {
|
||
localStorage[settingName] = defaultValue;
|
||
}
|
||
if (clicked == true) {
|
||
// save it
|
||
localStorage[settingName] = $('#settings_' + settingName).is(":checked");
|
||
} else {
|
||
// update checkbox (called on load)
|
||
if (localStorage[settingName] == 'true')
|
||
$('#settings_' + settingName).attr("checked","checked");
|
||
else
|
||
$('#settings_' + settingName).removeAttr("checked");
|
||
}
|
||
return (localStorage[settingName] == 'true') || (localStorage[settingName] == true) ;
|
||
},
|
||
|
||
fxEnabled: function(changed) {
|
||
var enabled = Settings._checkbox(changed, 'fxEnabled', true);
|
||
if (changed != null) {
|
||
$.fx.off = !enabled;
|
||
}
|
||
return enabled;
|
||
},
|
||
|
||
showReplies: function(changed) {
|
||
var enabled = Settings._checkbox(changed, 'showReplies', true);
|
||
if (changed != null) {
|
||
scrollAnchor.save('replymap', '.postnode', window, 'v')
|
||
if (enabled) {
|
||
replyMap.showReplies()
|
||
injector.remove('hide-replies')
|
||
}
|
||
else {
|
||
injector.inject('hide-replies', '.replieslist {display: none}')
|
||
}
|
||
scrollAnchor.restore('replymap')
|
||
}
|
||
return enabled;
|
||
},
|
||
|
||
sfwMode: function(changed) {
|
||
var enabled = Settings._checkbox(changed, 'sfwMode', false);
|
||
if (enabled) {
|
||
injector.inject('sfwMode', '.thumb { opacity: 0.05;} .thumb:hover { opacity: 1;}');
|
||
}
|
||
else {
|
||
injector.remove('sfwMode');
|
||
}
|
||
return enabled;
|
||
},
|
||
|
||
expandImgFull: function(changed) {
|
||
return Settings._checkbox(changed, 'expandImgFull', false);
|
||
},
|
||
|
||
constrainWidth: function(changed) {
|
||
var enabled = Settings._checkbox(changed, 'constrainWidth', false);
|
||
if (enabled) {
|
||
injector.inject('constrainWidth', `body {
|
||
max-width: 960px;
|
||
margin: 0px auto;
|
||
}`)
|
||
}
|
||
else {
|
||
injector.remove('constrainWidth')
|
||
}
|
||
}
|
||
}
|
||
|
||
var rswap = {
|
||
i: true,
|
||
swap: function() {
|
||
if(this.i) $('#delform').before($('#rswapper')).after($('.postarea'));
|
||
else $('#delform').before($('.postarea')).after($('#rswapper'));
|
||
this.i = !this.i;
|
||
}
|
||
}
|
||
|
||
var isTouch = (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) || false;
|
||
if(localStorage['interfaceType'] == 'desktop')
|
||
isTouch = false;
|
||
if(localStorage['interfaceType'] == 'touch')
|
||
isTouch = true;
|
||
|
||
var captchalang = getCookie('captchalang') || 'ru';
|
||
function setCaptchaLang(lang) {
|
||
if(!in_array(lang, ['ru', 'en', 'num'])) return;
|
||
captchalang = lang;
|
||
set_cookie('captchalang', lang, 365);
|
||
}
|
||
|
||
function readyset() {
|
||
$('body').addClass('js-supported')
|
||
$('.make-me-readonly').each(function() {
|
||
$(this).attr('readonly', true)
|
||
.on('focus', function() {
|
||
$(this).removeAttr('readonly')
|
||
})
|
||
})
|
||
|
||
if(!ispage) $('.mgoback').show();
|
||
if(isTouch)
|
||
$('#js_settings').prepend('<a href="javascript: localStorage.setItem(\'interfaceType\', \'desktop\'); location.reload();">'+_l.returnDesktop+'</a><br>');
|
||
else
|
||
$('#js_settings').prepend('<a href="javascript: localStorage.setItem(\'interfaceType\', \'touch\'); location.reload();">'+_l.returnTouch+'</a><br>');
|
||
|
||
$('#js_settings').prepend(_l.captchalang+': <a href="javascript:setCaptchaLang(\'ru\');">Cyrillic</a> | <a href="javascript:setCaptchaLang(\'en\');">Latin</a> | <a href="javascript:setCaptchaLang(\'num\');">Numeral</a><br />');
|
||
|
||
if(Styles.$cancelLink)
|
||
$('#js_settings').prepend(Styles.$cancelLink)
|
||
|
||
LatexIT.init();
|
||
checkhighlight();
|
||
checkgotothread();
|
||
checknamesave();
|
||
|
||
bnrs.init();
|
||
|
||
cloud20.init();
|
||
$('#boardselect').on('input', function() {
|
||
cloud20.filter($(this).val());
|
||
});
|
||
|
||
if(getCookie('ku_menutype')) {
|
||
var c = Cookie('ku_menutype');
|
||
if(c != 'default' && c != '')
|
||
document.getElementById('overlay_menu').style.position = c;
|
||
}
|
||
|
||
//initial post-process
|
||
processNodeInsertion()
|
||
if (kumod_set)
|
||
moddelcheckbox()
|
||
|
||
if(!isTouch) {
|
||
$('.mobile-nav').hide();
|
||
$('.sect-exr').mouseenter(function() { menu_show('ms-'+$(this).data('toexpand')); });
|
||
$('#overlay_menu').mouseleave(function() { menu_show('_off_'); });
|
||
$('body').on('mouseenter', "a[class^='ref']", function(ev) {
|
||
this.predelay = setTimeout(() => PostPreviews._mouseover.bind(this)(ev), PostPreviews._timings.predelay)
|
||
});
|
||
$('body').on('mouseleave', "a[class^='ref']", PostPreviews._mouseout);
|
||
$('body').on('click', "a[class^='ref']", function(e) {
|
||
e.preventDefault()
|
||
let href = this.getAttribute('href')
|
||
if (highlight(href.split('#')[1]) == 'not-found') {
|
||
document.location.href = href
|
||
}
|
||
})
|
||
}
|
||
else {
|
||
$('body').addClass('touch-mode');
|
||
$('.sect-exr:not([data-toexpand="_options"])').parent().hide();
|
||
$('.sect-exr').click(function() {
|
||
if($('#js_settings').is(':visible')) {
|
||
menu_show('_off_');
|
||
}
|
||
else {
|
||
menu_show('ms-_options');
|
||
}
|
||
return false;
|
||
});
|
||
$('body').click(function(event) {
|
||
menu_show('_off_');
|
||
$('[id^=preview]').addClass('pre-hidden')
|
||
setTimeout(() => {
|
||
$('[id^=preview]').remove();
|
||
}, PostPreviews._timings.transition)
|
||
});
|
||
$('.mobile-nav').show();
|
||
$('body').on('click', "a[class^='ref']", PostPreviews._mouseover);
|
||
|
||
injector.inject('mb', 'body {margin-bottom: 350px;}')
|
||
}
|
||
|
||
// new markup
|
||
$('body').on('click', '.uib-mup', function() {
|
||
markup($(this).parents('form'), $(this).data('mups'), $(this).data('mupe'), $(this).data('imups'), $(this).data('imupe'));
|
||
return false;
|
||
});
|
||
$('.opt-exp').click(function() {
|
||
$(this).find('.expandee').toggleClass('expanded');
|
||
})
|
||
.mouseleave(function() {
|
||
$(this).find('.expandee').removeClass('expanded');
|
||
});
|
||
$('.code_markup_select').change(function() {
|
||
markup($(this).parents('form'), '[code='+$(this).val()+']', '[/code]');
|
||
})
|
||
$('body').on('click', '.uib-bul', function() {
|
||
bullets($(this).parents('form'), $(this).data('bul'), $(this).data('imups'), $(this).data('imupe'));
|
||
return false;
|
||
});
|
||
$('body').on('click', '.uib-tx', function() {
|
||
var target = $(this).data('target');
|
||
head.js('http://latex.codecogs.com/editor3.js', function() {
|
||
OpenLatexEditor(target,'phpBB','en-us', false, '','full');
|
||
});
|
||
return false;
|
||
});
|
||
//Webm expanding
|
||
$('body').on('click', '.movie', function(event) {expandwebm($(this), event)});
|
||
//new quick reply
|
||
$('body').on('click', '.qrl', quickreply);
|
||
$('#postclone label').each(function() {
|
||
let id =$(this).attr('for')
|
||
, newid = id+'_clone'
|
||
$(this).parents('form').find('#'+id).attr('id', newid);
|
||
$(this).attr('for', newid);
|
||
});
|
||
$('#postform textarea').attr('id', 'top-textarea'); $('#postform .uib-tx').data('target', 'top-textarea');
|
||
$('#postclone textarea').attr('id', 'pop-textarea'); $('#postclone .uib-tx').data('target', 'pop-textarea');
|
||
if(!isTouch) {
|
||
$('input, textarea, select, label').hover(function() {
|
||
$('#postclone').dragsOff();
|
||
}, function() {
|
||
$('#postclone').drags();
|
||
});
|
||
var pinnerState = !!+localStorage['pinForm'] ? 'pinned' : 'unpinned';
|
||
var pinner = '<a href="#" class="pinner '+pinnerState+'" onclick="javascript:$(\'#postclone\').pin();return false;" title="Прикрепить / Открепить"><svg class="icon b-icon"><use class="use-pin" xlink:href="#i-pin"></use><use class="use-unpin" xlink:href="#i-unpin"></use></svg></a>';
|
||
}
|
||
else {
|
||
var pinner = '';
|
||
}
|
||
|
||
/* not losing floating form data */
|
||
ffdata.load();
|
||
|
||
$('<span class="extrabtns postboxcontrol">'+ pinner +
|
||
' <a href="#" onclick="javascript:$(\'#postclone\').hide();return false;" title="Закрыть"><svg class="icon b-icon"><use xlink:href="#i-x"></use></svg></a>'+
|
||
'</span>').appendTo('#postclone');
|
||
|
||
//Dollscript rape begins
|
||
//Switch captcha language
|
||
/*dcxt.addTask(function() {
|
||
dcxt.openSettings();
|
||
//Switch to "form" tab
|
||
$('.de-cfg-tab[info=form]')[0].click();
|
||
//Switch language if it's set wrong
|
||
if(captchalang == 'ru' && $('select[info=captchaLang] option:selected').val() !== $('select[info=captchaLang] option:contains(Rus)').val()) {
|
||
$('select[info=captchaLang]').val($('select[info=captchaLang] option:contains(Rus)').val()).triggerNative('change');
|
||
}
|
||
if(captchalang == 'en' && $('select[info=captchaLang] option:selected').val() !== $('select[info=captchaLang] option:contains(Eng)').val()) {
|
||
$('select[info=captchaLang]').val($('select[info=captchaLang] option:contains(Eng)').val()).triggerNative('change');
|
||
}
|
||
dcxt.closeSettings();
|
||
});*/
|
||
|
||
/*if(liveupd_ena && typeof io !== 'undefined') {
|
||
// Remove malfunctioning post counter
|
||
injector.inject('dcxt-nocount', '.de-ppanel-cnt:after {display: none}');
|
||
$("#postform, #postclone").each(function() { $(this).append($('<input type="hidden" name="token">').val(randomString())) } );
|
||
$('#postform input[type="submit"]').after('<img class="sending-loading" src="'+ku_boardspath+'/images/loading.gif">')
|
||
var socket = io.connect(liveupd_api);
|
||
if(ispage) {
|
||
var subscribeTo = [liveupd_sitename+this_board_dir+':newthreads'];
|
||
$('.op .reflink').children(':last-child').each(function() {
|
||
subscribeTo.push(liveupd_sitename+this_board_dir+':'+$(this).text());
|
||
});
|
||
socket.on('update', updater.bpageNotify)
|
||
.emit('subscribe', subscribeTo);
|
||
}
|
||
else {
|
||
dcxt.addTask(function() {
|
||
dcxt.openSettings();
|
||
$('.de-cfg-tab[info=form]')[0].click();
|
||
//Detect if AJAX posting enabled.
|
||
if(+$('select[info=ajaxReply]').val()) {
|
||
updater.ajaxPosting = true;
|
||
}
|
||
//Switch to "posts" tab
|
||
$('.de-cfg-tab[info=posts]')[0].click();
|
||
//Turn off AJAX thread update
|
||
if($('input[info=ajaxUpdThr]:checked').length) {
|
||
$('input[info=ajaxUpdThr]:checked')[0].click();
|
||
dcxt.changed++;
|
||
}
|
||
dcxt.closeSettings();
|
||
});
|
||
_l.noNewPosts += ("<br>" + _l.threadUpdationAutomatically);
|
||
socket.emit('subscribe', liveupd_sitename+$('input[name=board]').val()+':'+$('input[name=replythread]').val());
|
||
socket.on('update', function(data) {
|
||
updater.update(data);
|
||
});
|
||
$('body').on('submit', '#postform, #postclone', function(e) {
|
||
e.preventDefault();
|
||
if (!dcxt.enabled || checkcaptcha($(this).attr('id')))
|
||
updater.send($(this));
|
||
});
|
||
}
|
||
}*/
|
||
|
||
$('body').on('submit', '#postform, #postclone', function(e) {
|
||
e.preventDefault()
|
||
handleSubmit(this)
|
||
});
|
||
|
||
$('#delform').on('submit', function(e) {
|
||
e.preventDefault()
|
||
Ajax.deletePost(this)
|
||
});
|
||
|
||
$('input[name=reportpost]').click(function(e) {
|
||
e.preventDefault()
|
||
Ajax.reportPost($(this).parents('form')[0])
|
||
})
|
||
|
||
$('body').on('click', '.delete-file', function(e) {
|
||
e.preventDefault()
|
||
e.stopPropagation()
|
||
let $this = $(this)
|
||
Ajax.deleteFile($this.parents('figure')[0].dataset['fileid'])
|
||
})
|
||
|
||
|
||
|
||
$('#delform').after('<div id="rswapper">[<a onclick="javascript:rswap.swap();return false;" href="#">'+(ispage ? _l.NewThread : _l.reply)+'</a>]<hr /></div>');
|
||
|
||
|
||
/*dcxt.addTask(function() {
|
||
$('#rswapper').remove();
|
||
})*/
|
||
|
||
Settings.sfwMode(false);
|
||
if (localStorage) {
|
||
for(var s in Settings) {
|
||
if (s.substring(0,1) == "_") continue;
|
||
$("#js_settings").append('<label><input type="checkbox" onchange="javascript:Settings.'+s+'(true)" name="settings_'+s+'" id="settings_'+s+'" value="true"> '+_l['settings_'+s]+'</label><br />');
|
||
Settings[s](false);
|
||
}
|
||
} else {
|
||
$("#js_settings").append("<span style=\"color:#F00\">"+_l.noLocalStorage+"</span><br />Твой браузер — говно. Скачай <a href=\"/web/20110329072959/http://google.com/chrome\" target=\"_blank\">Chome</a>, например.");
|
||
}
|
||
|
||
var textbox = document.getElementById('message');
|
||
if(textbox)
|
||
{
|
||
textbox.onfocus=function(){is_entering = true;}
|
||
textbox.onblur=function(){is_entering = false;}
|
||
}
|
||
|
||
$('body').on('click', '.posttypeindicator a', function() {
|
||
var xl = $(this);
|
||
var offset = $('[name="' + xl.attr('href').substr(1) + '"]').offset() || $('[name="' + xl.text().split('>>')[1] + '"]').offset() || false;
|
||
if(offset) {
|
||
$('html, body').animate({
|
||
scrollTop: offset.top - ( $('#overlay_menu').height() + 10 )
|
||
}, 250);
|
||
}
|
||
return false;
|
||
});
|
||
|
||
$('body').on('click', '.dice', function() {
|
||
if(typeof $(this).data('html') === 'undefined') $(this).data('html', $(this).html());
|
||
var htm = stripHTML($(this).html());
|
||
$(this).html($(this).attr('title'));
|
||
$(this).attr('title', htm);
|
||
});
|
||
|
||
//Permalinks and stuff
|
||
$('<div id="viewlink"></div>').addClass('content-background reflinkpreview qreplyform').html(
|
||
'<a style="float:left;" href="#" onclick="javascript:$(\'#viewlink\').hide();return false;"><svg style="margin-left:0" class="icon b-icon"><use xlink:href="#i-x"></use></svg></a>'+
|
||
'<div style="display:inline-block"><input type="text" id="directLink"><br /><input type="text" id="quoteLink"></div>'
|
||
).hide().appendTo('body');
|
||
$('body').on('click', '.shl', showLinks);
|
||
$('#directLink, #quoteLink').on("click", function() { $(this).select(); });
|
||
|
||
//Ultimate YOBA Youtube embeds
|
||
$('body').on('click','.embed-play-button', function(ev) {
|
||
ev.preventDefault()
|
||
unwrapEmbed($(this).parents('figure'))
|
||
});
|
||
$('body').on('click','.collapse-video', function(ev) {
|
||
ev.preventDefault()
|
||
wrapEmbed($(this).parents('figure'))
|
||
});
|
||
// $('body').on('click','.embed', function() {$(this).unwrap() });
|
||
//detect node insertions and process them
|
||
$(document).on('animationstart webkitAnimationStart MSAnimationStart oanimationstart', function(event) {
|
||
var $target = $(event.target);
|
||
if (event.originalEvent.animationName == "nodeInserted" && !$target.hasClass('_inserted_'))
|
||
processNodeInsertion($target);
|
||
});
|
||
$('body').on('mouseenter', '._country_', function() {
|
||
if(typeof $(this).attr('title') === "undefined") {
|
||
$(this).attr('title', countries[$(this).attr('src').split('flags/')[1].split('.png')[0].toUpperCase()]);
|
||
}
|
||
});
|
||
dcxt.performTasks();
|
||
|
||
$('body').on('click', '.audiowrap', function(ev) {
|
||
ev.preventDefault();
|
||
let $this = $(this)
|
||
var src = $this.attr('href');
|
||
let $fig = $this.parents('figure')
|
||
if (! $fig.hasClass('unwrapped')) {
|
||
$fig.addClass('unwrapped unwrapped-audio')
|
||
}
|
||
let $fsz = $fig.find('.filesize');
|
||
if (! $fsz.find('.collapse-btn').length)
|
||
$fsz.append(`
|
||
<button title="${_l.collapse}" class="emb-button collapse-video">
|
||
<svg class="icon b-icon"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-shrink"></use></svg>
|
||
</button>`);
|
||
if (! $this.find('audio').length)
|
||
$this.append('<audio src="'+src+'" controls autoplay="true"></audio>')
|
||
$fsz.find('.collapse-video').click(function() {
|
||
$fig.removeClass('unwrapped unwrapped-audio')
|
||
.find('audio')[0].pause()
|
||
})
|
||
})
|
||
|
||
$('input[name^=embed]').on('input', function() {
|
||
var match = embedLinks.process($(this).val());
|
||
if(match) {
|
||
$(this).val(match.code)
|
||
.parents('.multiembedwrap').find('[name^=embedtype]').val(match.site);
|
||
}
|
||
});
|
||
|
||
$('input[name^=imagefile]').on('change', function() {
|
||
let $this = $(this)
|
||
if ($this.val()) {
|
||
let nextCheckbox = $this.parent().next()
|
||
if (nextCheckbox.length)
|
||
nextCheckbox.prop('checked', true)
|
||
}
|
||
})
|
||
|
||
if(typeof is_catalog !== 'undefined' && is_catalog) catalog.init();
|
||
|
||
$('.userdelete').addClass('content-background reflinkpreview');
|
||
$('body').on('change', 'input[name="post[]"]', function() {
|
||
if (!$('.userdelete').hasClass('ud-active'))
|
||
$('.userdelete').addClass('ud-active');
|
||
else if (!($('input[name="post[]"]').is(":checked")))
|
||
$('.userdelete').removeClass('ud-active');
|
||
})
|
||
|
||
$('<div id="tripinfo"></div>').addClass('content-background reflinkpreview qreplyform').hide().appendTo('body');
|
||
|
||
$('#delform').on('click', '.postertrip', function(ev) {
|
||
ev.preventDefault()
|
||
var trip = $(this).text().split('!')[1]
|
||
, offset = $(this).offset(), height = $(this).height()
|
||
$.getJSON('/tripinfo.php', { trip: trip })
|
||
.done(function(data) {
|
||
var active_on = [];
|
||
_.each(data.active_on, function(board) {
|
||
active_on.push('<a target="_blank" href="'+ku_boardspath+'/'+board+'/">'+'/'+board+'/</a>');
|
||
})
|
||
$('#tripinfo')
|
||
.html(
|
||
'<div><b class="postertrip">!'+trip+'</b> ['+'<a href="https://www.google.com/search?q=!'+trip+'" target="_blank">G</a>]</div>'+
|
||
'<a style="float:left;" href="#" onclick="javascript:$(\'#tripinfo\').hide();return false;"><svg style="position: absolute; top: 3px; right: 3px;" class="icon b-icon"><use xlink:href="#i-x"></use></svg></a>'+
|
||
'<div class="trip-info-line">'+_l.threads+': '+data.threads+', '+_l.comments+': '+data.comments+'</div>'+
|
||
'<div class="trip-info-line">'+_l.active_since+': '+catalog.formatDate(data.active_since, true)+'</div>'+
|
||
'<div class="trip-info-line">'+_l.last_active+': '+catalog.formatDate(data.last_active, true)+'</div>'+
|
||
(active_on.length ? '<div class="trip-info-line">'+_l.active_on+': '+active_on.join(', ')+'</div>' : '')
|
||
)
|
||
.css({
|
||
top: offset.top + height,
|
||
left: offset.left
|
||
})
|
||
.fadeIn('fast');
|
||
})
|
||
.fail(function(error) {
|
||
console.error(error)
|
||
})
|
||
})
|
||
$('body').on('click', '.csswrap', function(ev) {
|
||
ev.preventDefault()
|
||
var cssLink = $(this).attr('href')
|
||
Styles.testStyle(cssLink)
|
||
})
|
||
|
||
$('input[name=disable_name]').on('change', function() {
|
||
var off = $(this).is(':checked')
|
||
$(this).parents('form').find('input[name=name]').attr('disabled', off)
|
||
localStorage.setItem('post_anonymously', +off)
|
||
})
|
||
.prop('checked', !!+localStorage['post_anonymously']).trigger('change')
|
||
|
||
unreadCounter.update()
|
||
|
||
Captcha.init()
|
||
}
|
||
|
||
// this will be applied to every new inserted node (post)
|
||
function processNodeInsertion($node) {
|
||
if(typeof $node === 'undefined')
|
||
$node = $('body');
|
||
else {
|
||
$node.addClass('_inserted_');
|
||
$node = $node.parents(":eq(1)");
|
||
}
|
||
if($node.find('.prettyprint').length)
|
||
prettyPrint.apply(window);
|
||
LatexIT.render($node);
|
||
processEmbeds($node);
|
||
if (kumod_set) {
|
||
delandbanlinks($node);
|
||
}
|
||
}
|
||
|
||
var dcxt = {
|
||
tries: 10,
|
||
enabled: false,
|
||
tasks: [],
|
||
changed: 0,
|
||
openSettings: function() {
|
||
if($('#de-content-cfg').length) return;
|
||
injector.inject('dcxt-hide', '#de-content-cfg {opacity: 0!important}');
|
||
$('#de-btn-settings')[0].click();
|
||
},
|
||
closeSettings: function() {
|
||
if(!$('#de-content-cfg').length) return;
|
||
$('#de-btn-settings')[0].click();
|
||
injector.remove('dcxt-hide');
|
||
},
|
||
addTask: function(fn) {
|
||
if(this.enabled) fn();
|
||
else this.tasks.push(fn);
|
||
},
|
||
performTasks: function() {
|
||
if(!this.enabled && $('#de-btn-settings').length) {
|
||
this.enabled = true;
|
||
$('#gotothread').prop('checked', true);
|
||
_.each(this.tasks, function(task) {
|
||
task();
|
||
});
|
||
this.tasks = [];
|
||
if(this.changed) location.reload();
|
||
}
|
||
else if(this.tries) {
|
||
setTimeout(function() {
|
||
dcxt.performTasks();
|
||
}, 500);
|
||
this.tries--;
|
||
}
|
||
}
|
||
}
|
||
|
||
var updater = {
|
||
ajaxPosting: false,
|
||
newThreads: [],
|
||
showNewThreads: function() {
|
||
$('#wild_thread_appeared').remove();
|
||
_.each(this.newThreads, function(thread) {
|
||
$.get(ku_boardspath+'/read.php?b='+this_board_dir+'&t='+this_board_dir+'&p='+thread+'&single&replink=1', function(data) {
|
||
$('#delform').prepend(data+'<br clear="left" /><hr />');
|
||
});
|
||
});
|
||
this.newThreads = [];
|
||
},
|
||
update: function(data) {
|
||
if(typeof data.token !== undefined) {
|
||
if($('input[name=token][value='+ data.token +']').length) {
|
||
// This is my post
|
||
clearfields($('input[name=token][value='+ data.token +']').parents('form'));
|
||
if(!this.ajaxPosting) getnewposts();
|
||
}
|
||
else {
|
||
getnewposts();
|
||
}
|
||
}
|
||
var lastvisits = localStorage['lastvisits'] ? (JSON.parse(localStorage['lastvisits']) || { }) : { };
|
||
if(typeof data.timestamp !== 'undefined') {
|
||
lastvisits[boardid] = data.timestamp;
|
||
localStorage.setItem('lastvisits', JSON.stringify(lastvisits));
|
||
}
|
||
},
|
||
bpageNotify: function(data) {
|
||
if($('input[name=token][value='+ data.token +']').length) return;
|
||
if(data.room == 'newthreads') {
|
||
if(dcxt.enabled) return;
|
||
updater.newThreads.push(data.newthread);
|
||
if(!$('#wild_thread_appeared').length)
|
||
$('.postarea').after('<a class="xlink" href="javascript:updater.showNewThreads();return false;" id="wild_thread_appeared">'+_l.newThreadsAvailable+'<hr /></a>');
|
||
}
|
||
else {
|
||
var $target = $('[id^=replies'+data.room+']');
|
||
if(!$target.find('.fresh-replies').text(_l.newReplies+': '+(Number(($target.find('.fresh-replies').text().split(':')[1]))+1)).length)
|
||
$target.append('<a href="/'+ this_board_dir +'/res/'+data.room+'.html" class="xlink fresh-replies">'+_l.newReplies+': 1</a>').find('.fresh-replies').click(function(e) {
|
||
e.preventDefault();
|
||
var $label = $(this);
|
||
var after = /\d+/.exec($target.find('.reply').last().attr('id'));
|
||
$.ajax({
|
||
url: ku_boardspath + '/expand.php?after=' + after + '&board=' + this_board_dir + '&threadid=' + data.room,
|
||
success: function(data) {
|
||
if (data) {
|
||
$target.append($(data));
|
||
replyMap.showReplies()
|
||
|
||
} else {
|
||
popupMessage(_l.noNewPosts);
|
||
}
|
||
$label.remove();
|
||
},
|
||
error: function(xhr, status) {
|
||
popupMessage(_l.oops + " (" + status + ")");
|
||
}
|
||
});
|
||
});
|
||
}
|
||
},
|
||
send: function($form) {
|
||
if(!this.ajaxPosting) {
|
||
xsend($form.attr('id'));
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
|
||
function processEmbeds($scope) {
|
||
$scope.find('.embed:not(.title-given)').each(function() {
|
||
var container = $(this);
|
||
var vidID = container.data('id');
|
||
if(container.data('site') === 'youtube') {
|
||
$.get('https://www.googleapis.com/youtube/v3/videos?part=id%2Csnippet&id='+vidID+'&key='+ku_youtube_apikey, function(res) {
|
||
if(!res.error && res.items.length) {
|
||
var videotitle = res.items[0].snippet.title;
|
||
container.append($('<a target="_blank" title="'+_l.watchOn+' Youtube"></a>').addClass('yt-title-overlay').text(videotitle).attr('href', 'http://www.youtube.com/watch?v='+vidID)
|
||
.click(function(ev) { ev.stopPropagation(); }));
|
||
}
|
||
});
|
||
container.addClass('title-given');
|
||
}
|
||
if(container.data('site') === 'vimeo') {
|
||
$.get('http://vimeo.com/api/v2/video/'+vidID+'.json', function(res) {
|
||
var videotitle = res[0].title, thumbnail = res[0].thumbnail_large;
|
||
container.css({'background-image': 'url('+thumbnail+')'})
|
||
.append($('<a target="_blank" title="'+_l.watchOn+' Vimeo"></a>').addClass('vi-title-overlay').text(videotitle).attr('href', 'http://vimeo.com/'+vidID)
|
||
.click(function(ev) { ev.stopPropagation(); }));
|
||
});
|
||
container.addClass('title-given');
|
||
}
|
||
if(container.data('site') === 'coub') {
|
||
$.get(ku_boardspath+'/corpsy.php?code='+vidID, function(res) {
|
||
var videotitle = res.title, thumbnail = res.thumbnail_url;
|
||
container.css({'background-image': 'url('+thumbnail+')'})
|
||
.append($('<a target="_blank" title="'+_l.watchOn+' Coub"></a>').addClass('co-title-overlay').text(videotitle).attr('href', 'http://coub.com/view/'+vidID)
|
||
.click(function(ev) { ev.stopPropagation(); }));
|
||
});
|
||
container.addClass('title-given');
|
||
}
|
||
});
|
||
}
|
||
|
||
if (+localStorage['localmod']) {
|
||
kumod_set = true
|
||
}
|
||
else {
|
||
let kumod = getCookie('kumod');
|
||
if (kumod !== '') {
|
||
if (kumod === 'allboards')
|
||
kumod_set = true
|
||
else
|
||
kumod_set = in_array(this_board_dir, kumod.split('|'));
|
||
}
|
||
}
|
||
|
||
|
||
|
||
var mp3playerid = 0;
|
||
function expandmp3(id, path){
|
||
if (mp3playerid == id)
|
||
{
|
||
document.getElementById('player'+id).innerHTML = '';
|
||
document.getElementById('player'+id).style.display = 'none';
|
||
mp3playerid = 0;
|
||
} else {
|
||
if(mp3playerid != 0)
|
||
{
|
||
document.getElementById('player'+mp3playerid).innerHTML = '';
|
||
document.getElementById('player'+mp3playerid).style.display = 'none';
|
||
}
|
||
|
||
document.getElementById('player'+id).innerHTML = '<embed src="/web/20110329072959/http://www.0chan.ru/mediaplayer.swf?type=mp3&file='+path+'" width="320" height="20">';
|
||
document.getElementById('player'+id).style.display = 'block';
|
||
mp3playerid = id;
|
||
}
|
||
}
|
||
|
||
var swfplayerid = 0;
|
||
function expandswf(id, path, w, h){
|
||
if (swfplayerid == id)
|
||
{
|
||
document.getElementById('swfplayer'+id).innerHTML = '';
|
||
document.getElementById('swfplayer'+id).style.display = 'none';
|
||
swfplayerid = 0;
|
||
} else {
|
||
if(swfplayerid != 0)
|
||
{
|
||
document.getElementById('swfplayer'+swfplayerid).innerHTML = '';
|
||
document.getElementById('swfplayer'+swfplayerid).style.display = 'none';
|
||
}
|
||
|
||
document.getElementById('swfplayer'+id).innerHTML = '<embed src="'+path+'" width="'+w+'" height="'+h+'">';
|
||
document.getElementById('swfplayer'+id).style.display = 'block';
|
||
swfplayerid = id;
|
||
}
|
||
}
|
||
|
||
|
||
function expandwebm($mov, ev) {
|
||
//good luck understanding this shitcode :^)
|
||
let $reply = $mov.parents('.reply')
|
||
if($mov.data('expanded') !== '1') {
|
||
ev.preventDefault();
|
||
var movieurl = $mov.attr('href'), imgh = $mov.data('height'), imgw = $mov.data('width'), dt = $mov.data('thumb'), postnum = $mov.data('id');
|
||
var uid = '_vframe_'+makeid()+(new Date().getTime());
|
||
$mov.replaceWith(function() {
|
||
return '<span id="'+uid+'" data-thumb="'+dt+'" data-width="'+imgw+'"" data-height="'+imgh+'" data-href="'+movieurl+'">'+this.innerHTML + '</span>';
|
||
});
|
||
$mov = $("#"+uid);
|
||
$mov.find('img').hide();
|
||
var video = $mov.find('video').show(), notice = '';
|
||
if(!video.length) {
|
||
$mov.find('.playable-thumb').append('<video class="thumb" src="'+movieurl+'" controls loop autoplay height="'+imgh+'" width="'+imgw+'"></video>').promise().done(function() {
|
||
video = $mov.find('video');
|
||
});
|
||
}
|
||
else video.get(0).play();
|
||
if(!Settings.expandImgFull()) {
|
||
var offset = 50, offset_el = video[0];
|
||
var max_w = document.documentElement?document.documentElement.clientWidth : document.body.clientWidth;
|
||
while (offset_el != null) {
|
||
offset += offset_el.offsetLeft;
|
||
offset_el = offset_el.offsetParent;
|
||
}
|
||
var new_w = max_w - offset;
|
||
if(imgw > new_w) {
|
||
var ratio = imgw / imgh;
|
||
var zoom = 1 - new_w / imgw;
|
||
var new_h = new_w / ratio;
|
||
video.width(new_w);
|
||
video.height(new_h);
|
||
notice = _l.videoDownscaledBy + " " + Math.round(zoom*100) + "% "+_l.toFit;
|
||
}
|
||
}
|
||
// $mov.parent().find('.filesize').append('<span class="videocloser"><b> [<a href="#"> x </a>]</b> '+notice+'</span>');
|
||
let $fig = $mov.parents('figure');
|
||
if (! $fig.hasClass('unwrapped')) {
|
||
$fig.addClass('unwrapped')
|
||
}
|
||
let $fsz = $mov.parent().find('.filesize');
|
||
if (! $fsz.find('.collapse-btn').length) {
|
||
$fsz.append(`
|
||
<button title="${_l.collapse}" class="emb-button collapse-video">
|
||
<svg class="icon b-icon"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-shrink"></use></svg>
|
||
</button>`);
|
||
$mov.parent().find('.collapse-video').click(function() {
|
||
$fig.removeClass('unwrapped')
|
||
var uid = '_vframe_'+makeid()+(new Date().getTime());
|
||
$mov.replaceWith(function() {
|
||
return '<a class="movie" id="'+uid+'" data-thumb="'+dt+'" data-width="'+imgw+'"" data-height="'+imgh+'" href="'+movieurl+'">'+this.innerHTML + '</a>';
|
||
}).data('expanded', '0');
|
||
$mov = $("#"+uid);
|
||
$mov.find('video').hide()[0].pause();
|
||
$mov.find('img').show();
|
||
$(this).remove();
|
||
$mov.parents('.reply').removeClass('reply-expanded')
|
||
return false;
|
||
});
|
||
}
|
||
$mov.parents('.reply').addClass('reply-expanded')
|
||
}
|
||
}
|
||
|
||
|
||
function makeid()
|
||
{
|
||
var text = "";
|
||
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||
|
||
for( var i=0; i < 5; i++ )
|
||
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
||
|
||
return text;
|
||
}
|
||
|
||
function checknamesave(){
|
||
var checkd;
|
||
if(getCookie('name') != '') {
|
||
checkd = true;
|
||
} else {
|
||
checkd = false;
|
||
}
|
||
var doc = document.getElementById('save');
|
||
if (doc != null) doc.checked = checkd;
|
||
}
|
||
function checkgotothread(){
|
||
var checkd;
|
||
if(getCookie('tothread') == 'on') {
|
||
checkd = true;
|
||
} else {
|
||
checkd = false;
|
||
}
|
||
$("#gotothread").attr('checked', checkd);
|
||
}
|
||
|
||
function navigatepages (event)
|
||
{
|
||
if (!document.getElementById) return;
|
||
if (is_entering) return;
|
||
if (window.event) event = window.event;
|
||
|
||
if (event.ctrlKey)
|
||
{
|
||
|
||
var link = null;
|
||
var href = null;
|
||
|
||
var docloc = document.location.toString();
|
||
if (docloc.indexOf('/res/') != -1) {
|
||
if( (event.keyCode ? event.keyCode : event.which ? event.which : null) == 13 )
|
||
$('textarea[name="message"]:focus').parents('form').submit();
|
||
}
|
||
else {
|
||
if (docloc.indexOf('.html') == -1 || docloc.indexOf('board.html') != -1) {
|
||
var page = 0;
|
||
var docloc_trimmed = docloc.substr(0, docloc.lastIndexOf('/') + 1);
|
||
} else {
|
||
var page = docloc.substr((docloc.lastIndexOf('/') + 1));
|
||
page = (+page.substr(0, page.indexOf('.html')));
|
||
var docloc_trimmed = docloc.substr(0, docloc.lastIndexOf('/') + 1);
|
||
}
|
||
if (page == 0) {
|
||
var docloc_valid = docloc_trimmed;
|
||
} else {
|
||
var docloc_valid = docloc_trimmed + page + '.html';
|
||
}
|
||
let match;
|
||
if(match=/#s([0-9]+)/.exec(docloc)) {
|
||
var relativepost = (+match[1]);
|
||
} else {
|
||
var relativepost = -1;
|
||
}
|
||
var maxthreads = 0;
|
||
while(document.getElementsByName('s'+(++maxthreads)).length>0){}
|
||
switch (event.keyCode ? event.keyCode : event.which ? event.which : null)
|
||
{
|
||
case 13: // ctrl+Enter
|
||
$('textarea[name="message"]:focus').parents('form').submit();
|
||
break;
|
||
|
||
case 0x25: // ctrl+left
|
||
link = document.getElementById('prevPage');
|
||
break;
|
||
case 0x27: // ctrl+right
|
||
link = document.getElementById('nextPage');
|
||
break;
|
||
|
||
case 0x28: // ctrl+down
|
||
if (relativepost == maxthreads - 1) {
|
||
break; //var newrelativepost = 0;
|
||
} else {
|
||
var newrelativepost = relativepost + 1;
|
||
}
|
||
href = docloc_valid + '#s' + newrelativepost;
|
||
break;
|
||
|
||
case 0x26: // ctrl+up
|
||
if (relativepost == -1 || relativepost == 0) {
|
||
break; //var newrelativepost = maxthreads - 1;
|
||
} else {
|
||
var newrelativepost = relativepost - 1;
|
||
}
|
||
href = docloc_valid + '#s' + newrelativepost;
|
||
break;
|
||
|
||
case 0x24: // ctrl+home
|
||
document.location = docloc_trimmed;
|
||
break;
|
||
}
|
||
|
||
if (link && link.action) document.location = link.action;
|
||
if (href) document.location.href = href;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if (window.document.addEventListener) {
|
||
window.document.addEventListener("keydown", navigatepages, false);
|
||
} else {
|
||
window.document.attachEvent("onkeydown", navigatepages);
|
||
}
|
||
|
||
NodeList.prototype.forEach = Array.prototype.forEach;
|
||
|
||
var replyMap = {
|
||
showReplies: function(root) {
|
||
;(root || document).querySelectorAll('.postnode').forEach(post => {
|
||
let n = post.querySelector('.reflink a:last-child').innerHTML
|
||
, msg = post.querySelector('.postmessage')
|
||
, repliesContainer = post.querySelector('.replieslist')
|
||
if (this.posts[n]) {
|
||
this.posts[n].container = repliesContainer
|
||
}
|
||
else {
|
||
this.posts[n] = {
|
||
container: repliesContainer,
|
||
replies: []
|
||
}
|
||
}
|
||
let links = msg.querySelectorAll(`a[class^=ref\\|${this_board_dir}]`)
|
||
if (links.length) links.forEach(link => {
|
||
let linkData = link.className.split(' ')[0].split('|')
|
||
, linkN = linkData[3]
|
||
, href = linkData[2] !== ''
|
||
? `/${linkData[1]}/res/${linkData[2]}.html#${n}`
|
||
: `${ku_boardspath}/postbynumber.php?b=${linkData[1]}&p=${linkData[3]}`
|
||
, htm = `<a class="ref-reply" href="${href}">>>${n}</a>`
|
||
if (this.posts[linkN]) {
|
||
if (! _.includes(this.posts[linkN].replies, htm)) {
|
||
this.posts[linkN].replies.push(htm)
|
||
}
|
||
}
|
||
else {
|
||
this.posts[linkN] = {
|
||
replies: [htm]
|
||
}
|
||
}
|
||
this.posts[linkN].skip = false
|
||
})
|
||
})
|
||
_.each(this.posts, post => {
|
||
if (!post.skip && post.replies.length && post.container) {
|
||
post.container.innerHTML = `${_l.replies}: ${post.replies.join(', ')}`
|
||
post.skip = true
|
||
}
|
||
})
|
||
},
|
||
posts: {}
|
||
}
|
||
|
||
var scrollAnchor = {
|
||
save: function(id, elements, parent, dimensions) {
|
||
parent = parent || window
|
||
dimensions = dimensions || 'vh'
|
||
let mid = [window.innerWidth / 2, window.innerHeight / 2]
|
||
, elMap = []
|
||
, parentBCR = (parent != window)
|
||
? parent.getBoundingClientRect()
|
||
: {
|
||
left: 0,
|
||
top: 0,
|
||
right: window.innerWidth,
|
||
bottom: window.innerHeight
|
||
}
|
||
if (
|
||
parent != window
|
||
&&
|
||
(
|
||
(parentBCR.left <= 0 && parentBCR.right <= 0)
|
||
||
|
||
(parentBCR.top <= 0 && parentBCR.bottom <= 0)
|
||
||
|
||
parentBCR.left >= window.innerWidth
|
||
||
|
||
parentBCR.top >= window.innerHeight
|
||
)
|
||
) {
|
||
mid = [parentBCR.left + parentBCR.width/2, parentBCR.top + parentBCR.height/2]
|
||
}
|
||
let elems = (parent == window ? document : parent).querySelectorAll(elements)
|
||
if (! elems.length) return;
|
||
elems.forEach(function (el) {
|
||
let bcr = el.getBoundingClientRect()
|
||
, relativeVisibleWidth = Math.pos(bcr.width - (Math.pos(parentBCR.left - bcr.left) + Math.pos(bcr.right - parentBCR.right))) / bcr.width
|
||
, relativeVisibleHeight = Math.pos(bcr.height - (Math.pos(parentBCR.top - bcr.top) + Math.pos(bcr.bottom - parentBCR.bottom))) / bcr.height
|
||
, dx = Math.abs(mid[0] - (bcr.left + bcr.width/2))
|
||
, dy = Math.abs(mid[1] - (bcr.top + bcr.height/2))
|
||
elMap.push({
|
||
el: el,
|
||
primaryVisibility: dimensions[0] == 'h' ? relativeVisibleWidth : relativeVisibleHeight,
|
||
secondaryVisibility: dimensions[0] == 'v' ? relativeVisibleWidth : relativeVisibleHeight,
|
||
primaryOffset: dimensions[0] == 'h' ? dx : dy,
|
||
secondaryOffset: dimensions[0] == 'v' ? dx : dy
|
||
})
|
||
})
|
||
elMap.sort((a, b) => {
|
||
if (b.primaryVisibility !== a.primaryVisibility) {
|
||
return b.primaryVisibility - a.primaryVisibility
|
||
}
|
||
else if (dimensions.length > 1 && b.secondaryVisibility !== a.secondaryVisibility) {
|
||
return b.secondaryVisibility - a.secondaryVisibility
|
||
}
|
||
else if (a.primaryOffset !== b.primaryOffset) {
|
||
return a.primaryOffset - b.primaryOffset
|
||
}
|
||
else if (dimensions.length > 1) {
|
||
return a.secondaryOffset - b.secondaryOffset
|
||
}
|
||
})
|
||
let anchor = elMap[0].el
|
||
, bcrBefore = anchor.getBoundingClientRect()
|
||
this.saved[id] = {
|
||
anchor: anchor,
|
||
left: bcrBefore.left,
|
||
top: bcrBefore.top,
|
||
parent: parent,
|
||
dimensions: dimensions
|
||
}
|
||
},
|
||
restore: function(id) {
|
||
let loaded = this.saved[id]
|
||
if (! loaded) return;
|
||
window.requestAnimationFrame(() => {
|
||
let bcrAfter = loaded.anchor.getBoundingClientRect()
|
||
loaded.parent.scrollBy(loaded.dimensions.indexOf('h') !== (-1) ? bcrAfter.left - loaded.left : 0, loaded.dimensions.indexOf('v') !== (-1) ? bcrAfter.top - loaded.top : 0)
|
||
})
|
||
},
|
||
saved: {}
|
||
}
|
||
Math.pos = x => x >= 0 ? x : 0;
|
||
|
||
// requestAnimationFrame polyfill https://gist.github.com/paulirish/1579671
|
||
(function() {
|
||
var lastTime = 0;
|
||
var vendors = ['ms', 'moz', 'webkit', 'o'];
|
||
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
||
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
|
||
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
|
||
}
|
||
|
||
if (!window.requestAnimationFrame)
|
||
window.requestAnimationFrame = function(callback, element) {
|
||
var currTime = new Date().getTime();
|
||
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||
var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
|
||
lastTime = currTime + timeToCall;
|
||
return id;
|
||
};
|
||
|
||
if (!window.cancelAnimationFrame)
|
||
window.cancelAnimationFrame = function(id) {
|
||
clearTimeout(id);
|
||
};
|
||
}());
|
||
|
||
/// overlay menu
|
||
var menu_current = '';
|
||
var menu_last = '';
|
||
function menu_show(id)
|
||
{
|
||
if(menu_current != '')
|
||
{
|
||
var dl = (id == '_off_') ? 125 : 0;
|
||
$('#'+menu_current).delay(dl).slideUp(100);
|
||
menu_last = menu_current;
|
||
}
|
||
if (id != '') {
|
||
if (menu_last == id && typeof $('#' + id).queue() !== 'undefined' && $('#' + id).queue().length > 0) {
|
||
$('#' + id).clearQueue();
|
||
} else {
|
||
$('#' + id).slideDown(150);
|
||
}
|
||
}
|
||
menu_current = id;
|
||
}
|
||
function menu_pin(){
|
||
if(document.getElementById('overlay_menu').style.position == 'absolute') {
|
||
document.getElementById('overlay_menu').style.position = 'fixed';
|
||
Cookie('ku_menutype', 'fixed', 365);
|
||
} else {
|
||
document.getElementById('overlay_menu').style.position = 'absolute';
|
||
Cookie('ku_menutype', 'absolute', 365);
|
||
}
|
||
}
|
||
|
||
function set_oldmenu(cookie){
|
||
if(cookie) {
|
||
Cookie('ku_oldmenu', 'yes', 90);
|
||
}
|
||
var h = document.getElementById('boardlist_header');
|
||
var f = document.getElementById('boardlist_footer');
|
||
if (h && f) {
|
||
h.innerHTML = f.innerHTML + ' <a href=\"#\" onclick=\"javascript:set_cookie(\'ku_oldmenu\', \'no\', 90);parent.document.location.reload(true);\">[overlay]</a>';
|
||
}
|
||
}
|
||
|
||
var LatexIT = {
|
||
mode : 'gif',
|
||
init : function() {
|
||
if(document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"))
|
||
this.mode='svg';
|
||
},
|
||
odc: "javascript:LatexIT.replaceWithSrc(this);",
|
||
dcls: "Double click to show source",
|
||
|
||
pre : function(eqn) {
|
||
var txt=eqn.innerHTML;
|
||
if ( !txt.match(/<img.*?>/i) && !txt.match(/<object.*?>/i))
|
||
{
|
||
//Clean code
|
||
txt=txt.replace(/<br>/gi,"").replace(/<br \/>/gi,"").replace(/&/mg,'&');
|
||
var atxt = "[tex]"+txt+"[/tex]";
|
||
txt=escape(txt.replace(/\\/mg,'\\'));
|
||
// Add coloring according to style of text
|
||
var c = eval("LatexIT.normalize"+$(eqn).parent().css('color'));
|
||
var extxt = "{\\color[rgb]{"+c.r+','+c.g+','+c.b+"}"+txt+"}";
|
||
txt = " <img src=\"http://latex.codecogs.com/"+this.mode+".latex?"+ extxt +"\" title=\""+this.dcls+"\" alt=\""+atxt+"\" ondblclick=\""+this.odc+"\" border=\"0\" class=\"latex\" /> ";
|
||
}
|
||
return txt;
|
||
},
|
||
|
||
replaceWithSrc: function(eqn) {
|
||
var txt = $(eqn).attr('alt');
|
||
$(eqn).parent().html(txt);
|
||
},
|
||
|
||
render : function($scope) {
|
||
var scope = (typeof $scope === 'undefined') ? window.document : $scope[0];
|
||
var eqn = scope.getElementsByTagName("*");
|
||
for (var i=0; i<eqn.length; i++) {
|
||
if(eqn[i].getAttribute("lang") == "latex" || eqn[i].getAttribute("xml:lang") == "latex")
|
||
eqn[i].innerHTML = this.pre(eqn[i]);
|
||
}
|
||
},
|
||
|
||
normalizergb : function(r, g, b) {
|
||
return {r: (r/255).toFixed(3), g: (g/255).toFixed(2), b: (b/255).toFixed(2) }
|
||
},
|
||
normalizergba : function(r, g, b, a) {
|
||
return this.normalizergb(r, g, b);
|
||
}
|
||
};
|
||
|
||
function in_array(needle, haystack) {
|
||
return (typeof haystack !== 'object') ? (needle === haystack) : _.includes(haystack, needle)
|
||
}
|
||
|
||
(function($) {
|
||
$.fn.drags = function(opt) {
|
||
opt = $.extend({handle:"",cursor:"move"}, opt);
|
||
|
||
if(opt.handle === "") {
|
||
var $el = this;
|
||
} else {
|
||
var $el = this.find(opt.handle);
|
||
}
|
||
|
||
return $el.css('cursor', opt.cursor).on("mousedown", function(e) {
|
||
if(opt.handle === "") {
|
||
var $drag = $(this).addClass('draggable');
|
||
} else {
|
||
var $drag = $(this).addClass('active-handle').parent().addClass('draggable');
|
||
}
|
||
var z_idx = $drag.css('z-index'),
|
||
drg_h = $drag.outerHeight(),
|
||
drg_w = $drag.outerWidth(),
|
||
pos_y = $drag.offset().top + drg_h - e.pageY,
|
||
pos_x = $drag.offset().left + drg_w - e.pageX;
|
||
$drag.css('z-index', 1000).parents().on("mousemove", function(e) {
|
||
$('.draggable').offset({
|
||
top:e.pageY + pos_y - drg_h,
|
||
left:e.pageX + pos_x - drg_w
|
||
}).on("mouseup", function() {
|
||
$(this).removeClass('draggable').css('z-index', z_idx);
|
||
});
|
||
});
|
||
e.preventDefault(); // disable selection
|
||
}).on("mouseup", function() {
|
||
if(opt.handle === "") {
|
||
$(this).removeClass('draggable');
|
||
} else {
|
||
$(this).removeClass('active-handle').parent().removeClass('draggable');
|
||
}
|
||
});
|
||
}
|
||
$.fn.dragsOff = function(opt) {
|
||
opt = $.extend({handle:"",cursor:"default"}, opt);
|
||
|
||
if(opt.handle === "") {
|
||
var $el = this;
|
||
$(this).removeClass('draggable');
|
||
} else {
|
||
var $el = this.find(opt.handle);
|
||
$(this).removeClass('active-handle')
|
||
.parent()
|
||
.removeClass('draggable');
|
||
}
|
||
return $el.css('cursor', "default")
|
||
.off("mousedown")
|
||
.off("mouseup")
|
||
.off("mousemove");
|
||
}
|
||
$.fn.pin = function() {
|
||
if(this.css('position') !== 'fixed') {
|
||
var abs = {
|
||
top: this.position().top - $(document).scrollTop(),
|
||
left: this.position().left - $(document).scrollLeft()
|
||
}
|
||
this.css({
|
||
position: 'fixed',
|
||
left: abs.left,
|
||
top: abs.top
|
||
});
|
||
this.find('.pinner').removeClass('pinned').addClass('unpinned');
|
||
localStorage['pinForm'] = 0;
|
||
// localStorage['pinPreference'] = 'pinned';
|
||
}
|
||
else {
|
||
var abs = {
|
||
top: this.position().top + $(document).scrollTop(),
|
||
left: this.position().left + $(document).scrollLeft()
|
||
}
|
||
this.css({
|
||
position: 'absolute',
|
||
left: abs.left,
|
||
top: abs.top
|
||
});
|
||
this.find('.pinner').removeClass('unpinned').addClass('pinned');
|
||
localStorage['pinForm'] = 1;
|
||
// localStorage['pinPreference'] = 'unpinned';
|
||
}
|
||
}
|
||
$.fn.triggerNative = function(eventName) {
|
||
return this.each(function() {
|
||
var el = $(this).get(0);
|
||
triggerNativeEvent(el, eventName);
|
||
});
|
||
};
|
||
function triggerNativeEvent(el, eventName){
|
||
if (el.fireEvent) { // < IE9
|
||
(el.fireEvent('on' + eventName));
|
||
} else {
|
||
var evt = document.createEvent('Events');
|
||
evt.initEvent(eventName, true, false);
|
||
el.dispatchEvent(evt);
|
||
}
|
||
}
|
||
})(jQuery);
|
||
|
||
function unwrapEmbed($fig) {
|
||
$fig.addClass('unwrapped')
|
||
let $iw = $fig.find('.emb-iframe-wrapper')
|
||
if ($iw.data('h') > $iw.data('w'))
|
||
$iw.addClass('vertical-video');
|
||
$iw.css({
|
||
paddingBottom: `${($iw.data('h')/$iw.data('w'))*100}%`
|
||
})
|
||
let code = $iw.data('code')
|
||
, iframeOptions = `frameborder="0" scrolling="no" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""`
|
||
if ($iw.data('site') == "Youtube")
|
||
$iw.append(`<iframe src="https://www.youtube.com/embed/${code}?autoplay=1" ${iframeOptions}></iframe>`)
|
||
if ($iw.data('site') == "Vimeo")
|
||
$iw.append(`<iframe src="//player.vimeo.com/video/${code}?badge=0&autoplay=1" ${iframeOptions}></iframe>`)
|
||
if ($iw.data('site') == "Coub")
|
||
$iw.append(`<iframe src="http://coub.com/embed/${code}?muted=false&autostart=true&originalSize=false&hideTopBar=false&noSiteButtons=false&startWithHD=false" ${iframeOptions}></iframe>`)
|
||
let $ew = $fig.find('.embed-wrap')
|
||
if (! $ew.find('.collapse-video').length)
|
||
$fig.find('.embed-wrap').append(`
|
||
<button title="${_l.collapse}" class="emb-button collapse-video">
|
||
<svg class="icon"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-shrink"></use></svg>
|
||
</button>`)
|
||
}
|
||
|
||
function wrapEmbed($fig) {
|
||
$fig.removeClass('unwrapped')
|
||
$fig.find('.emb-iframe-wrapper').empty()
|
||
}
|
||
|
||
function xsend(formid) {
|
||
if(typeof formid === 'undefined') formid = "postform";
|
||
$('#'+formid).ajaxSubmit({
|
||
beforeSubmit: function() {
|
||
$('#'+formid).addClass('form-sending');
|
||
},
|
||
success: function(responseText, statusText, xhr, $form) {
|
||
$('#'+formid).removeClass('form-sending');
|
||
var resp = $('<html></html>').append(responseText);
|
||
if(resp.find('h1').text() !== '') {
|
||
popupMessage(resp.find('h2').text());
|
||
clearfields($(formid), true);
|
||
}
|
||
else if(resp.find('.big-shit').text() !== '') {
|
||
if(resp.find('.big-shit').text() === 'Вы забанены!') {
|
||
window.location.href = ku_cgipath + "/banned.php";
|
||
}
|
||
popupMessage(resp.find('.big-shit').text());
|
||
clearfields($(formid), true);
|
||
}
|
||
}
|
||
});
|
||
return false;
|
||
}
|
||
|
||
function clearfields($form, onlycaptcha) {
|
||
if(typeof onlycaptcha === 'undefined') onlycaptcha = false;
|
||
if(!onlycaptcha) {
|
||
$form.find('[name="message"]').val('');
|
||
$form.find('[name="captcha"]').val('');
|
||
$form.find('[name="subject"]').val('');
|
||
$form.find('[name="imagefile"]').val('');
|
||
$form.find('[name="name"]').val('');
|
||
$form.find('[name="embed"]').val('');
|
||
$form.find('[name="token"]').val(randomString());
|
||
}
|
||
if(!dcxt.enabled) {
|
||
$('.captchawrap').stop();
|
||
clearTimeout(rottencaptcha);
|
||
rotCaptcha();
|
||
}
|
||
}
|
||
|
||
function resetForm(form) {
|
||
let fields = form.querySelectorAll('input[type=text]:not([name=name]), input[type=file], textarea')
|
||
Array.prototype.forEach.call(fields, field => field.value = null)
|
||
}
|
||
|
||
var injector = {
|
||
inject: function(alias, css) {
|
||
var id = `injector:${alias}`
|
||
var existing = document.getElementById(id)
|
||
if (existing) {
|
||
existing.innerHTML = css
|
||
return
|
||
}
|
||
var head = document.head || document.getElementsByTagName('head')[0]
|
||
, style = document.createElement('style')
|
||
style.type = 'text/css'
|
||
style.id = id
|
||
if (style.styleSheet) {
|
||
style.styleSheet.cssText = css
|
||
} else {
|
||
style.appendChild(document.createTextNode(css))
|
||
}
|
||
head.appendChild(style)
|
||
},
|
||
remove: function(alias) {
|
||
var id = `injector:${alias}`
|
||
var style = document.getElementById(id)
|
||
if (style) {
|
||
var head = document.head || document.getElementsByTagName('head')[0]
|
||
if (head)
|
||
head.removeChild(document.getElementById(id))
|
||
}
|
||
}
|
||
}
|
||
|
||
function randomString() {
|
||
var result = '', chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', length = 10;
|
||
for (var i = length; i > 0; --i) result += chars[Math.round(Math.random() * (chars.length - 1))];
|
||
return result;
|
||
}
|
||
|
||
var cloud20 = {
|
||
init: function() {
|
||
$.getJSON(ku_cgipath + '/boards20.json', function(data) {
|
||
cloud20.allboards = data;
|
||
cloud20.filter('');
|
||
});
|
||
},
|
||
filter: function(query) {
|
||
var res = [];
|
||
if(typeof this.allboards === "undefined") return;
|
||
if(query == '') res = this.allboards;
|
||
else {
|
||
query = query.toLowerCase();
|
||
_.each(this.allboards, function(board) {
|
||
if(board.name.toLowerCase().search(query) !== -1 || board.desc.toLowerCase().search(query) !== -1)
|
||
res.push(board);
|
||
});
|
||
}
|
||
this.display(res);
|
||
},
|
||
display: function(list) {
|
||
var newhtml = '', opts = '';
|
||
_.each(list, function(item) {
|
||
newhtml += '<a class="menu-item" title="'+ item.desc +'" href="'+ku_boardsfolder+item.name+'/">/'+item.name+'/ - '+ item.desc +'</a>';
|
||
opts += '<option value="'+item.name+'">/'+item.name+'/ - '+ item.desc +'</option>';
|
||
});
|
||
$('#boards20').html(newhtml);
|
||
$('.boardsel20').append(opts);
|
||
}
|
||
}
|
||
|
||
var countries = {
|
||
'A1': "Anonymous Proxy",
|
||
'A2': "Satellite Provider",
|
||
'O1': "Other Country",
|
||
'AD': "Andorra",
|
||
'AE': "United Arab Emirates",
|
||
'AF': "Afghanistan",
|
||
'AG': "Antigua and Barbuda",
|
||
'AI': "Anguilla",
|
||
'AL': "Albania",
|
||
'AM': "Armenia",
|
||
'AO': "Angola",
|
||
'AP': "Asia/Pacific Region",
|
||
'AQ': "Antarctica",
|
||
'AR': "Argentina",
|
||
'AS': "American Samoa",
|
||
'AT': "Austria",
|
||
'AU': "Australia",
|
||
'AW': "Aruba",
|
||
'AX': "Aland Islands",
|
||
'AZ': "Azerbaijan",
|
||
'BA': "Bosnia and Herzegovina",
|
||
'BB': "Barbados",
|
||
'BD': "Bangladesh",
|
||
'BE': "Belgium",
|
||
'BF': "Burkina Faso",
|
||
'BG': "Bulgaria",
|
||
'BH': "Bahrain",
|
||
'BI': "Burundi",
|
||
'BJ': "Benin",
|
||
'BL': "Saint Bartelemey",
|
||
'BM': "Bermuda",
|
||
'BN': "Brunei Darussalam",
|
||
'BO': "Bolivia",
|
||
'BQ': "Bonaire, Saint Eustatius and Saba",
|
||
'BR': "Brazil",
|
||
'BS': "Bahamas",
|
||
'BT': "Bhutan",
|
||
'BV': "Bouvet Island",
|
||
'BW': "Botswana",
|
||
'BY': "Belarus",
|
||
'BZ': "Belize",
|
||
'CA': "Canada",
|
||
'CC': "Cocos (Keeling) Islands",
|
||
'CD': "Congo, The Democratic Republic of the",
|
||
'CF': "Central African Republic",
|
||
'CG': "Congo",
|
||
'CH': "Switzerland",
|
||
'CI': "Cote d'Ivoire",
|
||
'CK': "Cook Islands",
|
||
'CL': "Chile",
|
||
'CM': "Cameroon",
|
||
'CN': "China",
|
||
'CO': "Colombia",
|
||
'CR': "Costa Rica",
|
||
'CU': "Cuba",
|
||
'CV': "Cape Verde",
|
||
'CW': "Curacao",
|
||
'CX': "Christmas Island",
|
||
'CY': "Cyprus",
|
||
'CZ': "Czech Republic",
|
||
'DE': "Germany",
|
||
'DJ': "Djibouti",
|
||
'DK': "Denmark",
|
||
'DM': "Dominica",
|
||
'DO': "Dominican Republic",
|
||
'DZ': "Algeria",
|
||
'EC': "Ecuador",
|
||
'EE': "Estonia",
|
||
'EG': "Egypt",
|
||
'EH': "Western Sahara",
|
||
'ER': "Eritrea",
|
||
'ES': "Spain",
|
||
'ET': "Ethiopia",
|
||
'EU': "Europe",
|
||
'FI': "Finland",
|
||
'FJ': "Fiji",
|
||
'FK': "Falkland Islands (Malvinas)",
|
||
'FM': "Micronesia, Federated States of",
|
||
'FO': "Faroe Islands",
|
||
'FR': "France",
|
||
'GA': "Gabon",
|
||
'GB': "United Kingdom",
|
||
'GD': "Grenada",
|
||
'GE': "Georgia",
|
||
'GF': "French Guiana",
|
||
'GG': "Guernsey",
|
||
'GH': "Ghana",
|
||
'GI': "Gibraltar",
|
||
'GL': "Greenland",
|
||
'GM': "Gambia",
|
||
'GN': "Guinea",
|
||
'GP': "Guadeloupe",
|
||
'GQ': "Equatorial Guinea",
|
||
'GR': "Greece",
|
||
'GS': "South Georgia and the South Sandwich Islands",
|
||
'GT': "Guatemala",
|
||
'GU': "Guam",
|
||
'GW': "Guinea-Bissau",
|
||
'GY': "Guyana",
|
||
'HK': "Hong Kong",
|
||
'HM': "Heard Island and McDonald Islands",
|
||
'HN': "Honduras",
|
||
'HR': "Croatia",
|
||
'HT': "Haiti",
|
||
'HU': "Hungary",
|
||
'ID': "Indonesia",
|
||
'IE': "Ireland",
|
||
'IL': "Israel",
|
||
'IM': "Isle of Man",
|
||
'IN': "India",
|
||
'IO': "British Indian Ocean Territory",
|
||
'IQ': "Iraq",
|
||
'IR': "Iran, Islamic Republic of",
|
||
'IS': "Iceland",
|
||
'IT': "Italy",
|
||
'JE': "Jersey",
|
||
'JM': "Jamaica",
|
||
'JO': "Jordan",
|
||
'JP': "Japan",
|
||
'KE': "Kenya",
|
||
'KG': "Kyrgyzstan",
|
||
'KH': "Cambodia",
|
||
'KI': "Kiribati",
|
||
'KM': "Comoros",
|
||
'KN': "Saint Kitts and Nevis",
|
||
'KP': "Korea, Democratic People's Republic of",
|
||
'KR': "Korea, Republic of",
|
||
'KW': "Kuwait",
|
||
'KY': "Cayman Islands",
|
||
'KZ': "Kazakhstan",
|
||
'LA': "Lao People's Democratic Republic",
|
||
'LB': "Lebanon",
|
||
'LC': "Saint Lucia",
|
||
'LI': "Liechtenstein",
|
||
'LK': "Sri Lanka",
|
||
'LR': "Liberia",
|
||
'LS': "Lesotho",
|
||
'LT': "Lithuania",
|
||
'LU': "Luxembourg",
|
||
'LV': "Latvia",
|
||
'LY': "Libyan Arab Jamahiriya",
|
||
'MA': "Morocco",
|
||
'MC': "Monaco",
|
||
'MD': "Moldova, Republic of",
|
||
'ME': "Montenegro",
|
||
'MF': "Saint Martin",
|
||
'MG': "Madagascar",
|
||
'MH': "Marshall Islands",
|
||
'MK': "Macedonia",
|
||
'ML': "Mali",
|
||
'MM': "Myanmar",
|
||
'MN': "Mongolia",
|
||
'MO': "Macao",
|
||
'MP': "Northern Mariana Islands",
|
||
'MQ': "Martinique",
|
||
'MR': "Mauritania",
|
||
'MS': "Montserrat",
|
||
'MT': "Malta",
|
||
'MU': "Mauritius",
|
||
'MV': "Maldives",
|
||
'MW': "Malawi",
|
||
'MX': "Mexico",
|
||
'MY': "Malaysia",
|
||
'MZ': "Mozambique",
|
||
'NA': "Namibia",
|
||
'NC': "New Caledonia",
|
||
'NE': "Niger",
|
||
'NF': "Norfolk Island",
|
||
'NG': "Nigeria",
|
||
'NI': "Nicaragua",
|
||
'NL': "Netherlands",
|
||
'NO': "Norway",
|
||
'NP': "Nepal",
|
||
'NR': "Nauru",
|
||
'NU': "Niue",
|
||
'NZ': "New Zealand",
|
||
'OM': "Oman",
|
||
'PA': "Panama",
|
||
'PE': "Peru",
|
||
'PF': "French Polynesia",
|
||
'PG': "Papua New Guinea",
|
||
'PH': "Philippines",
|
||
'PK': "Pakistan",
|
||
'PL': "Poland",
|
||
'PM': "Saint Pierre and Miquelon",
|
||
'PN': "Pitcairn",
|
||
'PR': "Puerto Rico",
|
||
'PS': "Palestinian Territory",
|
||
'PT': "Portugal",
|
||
'PW': "Palau",
|
||
'PY': "Paraguay",
|
||
'QA': "Qatar",
|
||
'RE': "Reunion",
|
||
'RO': "Romania",
|
||
'RS': "Serbia",
|
||
'RU': "Russian Federation",
|
||
'RW': "Rwanda",
|
||
'SA': "Saudi Arabia",
|
||
'SB': "Solomon Islands",
|
||
'SC': "Seychelles",
|
||
'SD': "Sudan",
|
||
'SE': "Sweden",
|
||
'SG': "Singapore",
|
||
'SH': "Saint Helena",
|
||
'SI': "Slovenia",
|
||
'SJ': "Svalbard and Jan Mayen",
|
||
'SK': "Slovakia",
|
||
'SL': "Sierra Leone",
|
||
'SM': "San Marino",
|
||
'SN': "Senegal",
|
||
'SO': "Somalia",
|
||
'SR': "Suriname",
|
||
'SS': "South Sudan",
|
||
'ST': "Sao Tome and Principe",
|
||
'SV': "El Salvador",
|
||
'SX': "Sint Maarten",
|
||
'SY': "Syrian Arab Republic",
|
||
'SZ': "Swaziland",
|
||
'TC': "Turks and Caicos Islands",
|
||
'TD': "Chad",
|
||
'TF': "French Southern Territories",
|
||
'TG': "Togo",
|
||
'TH': "Thailand",
|
||
'TJ': "Tajikistan",
|
||
'TK': "Tokelau",
|
||
'TL': "Timor-Leste",
|
||
'TM': "Turkmenistan",
|
||
'TN': "Tunisia",
|
||
'TO': "Tonga",
|
||
'TR': "Turkey",
|
||
'TT': "Trinidad and Tobago",
|
||
'TV': "Tuvalu",
|
||
'TW': "Taiwan",
|
||
'TZ': "Tanzania, United Republic of",
|
||
'UA': "Ukraine",
|
||
'UG': "Uganda",
|
||
'UM': "United States Minor Outlying Islands",
|
||
'US': "United States",
|
||
'UY': "Uruguay",
|
||
'UZ': "Uzbekistan",
|
||
'VA': "Holy See (Vatican City State)",
|
||
'VC': "Saint Vincent and the Grenadines",
|
||
'VE': "Venezuela",
|
||
'VG': "Virgin Islands, British",
|
||
'VI': "Virgin Islands, U.S.",
|
||
'VN': "Vietnam",
|
||
'VU': "Vanuatu",
|
||
'WF': "Wallis and Futuna",
|
||
'WS': "Samoa",
|
||
'YE': "Yemen",
|
||
'YT': "Mayotte",
|
||
'ZA': "South Africa",
|
||
'ZM': "Zambia",
|
||
'ZW': "Zimbabwe",
|
||
'XX': "OMCK",
|
||
'T1': "Tor"
|
||
}
|
||
|
||
var bnrs = {
|
||
initiated: false,
|
||
init: function() {
|
||
$.getJSON(ku_boardspath+'/bnrs.json', function(data) {
|
||
var reduced = [];
|
||
if(data.length > 1) {
|
||
_.each(data, function(bnr) {
|
||
if(bnr.link !== this_board_dir) reduced.push(bnr);
|
||
});
|
||
}
|
||
else reduced = data;
|
||
bnrs.data = reduced;
|
||
bnrs.initiated = true;
|
||
bnrs.display();
|
||
});
|
||
},
|
||
display: function() {
|
||
if(!this.initiated) return;
|
||
if(!this.data.length) return;
|
||
var reduced = [];
|
||
if(typeof this.current !== 'undefined') {
|
||
_.each(this.data, function(item) {
|
||
if(item.path !== bnrs.current) reduced.push(item)
|
||
});
|
||
}
|
||
else reduced = this.data;
|
||
var toDisplay = randomItem(reduced);
|
||
this.current = toDisplay.path;
|
||
var link = (toDisplay.link.indexOf('http') === (-1)) ? ku_boardspath+'/'+toDisplay.link : toDisplay.link;
|
||
var newhtml = '<a class="bnrsupdate" href="#" onclick="javascript:bnrs.display();return false;"></a><a href="'+link+'"><img src="'+ku_boardspath+'/images/bnrs/'+toDisplay.path+'" /></a>';
|
||
if($('.bnr').length) {
|
||
$('.bnr').html(newhtml);
|
||
}
|
||
else $('.logo').before('<div class="bnr-wrap"><div class="bnr">'+newhtml+'</div></div>');
|
||
},
|
||
}
|
||
|
||
function getRandomInt (min, max) {
|
||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||
}
|
||
|
||
function randomItem(array) {
|
||
return array[getRandomInt(0, array.length-1)];
|
||
}
|
||
|
||
/* not losing floating form data */
|
||
var ffdata = {
|
||
pos: ['top', 'left'],
|
||
save: function() {
|
||
var data = {};
|
||
_.each(ffdata.pos, function(pos) {
|
||
data[pos] = $('#postclone').css(pos);
|
||
});
|
||
var savedOn = new Date().getTime();
|
||
data.savedon = savedOn;
|
||
ffdata.savedOn = savedOn;
|
||
$('#postform [name=ffdata_savedon]').val(savedOn);
|
||
localStorage.setItem('ffdata_'+this_board_dir+'_'+(ispage ? 'page' : $('#postform [name=replythread]').val()), JSON.stringify(data));
|
||
return true;
|
||
},
|
||
savedOn: false,
|
||
unload: function() {
|
||
$('#postform [name=ffdata_savedon]').val(ffdata.savedOn || new Date().getTime());
|
||
},
|
||
load: function() {
|
||
var key = 'ffdata_'+this_board_dir+'_'+(ispage ? 'page' : $('#postform [name=replythread]').val());
|
||
if(!localStorage[key]) return;
|
||
try {
|
||
let data = JSON.parse(localStorage[key]);
|
||
if(data.savedon && data.savedon == $('#postform [name=ffdata_savedon]').val()) {
|
||
_.each(ffdata.pos, function(pos) {
|
||
if(data.hasOwnProperty(pos)) $('#postclone').css(pos, data[pos]);
|
||
});
|
||
$('#postclone').show();
|
||
}
|
||
else localStorage.removeItem(key);
|
||
|
||
}
|
||
catch(e) {
|
||
localStorage.removeItem(key);
|
||
console.log('unable to load form data', e)
|
||
}
|
||
}
|
||
}
|
||
|
||
var embedLinks = {
|
||
sites: [
|
||
{id: 'you', rx: /(?:youtu(?:\.be|be\.com)\/(?:.*v(?:\/|=)|(?:.*\/)?)([\w'-]+))/ },
|
||
{id: 'vim', rx: /[\w\W]*vimeo\.com\/(?:.*?)([0-9]+)(?:.*)?/ },
|
||
{id: 'cob', rx: /[\w\W]*coub\.com\/view\/([\w\W]*)[\w\W]*/ }
|
||
],
|
||
process: function(val) {
|
||
var result = null;
|
||
_.find(this.sites, function(site) {
|
||
var fruit = site.rx.exec(val);
|
||
if(fruit != null) {
|
||
result = {
|
||
site: site.id,
|
||
code: fruit[1]
|
||
}
|
||
}
|
||
})
|
||
return result;
|
||
}
|
||
}
|
||
|
||
window.onbeforeunload = ffdata.unload;
|
||
|
||
var catalog = {
|
||
conf: {
|
||
sortBy: 'bumped',
|
||
layout: 'text',
|
||
respectStickied: true,
|
||
showHidden: true,
|
||
expandOnHover: true
|
||
},
|
||
saveConfig: function() {
|
||
localStorage['catalogSettings'] = JSON.stringify(this.conf);
|
||
},
|
||
init: function() {
|
||
// apply settings
|
||
if(localStorage['catalogSettings']) {
|
||
try {
|
||
var myConf = JSON.parse(localStorage['catalogSettings']);
|
||
_.each(myConf, function(val, key) {
|
||
this.conf[key] = val
|
||
}, this)
|
||
}
|
||
catch(e) {
|
||
console.error('Invalid catalog config');
|
||
localStorage.removeItem('catalogSettings');
|
||
}
|
||
}
|
||
|
||
var sortOptionElements = '';
|
||
_.each([
|
||
['bumped', 'bumpOrder'],
|
||
['replied', 'lastReply'],
|
||
['timestamp', 'creationDate'],
|
||
['reply_count', 'replyCount']
|
||
], (function(val_desc) {
|
||
sortOptionElements += '<option value="'+val_desc[0]+'"'+(val_desc[0]==this.conf.sortBy ? ' selected' : '')+'>'+_l[val_desc[1]]+'</option>';
|
||
}).bind(this));
|
||
|
||
// catalog control buttons
|
||
var sortBtns = '<div class="button-group" data-select="sortBy">';
|
||
_.each([
|
||
['bumped', 'bumpOrder', 'bump', 'i-20'],
|
||
['timestamp', 'creationDate', 'creation', 'i-20'],
|
||
['replied', 'lastReply', 'reply', 'i-16in20'],
|
||
['reply_count', 'replyCount', 'replies', 'i-20']
|
||
], (function(v_d_i) {
|
||
sortBtns += '<div class="bg-button'+(v_d_i[0]==this.conf.sortBy ? ' bgb-selected' : '')+
|
||
'" data-val="'+v_d_i[0]+'" title="'+_l.sortBy+' '+_l[v_d_i[1]]+'">\
|
||
<svg class="icon '+v_d_i[3]+'"><use xlink:href="#i-'+v_d_i[2]+'"></use></svg></div>'
|
||
}).bind(this));
|
||
sortBtns += '</div>';
|
||
var pinBtns = '<div class="button-group'+(this.conf.sortBy !== 'bumped' ? ' disabled' : '')+'" data-select="respectStickied" id="pinControl">';
|
||
_.each([
|
||
[1, 'doStick', 'pin', 'i-16in20'],
|
||
[0, 'doNotStick', 'unpin', 'i-16in20']
|
||
], (function(v_d_i) {
|
||
pinBtns += '<div class="bg-button'+(v_d_i[0]==this.conf.respectStickied ? ' bgb-selected' : '')+
|
||
'" data-val="'+v_d_i[0]+'" title="'+_l[v_d_i[1]]+'">\
|
||
<svg class="icon '+v_d_i[3]+'"><use xlink:href="#i-'+v_d_i[2]+'"></use></svg></div>'
|
||
}).bind(this));
|
||
pinBtns += '</div>';
|
||
var hideBtns = '<div class="button-group" data-select="showHidden">';
|
||
_.each([
|
||
[0, 'hideHidden', 'hide', 'i-16in20'],
|
||
[1, 'showHidden', 'unhide', 'i-16in20']
|
||
], (function(v_d_i) {
|
||
hideBtns += '<div class="bg-button'+(v_d_i[0]==this.conf.showHidden ? ' bgb-selected' : '')+
|
||
'" data-val="'+v_d_i[0]+'" title="'+_l[v_d_i[1]]+'">\
|
||
<svg class="icon '+v_d_i[3]+'"><use xlink:href="#i-'+v_d_i[2]+'"></use></svg></div>'
|
||
}).bind(this));
|
||
hideBtns += '</div>';
|
||
var layoutBtns = '<div class="button-group" data-select="layout">';
|
||
_.each([
|
||
['text', 'smallPics', 'grid-small', 'i-20'],
|
||
['gallery', 'largePics', 'gallery-grid', 'i-20'],
|
||
/*['legacy', 'legacyMode', 'legacy-grid', 'i-20']*/
|
||
], (function(v_d_i) {
|
||
layoutBtns += '<div class="bg-button'+(v_d_i[0]==this.conf.layout ? ' bgb-selected' : '')+
|
||
'" data-val="'+v_d_i[0]+'" title="'+_l[v_d_i[1]]+'">\
|
||
<svg class="icon '+v_d_i[3]+'"><use xlink:href="#i-'+v_d_i[2]+'"></use></svg></div>'
|
||
}).bind(this));
|
||
layoutBtns += '</div>';
|
||
// searck input
|
||
var searchInput = '<input name="subject" autocomplete="false" class="button-group" type="text" id="cat-search" placeholder="'+_l.search+'..." /><input type="text" name="FUCKYOUCHROMEFUCKYOU" style="display:none;"/>'
|
||
|
||
$('#catalog-controls').html(
|
||
sortBtns+pinBtns+searchInput+hideBtns+layoutBtns
|
||
);
|
||
this.load();
|
||
if(this.conf.expandOnHover)
|
||
$('#catalog-contents').addClass('expand-on-hover-enabled');
|
||
// Card events
|
||
$('#catalog-contents')
|
||
.on('click', '.namedate-overlay', function() {
|
||
$(this).toggleClass('date-on name-on');
|
||
})
|
||
.on('click', '.ce-text .bigThumb', function(ev) {
|
||
ev.stopPropagation(); ev.preventDefault();
|
||
var $card = $(this).parents('.cat-entry');
|
||
$card.toggleClass('thumbExpanded');
|
||
})
|
||
.on('click', '.bigThumb audio, .bigThumb video', function(ev) {
|
||
ev.stopPropagation();
|
||
})
|
||
.on('animationstart webkitAnimationStart MSAnimationStart oanimationstart', (function(event) {
|
||
var $target = $(event.target);
|
||
if (event.originalEvent.animationName == "embed-image-insert" && !$target.hasClass('_inserted_'))
|
||
this.getEmbedThumb($target);
|
||
}).bind(this))
|
||
.on('mousedown', '.cat-prv', function(ev) {
|
||
ev.preventDefault();
|
||
PostPreviews._mouseover.bind(this)(ev);
|
||
})
|
||
.on('click', '.cat-prv', function(ev) {
|
||
ev.stopPropagation();
|
||
ev.preventDefault();
|
||
})
|
||
.on('mouseleave', '.cat-prv', function(ev) {
|
||
PostPreviews._mouseout.bind(this)(ev);
|
||
})
|
||
.on('click', '.i-hide', (function(ev) {
|
||
var $target = $(ev.currentTarget)
|
||
, $card = $target.parents('.cat-entry')
|
||
, threadID = $card.data('id')
|
||
, threadIX = _.findIndex(this.model, {'id': threadID})
|
||
, thread = this.model[threadIX];
|
||
thread.hidden = !thread.hidden;
|
||
// addClass won't work here for some reason
|
||
if(thread.hidden) {
|
||
$target[0].classList.add('hidden-on');
|
||
$target.html('<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-unhide"></use>');
|
||
HiddenThreads.hide(threadID);
|
||
$card.addClass('thread-hidden')
|
||
}
|
||
else {
|
||
$target[0].classList.remove('hidden-on');
|
||
$target.html('<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#i-hide"></use>');
|
||
HiddenThreads.unhide(threadID);
|
||
$card.removeClass('thread-hidden')
|
||
}
|
||
//invalidate rendered cache
|
||
this.model[threadIX] = thread;
|
||
delete this.rendered[this.conf.layout][threadID];
|
||
}).bind(this))
|
||
// catalog configuration
|
||
$('.bg-button').click((function(ev) {
|
||
var $target = $(ev.currentTarget);
|
||
if($target.hasClass('bgb-selected')) return;
|
||
var $group = $target.parent()
|
||
, val = $target.data('val')
|
||
, key = $group.data('select');
|
||
$group.find('.bg-button').removeClass('bgb-selected');
|
||
$target.addClass('bgb-selected');
|
||
if(key !== 'sortBy' && key !== 'layout') val = !!val;
|
||
else {
|
||
if(val == 'bumped') $('#pinControl').removeClass('disabled');
|
||
else $('#pinControl').addClass('disabled');
|
||
}
|
||
this.conf[key] = val;
|
||
this.saveConfig();
|
||
if(key !== 'showHidden') this.build();
|
||
else {
|
||
if(val) $('#catalog-contents').removeClass('hideHidden');
|
||
else $('#catalog-contents').addClass('hideHidden');
|
||
}
|
||
}).bind(this))
|
||
$('#refresh_catalog').click((function(ev) {
|
||
ev.preventDefault();
|
||
this.load();
|
||
}).bind(this));
|
||
//search
|
||
$('#cat-search').on('input', function() {
|
||
var query = $(this).val().toLowerCase().replace(/\"/, '\\"');
|
||
try {
|
||
injector.remove('cat-search');
|
||
} catch(e) {}
|
||
if(query.length)
|
||
injector.inject('cat-search', '#catalog-contents .cat-entry:not([data-search *= "'+query+'"]) { display:none; }');
|
||
else injector.remove('cat-search');
|
||
}).trigger('input');
|
||
},
|
||
load: function() {
|
||
// clear data
|
||
this.rendered = {text: {}, gallery: {}};
|
||
this.model = null;
|
||
// get contents
|
||
$.getJSON('catalog.json?v='+(new Date().getTime()))
|
||
.done(this.build.bind(this))
|
||
.fail(function(err) {
|
||
throw err;
|
||
})
|
||
},
|
||
fileTypes: {
|
||
image: ['jpg', 'gif', 'png'],
|
||
jpgThumb: ['webm', 'cob', 'vim', 'you'],
|
||
iconsAvailable: ['swf', 'mp3', 'ogg', 'css', 'flv'],
|
||
audio: ['mp3', 'ogg'],
|
||
embed: ['cob', 'vim', 'you']
|
||
},
|
||
authorities: ['', 'Admin', 'Mod', '?', 'God'],
|
||
formatDate: function(timestamp, short) {
|
||
if(typeof short === 'undefined') short = false;
|
||
var date = new Date(timestamp * 1000)
|
||
, Dow = this.dateLocal.dows.hasOwnProperty(locale) ? this.dateLocal.dows[locale][date.getDay()] : this.dateLocal.dows.en[date.getDay()]
|
||
, yy = _.padLeft(date.getFullYear() % 100, 2, 0)
|
||
, mo = _.padLeft(date.getMonth()+1, 2, 0)
|
||
, Mon = (locale === 'ru') ? this.dateLocal.mons.ru[date.getMonth()] : date.getMonth()+1
|
||
, dd = _.padLeft(date.getDate(), 2, 0)
|
||
, hh = _.padLeft(date.getHours(), 2, 0)
|
||
, mm = _.padLeft(date.getMinutes(), 2, 0)
|
||
, ss = _.padLeft(date.getSeconds(), 2, 0);
|
||
return (short
|
||
? ( (locale === 'ru')
|
||
? (dd+'.'+mo+'.'+yy+' в ')
|
||
: (mo+'/'+dd+'/'+yy+' @ ') )
|
||
: ( (locale === 'ru')
|
||
? (Dow+' '+dd+' '+Mon+'’'+yy+' в ')
|
||
: (mo+'/'+dd+'/'+yy+' ('+Dow+') @ ') )
|
||
) + hh+':'+mm+':'+ss;
|
||
},
|
||
dateLocal: {
|
||
dows: {
|
||
ru: ['Пнд','Втр','Срд','Чтв','Птн','Сбт','Вск'],
|
||
en: ['Sun','Mon','Tue','Wen','Thu','Fri','Sat']
|
||
},
|
||
mons: {
|
||
ru: ['Янв','Фев','Мар','Апр','Май','Июн','Июл','Авг','Сен','Окт','Ноя','Дек']
|
||
}
|
||
},
|
||
build: function(data) {
|
||
if(typeof data === 'undefined') data = this.model;
|
||
if(!data) return;
|
||
// normalize
|
||
_.each(data, function(entry, i) {
|
||
_.each(['id', 'reply_count', 'bumped', 'replied', 'reply_count', 'timestamp', 'page', 'locked', 'stickied', 'deleted_timestamp'], function(prop) {
|
||
entry[prop] = ~~entry[prop];
|
||
})
|
||
data[i] = entry;
|
||
})
|
||
// Sort threads
|
||
if(this.conf.sortBy === 'bumped' && this.conf.respectStickied)
|
||
this.model = _.sortByOrder(data, ['stickied', 'bumped'], ['desc', 'desc']);
|
||
else {
|
||
var sby = [this.conf.sortBy];
|
||
if(this.conf.sortBy !== 'bumped')
|
||
sby.push('bumped')
|
||
this.model = _.sortByOrder(data, sby, _.repeat('desc', sby.length));
|
||
}
|
||
|
||
var html = '';
|
||
|
||
_.each(this.model, function(thread) {
|
||
html += this.buildEntry(thread);
|
||
}, this);
|
||
|
||
$('#catalog-contents').html(html);
|
||
},
|
||
getEmbedThumb: function($el) {
|
||
var site = $el.data('site'), id = $el.data('id'), img
|
||
, $thread = $el.parents('.cat-entry')
|
||
, threadID = $thread.data('id');
|
||
if(site == 'cob')
|
||
$.get(ku_boardspath+'/corpsy.php?code='+id, (function(res) {
|
||
$el.replaceWith('<img src="'+res.thumbnail_url+'">');
|
||
this.rendered[this.conf.layout][threadID] = $thread[0].outerHTML;
|
||
}).bind(this));
|
||
if(site == 'vim')
|
||
$.get('http://vimeo.com/api/v2/video/'+id+'.json', (function(res) {
|
||
$el.replaceWith('<img src="'+res[0].thumbnail_medium+'">');
|
||
this.rendered[this.conf.layout][threadID] = $thread[0].outerHTML
|
||
}).bind(this));
|
||
},
|
||
|
||
buildEntry: function(thread) {
|
||
if(this.rendered[this.conf.layout].hasOwnProperty(thread.id))
|
||
return this.rendered[this.conf.layout][thread.id];
|
||
|
||
if(!thread.processed) {
|
||
thread.url = '/'+this_board_dir+'/res/'+thread.id+'.html';
|
||
// --- Building blocks ---
|
||
// Thumbnails
|
||
var expanderBtn = '<svg class="actor icon cat-thumb-expand"><use xlink:href="#i-expand"></use></svg>',
|
||
playerBtn = '<svg class="actor icon cat-thumb-expand"><use xlink:href="#i-play"></use></svg>';
|
||
// Find first non-deleted file
|
||
let embed = thread.embeds ? (thread.embeds.find(e => e.file != 'removed') || 'removed') : null
|
||
// for images
|
||
if(!embed || embed === 'removed') {
|
||
thread.smallThumb =
|
||
'<a href="'+thread.url+'" class="smallThumb">\
|
||
<div class="nofile-removed ctx">'+(embed === 'removed' ? 'Удалён' : 'No File')+'</div>'
|
||
+'</a>';
|
||
}
|
||
else {
|
||
if (
|
||
_.includes(this.fileTypes.image, embed.file_type)
|
||
||
|
||
_.includes(this.fileTypes.jpgThumb, embed.file_type)
|
||
||
|
||
(
|
||
_.includes(this.fileTypes.audio, embed.file_type)
|
||
&&
|
||
(+embed.thumb_w) > 0
|
||
&&
|
||
(+embed.thumb_h) > 0
|
||
)
|
||
) {
|
||
let ftype = _.includes(this.fileTypes.image, embed.file_type)
|
||
? embed.file_type
|
||
: 'jpg'
|
||
, thumbURL = _.includes(this.fileTypes.embed, embed.file_type)
|
||
? `${embed.file_type}-${embed.file}-`
|
||
: embed.file
|
||
, vartype = embed.file_type == 'mp3' ? ' onerror="switchFileType(this)" extset="jpg,png,gif"' : ''
|
||
thread.smallThumb =
|
||
'<a href="'+thread.url+'" class="smallThumb">\
|
||
<img src="thumb/'+thumbURL+'c.'+ftype+'"'+vartype+'>'
|
||
+'</a>';
|
||
thread.bigThumb =
|
||
'<img src="thumb/'+thumbURL+'s.'+ftype+'"'+vartype+'>';
|
||
}
|
||
/*if(_.includes(this.fileTypes.image, thread.file_type)) {
|
||
thread.fileTypeClass = 'image';
|
||
thread.smallThumb =
|
||
'<a href="'+thread.url+'" class="smallThumb">\
|
||
<img src="thumb/'+thread.file+'c.'+(thread.file_type === 'webm' ? 'jpg' : thread.file_type)+'">'
|
||
+'</a>';
|
||
thread.bigThumb =
|
||
'<img src="thumb/'+thread.file+'s.'+(thread.file_type === 'webm' ? 'jpg' : thread.file_type)+'">';
|
||
}*/
|
||
// small thumbnail for embeds and generic files
|
||
else {
|
||
var smallSrc = (_.includes(this.fileTypes.iconsAvailable, embed.file_type))
|
||
? '/inc/filetypes/'+embed.file_type+'.png'
|
||
: '/inc/filetypes/generic'+(_.includes(this.fileTypes.embed, embed.file_type) ? '-embed' : '')+'.png';
|
||
var expandable = _.includes(this.fileTypes.embed, embed.file_type) || _.includes(this.fileTypes.audio, embed.file_type);
|
||
thread.smallThumb =
|
||
'<a href="'+thread.url+'" class="smallThumb">\
|
||
<img src="'+smallSrc+'">' +
|
||
/*+ ''+(expandable ? playerBtn : '') +*/
|
||
'</a>';
|
||
// for audios
|
||
if(_.includes(this.fileTypes.audio, embed.file_type)) {
|
||
thread.bigThumb =
|
||
'<audio src="src/'+embed.file+'.'+embed.file_type+'" controls></audio>';
|
||
}
|
||
}
|
||
/*// for embeds
|
||
if(_.includes(this.fileTypes.embed, thread.file_type)) {
|
||
thread.bigThumb = (thread.file_type == 'you')
|
||
? '<img src="http://i.ytimg.com/vi/'+thread.file+'/mqdefault.jpg">'
|
||
: '<div class="cat-bt-embed" data-site="'+thread.file_type+'" data-id="'+thread.file+'"></div>';
|
||
}
|
||
// for audios
|
||
if(_.includes(this.fileTypes.audio, thread.file_type)) {
|
||
thread.bigThumb =
|
||
'<audio src="src/'+thread.file+'.'+thread.file_type+'" controls></audio>';
|
||
}*/
|
||
thread.bigThumb = '<a target="_blank" href="'+thread.url+'" class="bigThumb">'+thread.bigThumb+'</a>';
|
||
}
|
||
/*if(!embed || embed === 'removed')
|
||
thread.bigThumb = '<a target="_blank" href="'+thread.url+'" class="bigThumb">'+thread.bigThumb+'</a>';*/
|
||
|
||
//OP
|
||
thread.op = '<a target="_blank" title="'+_l.goToThread+'" target="_blank" href="'+thread.url+'" class="op-number ctx">#'+thread.id+'</a>';
|
||
|
||
//preview
|
||
thread.preview =
|
||
'<a href="'+thread.url+'#'+thread.id+'" class="actor cat-prv">\
|
||
<svg class="icon"><use xlink:href="#i-eye"></use></svg>\
|
||
</a>';
|
||
|
||
//counters
|
||
var repliesLabel =
|
||
'<svg class="icon"><use xlink:href="#i-reply"></use></svg>\
|
||
<span class="ctx reply-count">'+thread.reply_count+'</span>';
|
||
if(thread.last_reply)
|
||
repliesLabel = '<a href="'+thread.url+'#'+thread.last_reply+'" class="actor cat-prv">'+repliesLabel+'</a>';
|
||
var replies =
|
||
'<div class="infolabel">'+repliesLabel+'</div>',
|
||
images =
|
||
'<div class="infolabel">\
|
||
<svg class="icon"><use xlink:href="#i-picture"></use></svg>\
|
||
<span class="ctx image-count">'+thread.images+'</span>\
|
||
</div>',
|
||
page =
|
||
'<div class="infolabel il-page">\
|
||
<a title="'+_l.threadOnPage+' '+thread.page+'" target="_blank" href="/'+this_board_dir+'/' + ((thread.page > 0) ? thread.page+'.html' : '')+'#'+thread.id+'" class="actor">\
|
||
<svg class="icon"><use xlink:href="#i-page"></use></svg>\
|
||
<span class="ctx page-number">'+thread.page+'</span>\
|
||
</a>\
|
||
</div>';
|
||
thread.countersCombined = replies+images+page;
|
||
|
||
//Poster name+date
|
||
thread.posterauthority = +thread.posterauthority;
|
||
thread.nameDatePriority = 'date';
|
||
if(localStorage['cat_nameDatePriority'] == 'name' ||
|
||
(localStorage['cat_nameDatePriority'] != 'date' &&
|
||
(thread.name || thread.tripcode || thread.posterauthority)
|
||
)
|
||
) thread.nameDatePriority = 'name';
|
||
|
||
// Poster name
|
||
var poster =
|
||
(thread.name ? '<span class="ctx postername">'+thread.name+'</span>' : '') +
|
||
(thread.tripcode ? '<span class="ctx postertrip">!'+thread.tripcode+'</span>' : '') +
|
||
(thread.posterauthority ? '<span class="ctx admin"> ##'+this.authorities[thread.posterauthority]+'##</span>' : '');
|
||
thread.poster = '<div class="cat-poster"><span class="ctx">by </span>'+ (poster || '<span class="ctx c-postername">'+(this_board_defaultName || _l.anonymous)+'</span>')+'</div>';
|
||
|
||
// Date
|
||
var dn = ' style="display:none"';
|
||
thread.date = '<div class="ctx cat-date cat-date-long">'+this.formatDate(thread.timestamp)+'</div>';
|
||
thread.dateCompact = '<div class="ctx cat-date cat-date-short">'+this.formatDate(thread.timestamp, 1)+'</div>';
|
||
|
||
//search data
|
||
thread.searchData = _.escape(stripHTML(thread.subject + ' ' + thread.message).toLowerCase());
|
||
|
||
thread.message = thread.message.replace(/\\"/mg, '"');
|
||
|
||
thread.processed = true;
|
||
this.model[_.findIndex(this.model, {id: thread.id})] = thread;
|
||
}
|
||
//indicators
|
||
thread = this.buildIndicators(thread);
|
||
|
||
var html = this.layouts[this.conf.layout].bind(this)(thread);
|
||
this.rendered[this.conf.layout][thread.id] = html;
|
||
return html
|
||
},
|
||
buildIndicators: function(thread) {
|
||
// if(!thread.hasOwnProperty('hidden'))
|
||
thread.hidden = _.includes((localStorage['hiddenThreads.'+this_board_dir] || '').split(','), ''+thread.id);
|
||
var pin = thread.stickied ? '<svg class="foradmin-act icon i-layer-1 i-pin"><use xlink:href="#i-pin"></use></svg>' : '',
|
||
lock = thread.locked ? '<svg class="foradmin-act icon i-layer-1 i-lock"><use xlink:href="#i-lock"></use></svg>' : '',
|
||
deathmark = thread.deleted_timestamp ? '<svg class="foradmin-act icon i-layer-1 i-deathmark"><use xlink:href="#i-skull"></use></svg>' : '',
|
||
hide = '<svg class="actor icon i-layer-1 i-hide'+(thread.hidden ? ' hidden-on' : '')+'"><use xlink:href="#i-'+(thread.hidden ? 'unhide' : 'hide')+'"></use></svg>',
|
||
burger = '<svg class="actor icon i-burger foradmin-show"><use xlink:href="#i-burger"></use></svg>',
|
||
del = '<svg class="actor icon i-layer-2 i-delete foradmin-show"><use xlink:href="#i-x"></use></svg>',
|
||
and = '<svg class="actor icon i-layer-2 i-dnb foradmin-show"><use xlink:href="#i-and"></use></svg>',
|
||
ban = '<svg class="actor icon i-layer-2 i-ban foradmin-show"><use xlink:href="#i-ban"></use></svg>';
|
||
thread.indicatorsCombined = '<div class="indicators">'+burger+'<span class="i-layer-1">'+deathmark+pin+lock+hide+'</span><span class="i-layer-2">'+del+and+ban+'</span></div>';
|
||
return thread;
|
||
},
|
||
layouts: {
|
||
text: function(thread) {
|
||
return ''+
|
||
'<div data-id="'+thread.id+'" class="cat-entry ce-text'+(thread.hidden ? ' thread-hidden' : '')+'" data-search="'+thread.searchData+'">\
|
||
<div class="cat-card">\
|
||
<div class="ce-heda">'
|
||
+thread.smallThumb+
|
||
'<div class="cat-infoline ci-op-link">'
|
||
+thread.op
|
||
+thread.indicatorsCombined+
|
||
'</div>\
|
||
<div class="cat-infoline namedate-overlay '+thread.nameDatePriority+'-on">'
|
||
+thread.poster
|
||
+thread.date
|
||
+'</div>\
|
||
<div class="cat-infoline">'
|
||
+thread.preview
|
||
+thread.countersCombined+
|
||
'</div>\
|
||
</div>\
|
||
<div class="ce-opcontent ctx">\
|
||
<h5>'+thread.subject+'</h5>'+
|
||
thread.message+
|
||
'</div>\
|
||
</div>'
|
||
+thread.bigThumb+
|
||
'</div>'
|
||
},
|
||
gallery: function(thread) {
|
||
return ''+
|
||
'<div data-id="'+thread.id+'" class="cat-entry ce-gallery'+(thread.hidden ? ' thread-hidden' : '')+'" data-search="'+thread.searchData+'">\
|
||
<div class="cat-card">'+
|
||
thread.bigThumb+
|
||
'<div class="cat-infoline">\
|
||
<div class="ci-op-link">'+thread.op+'</div>\
|
||
<div class="counters">'+thread.countersCombined+'</div>\
|
||
</div>\
|
||
<div class="cat-infoline">'
|
||
+thread.preview+
|
||
'<div class="namedate-overlay '+thread.nameDatePriority+'-on">'
|
||
+thread.poster
|
||
+thread.dateCompact
|
||
+'</div>'
|
||
+thread.indicatorsCombined+
|
||
'</div>\
|
||
<div class="ce-opcontent ctx">\
|
||
<h5>'+thread.subject+'</h5>'+
|
||
thread.message+
|
||
'</div>\
|
||
</div>\
|
||
</div>'
|
||
}
|
||
}
|
||
}
|
||
|
||
function stripHTML(html) {
|
||
var tmp = document.implementation.createHTMLDocument("New").body;
|
||
tmp.innerHTML = html;
|
||
return tmp.textContent || tmp.innerText || "";
|
||
}
|
||
|
||
var unreadCounter = {
|
||
init: function(built) {
|
||
if (!built) {
|
||
built = + document.querySelector('meta[property="i0:buildtime"]').content
|
||
}
|
||
this.lastvisits = localStorage['lastvisits'] ? (JSON.parse(localStorage['lastvisits']) || { }) : { }
|
||
let last_ts = this.lastvisits.hasOwnProperty(boardid) ? parseInt(this.lastvisits[boardid]) : 0;
|
||
if(last_ts < built) {
|
||
this.lastvisits[boardid] = built
|
||
localStorage.setItem('lastvisits', JSON.stringify(this.lastvisits))
|
||
}
|
||
},
|
||
update: function() {
|
||
if (!this.lastvisits) {
|
||
this.init()
|
||
}
|
||
$.ajax({
|
||
url: '/newpostscount.php',
|
||
data: this.lastvisits,
|
||
dataType: 'json',
|
||
success: function(data) {
|
||
$('.newposts-counter').remove()
|
||
$('.got-updates').removeClass('got-updates')
|
||
_.each(data, function(val, brd) {
|
||
if ((+val) > 0) {
|
||
let valstr = `<span class="newposts-counter"> (${val})</span>`
|
||
, $brd = $(`.menu-item[href="/${brd}/"]`)
|
||
if ($brd.length) {
|
||
$brd.append(valstr)
|
||
$(`.sect-exr[data-toexpand="${$brd.parents('.menu-sect').attr('id').split('ms-')[1]}"]`).parent().addClass('got-updates')
|
||
}
|
||
$(`.mobile-nav option[value="${brd}"]`).append(valstr)
|
||
}
|
||
})
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
var HTMLoader = {
|
||
loadThread: function(boardID, threadID, done, postID) {
|
||
$.get(threadID === '?'
|
||
? `${ku_boardspath}/postbynumber.php?b=${boardID}&p=${postID}`
|
||
: `${ku_boardspath}/${boardID}/res/${threadID}.html?${force_html_nocache ? Math.random() : ''}`)
|
||
.then(data => {
|
||
let posts = data.match(/<div\s*?class\s*?=\s*?"[^"]*?i0svcel[^"]*?"\s*?>!i0-pd:[0-9]+\s*?<\/div\s*?>[\s\S]+?<div\s*?class\s*?=\s*?"[^"]*?i0svcel[^"]*?"\s*?>!i0-pd-end\s*?<\/div\s*?>/gi)
|
||
.map(match => {
|
||
let res = match.match(/<div\s*?class\s*?=\s*?"[^"]*?i0svcel[^"]*?"\s*?>!i0-pd:([0-9]+)\s*?<\/div\s*?>([\s\S]+?)<div\s*?class\s*?=\s*?"[^"]*?i0svcel[^"]*?"\s*?>!i0-pd-end\s*?<\/div\s*?>/i);
|
||
return {
|
||
id: +res[1],
|
||
body: res[2]
|
||
}
|
||
})
|
||
if (threadID === '?') {
|
||
let thrno = data.match(/<!--i0:thrno=([0-9]+)-->/) //wtf
|
||
if (thrno)
|
||
threadID = thrno[1]
|
||
}
|
||
if (posts.length) {
|
||
let postMap = posts.map(post => {
|
||
this.cached[`${boardID}_${post.id}`] = post.body
|
||
return post.id
|
||
})
|
||
if (threadID !== '?') {
|
||
this.threadMaps[`${boardID}_${threadID}`] = postMap
|
||
}
|
||
}
|
||
done()
|
||
})
|
||
.fail(err => {
|
||
done(err.status || 'null')
|
||
})
|
||
},
|
||
getPost: function(boardID, threadID, postID, callback, secondTry) {
|
||
let cachedPost = this.cached[`${boardID}_${postID}`]
|
||
if (cachedPost) {
|
||
callback(false, cachedPost)
|
||
return
|
||
}
|
||
else {
|
||
if (!secondTry) {
|
||
let found = false
|
||
if (boardID === this_board_dir) {
|
||
let $post = $(`a[name=${postID}]`)
|
||
if ($post.length) {
|
||
let post = $post.parents('.postnode')[0].outerHTML
|
||
this.cached[`${boardID}_${postID}`] = post
|
||
found = true
|
||
callback(false, post)
|
||
}
|
||
}
|
||
if (!found) {
|
||
this.loadThread(boardID, threadID, err => {
|
||
if (err) {
|
||
callback(err)
|
||
}
|
||
else {
|
||
this.getPost(boardID, threadID, postID, callback, true)
|
||
}
|
||
}, postID)
|
||
}
|
||
}
|
||
else {
|
||
callback(null)
|
||
}
|
||
}
|
||
},
|
||
getThread: function(boardID, threadID, range, callback, secondTry, force) {
|
||
let threadMap = force ? false : this.threadMaps[`${boardID}_${threadID}`]
|
||
if (threadMap) {
|
||
if (range) {
|
||
threadMap = threadMap.filter(n => n > range[0] && n < range[1])
|
||
}
|
||
callback(false, threadMap.reduce((htm, postID) => htm + this.cached[`${boardID}_${postID}`], ''))
|
||
}
|
||
else {
|
||
if (!secondTry) {
|
||
this.loadThread(boardID, threadID, err => {
|
||
if (err) {
|
||
callback(err)
|
||
}
|
||
else {
|
||
this.getThread(boardID, threadID, range, callback, true)
|
||
}
|
||
})
|
||
}
|
||
else {
|
||
callback(null)
|
||
}
|
||
}
|
||
},
|
||
cached: {},
|
||
threadMaps: {}
|
||
}
|
||
|
||
function switchFileType(el) {
|
||
let exp = /\.([a-z0-9]+)(?=$|\?)/i
|
||
, match = el.src.match(exp)
|
||
if (!match) return;
|
||
let exts = el.getAttribute('extset').toLowerCase().split(',')
|
||
if (!exts.length) return;
|
||
let i = exts.indexOf(match[1].toLowerCase())
|
||
if (i == -1 || i >= (exts.length-1)) return;
|
||
el.src = el.src.replace(exp, `.${exts[i+1]}`)
|
||
} |