summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/ajax.js16
-rw-r--r--js/catalog-search.js82
-rw-r--r--js/expand-video.js4
-rw-r--r--js/favorites.js1
-rw-r--r--js/file-selector.js191
-rw-r--r--js/forced-anon.js2
-rw-r--r--js/gallery-view.js165
-rw-r--r--js/hide-images.js4
-rw-r--r--js/image-hover.js182
-rw-r--r--js/live-index.js2
-rw-r--r--js/no-animated-gif.js2
-rw-r--r--js/own-board.js116
-rw-r--r--js/quick-reply.js11
-rw-r--r--js/thread-stats.js116
-rw-r--r--js/toggle-images.js2
-rw-r--r--js/treeview.js48
-rw-r--r--js/upload-selection.js2
m---------js/wPaint0
-rw-r--r--js/watch.js9
-rw-r--r--js/wpaint.js9
20 files changed, 920 insertions, 44 deletions
diff --git a/js/ajax.js b/js/ajax.js
index 61d83df2..56f0df5c 100644
--- a/js/ajax.js
+++ b/js/ajax.js
@@ -115,17 +115,10 @@ $(window).ready(function() {
}
},
error: function(xhr, status, er) {
- // An error occured
- do_not_ajax = true;
- $(form).find('input[type="submit"]').each(function() {
- var $replacement = $('<input type="hidden">');
- $replacement.attr('name', $(this).attr('name'));
- $replacement.val(submit_txt);
- $(this)
- .after($replacement)
- .replaceWith($('<input type="button">').val(submit_txt));
- });
- $(form).submit();
+ console.log(xhr);
+ alert(_('The server took too long to submit your post. Your post was probably still submitted. If it wasn\'t, we might be experiencing issues right now -- please try your post again later. Error information: ') + "<div><textarea>" + JSON.stringify(xhr) + "</textarea></div>");
+ $(form).find('input[type="submit"]').val(submit_txt);
+ $(form).find('input[type="submit"]').removeAttr('disabled');
},
data: formData,
cache: false,
@@ -141,6 +134,7 @@ $(window).ready(function() {
};
setup_form($('form[name="post"]'));
$(window).on('quick-reply', function() {
+ $('form#quick-reply').off('submit');
setup_form($('form#quick-reply'));
});
});
diff --git a/js/catalog-search.js b/js/catalog-search.js
new file mode 100644
index 00000000..17a8edac
--- /dev/null
+++ b/js/catalog-search.js
@@ -0,0 +1,82 @@
+/*
+ * catalog-search.js
+ * - Search and filters threads when on catalog view
+ * - Optional shortcuts 's' and 'esc' to open and close the search.
+ *
+ * Usage:
+ * $config['additional_javascript'][] = 'js/jquery.min.js';
+ * $config['additional_javascript'][] = 'js/comment-toolbar.js';
+ */
+if (active_page == 'catalog') {
+ onready(function () {
+ 'use strict';
+
+ // 'true' = enable shortcuts
+ var useKeybinds = true;
+
+ // trigger the search 400ms after last keystroke
+ var delay = 400;
+ var timeoutHandle;
+
+ //search and hide none matching threads
+ function filter(search_term) {
+ $('.replies').each(function () {
+ var subject = $(this).children('.intro').text().toLowerCase();
+ var comment = $(this).clone().children().remove(':lt(2)').end().text().trim().toLowerCase();
+ search_term = search_term.toLowerCase();
+
+ if (subject.indexOf(search_term) == -1 && comment.indexOf(search_term) == -1) {
+ $(this).parents('div[id="Grid"]>.mix').css('display', 'none');
+ } else {
+ $(this).parents('div[id="Grid"]>.mix').css('display', 'inline-block');
+ }
+ });
+ }
+
+ function searchToggle() {
+ var button = $('#catalog_search_button')[0];
+
+ if (!button.dataset.expanded) {
+ button.dataset.expanded = '1';
+ button.innerText = 'Close';
+ $('.catalog_search').append(' <input id="search_field" style="border: inset 1px;">');
+ $('#search_field').focus();
+ } else {
+ delete button.dataset.expanded;
+ button.innerText = 'Search';
+ $('.catalog_search').children().last().remove();
+ $('div[id="Grid"]>.mix').each(function () { $(this).css('display', 'inline-block'); });
+ }
+ }
+
+ $('.threads').before('<span class="catalog_search">[<a id="catalog_search_button" style="text-decoration:none; cursor:pointer;"></a>]</span>');
+ $('#catalog_search_button').text('Search');
+
+ $('#catalog_search_button').on('click', searchToggle);
+ $('.catalog_search').on('keyup', 'input#search_field', function (e) {
+ window.clearTimeout(timeoutHandle);
+ timeoutHandle = window.setTimeout(filter, 400, e.target.value);
+ });
+
+ if (useKeybinds) {
+ // 's'
+ $('body').on('keydown', function (e) {
+ if (e.which === 83 && e.target.tagName === 'BODY' && !(e.ctrlKey || e.altKey || e.shiftKey)) {
+ e.preventDefault();
+ if ($('#search_field').length !== 0) {
+ $('#search_field').focus();
+ } else {
+ searchToggle();
+ }
+ }
+ });
+ // 'esc'
+ $('.catalog_search').on('keydown', 'input#search_field', function (e) {
+ if (e.which === 27 && !(e.ctrlKey || e.altKey || e.shiftKey)) {
+ window.clearTimeout(timeoutHandle);
+ searchToggle();
+ }
+ });
+ }
+ });
+}
diff --git a/js/expand-video.js b/js/expand-video.js
index 79872510..08b474c1 100644
--- a/js/expand-video.js
+++ b/js/expand-video.js
@@ -204,13 +204,13 @@ function setupVideo(thumb, url) {
function setupVideosIn(element) {
var thumbs = element.querySelectorAll("a.file");
for (var i = 0; i < thumbs.length; i++) {
- if (/\.webm$/.test(thumbs[i].pathname)) {
+ if (/\.webm$|\.mp4$/.test(thumbs[i].pathname)) {
setupVideo(thumbs[i], thumbs[i].href);
} else {
var m = thumbs[i].search.match(/\bv=([^&]*)/);
if (m != null) {
var url = decodeURIComponent(m[1]);
- if (/\.webm$/.test(url)) setupVideo(thumbs[i], url);
+ if (/\.webm$|\.mp4$/.test(url)) setupVideo(thumbs[i], url);
}
}
}
diff --git a/js/favorites.js b/js/favorites.js
index e325e110..daf7b732 100644
--- a/js/favorites.js
+++ b/js/favorites.js
@@ -54,7 +54,6 @@ if (active_page == 'thread' || active_page == 'index') {
$(document).ready(function(){
var favorites = JSON.parse(localStorage.favorites);
var is_board_favorite = ~$.inArray(board_name, favorites);
- console.log(is_board_favorite);
$('header>h1').append('<a id="favorite-star" href="#" data-active="'+(is_board_favorite ? 'true' : 'false')+'" style="color: '+(is_board_favorite ? 'yellow' : 'grey')+'; text-decoration:none">\u2605</span>');
add_favorites();
diff --git a/js/file-selector.js b/js/file-selector.js
new file mode 100644
index 00000000..207a5ae9
--- /dev/null
+++ b/js/file-selector.js
@@ -0,0 +1,191 @@
+/*
+ * file-selector.js - Add support for drag and drop file selection, and paste from clipbboard on supported browsers.
+ *
+ * Usage:
+ * $config['additional_javascript'][] = 'js/jquery.min.js';
+ * $config['additional_javascript'][] = 'js/file-selector.js';
+ */
+function init_file_selector(max_images) {
+
+$(document).ready(function () {
+ // add options panel item
+ if (window.Options && Options.get_tab('general')) {
+ Options.extend_tab('general', '<label id="file-drag-drop"><input type="checkbox">' + _('Drag and drop file selection') + '</label>');
+
+ $('#file-drag-drop>input').on('click', function() {
+ if ($('#file-drag-drop>input').is(':checked')) {
+ localStorage.file_dragdrop = 'true';
+ } else {
+ localStorage.file_dragdrop = 'false';
+ }
+ });
+
+ if (typeof localStorage.file_dragdrop === 'undefined') localStorage.file_dragdrop = 'true';
+ if (localStorage.file_dragdrop === 'true') $('#file-drag-drop>input').prop('checked', true);
+ }
+});
+
+// disabled by user, or incompatible browser.
+if (localStorage.file_dragdrop == 'false' || !(window.URL.createObjectURL && window.File))
+ return;
+
+// multipost not enabled
+if (typeof max_images == 'undefined') {
+ var max_images = 1;
+}
+
+$('<div class="dropzone-wrap" style="display: none;">'+
+ '<div class="dropzone" tabindex="0">'+
+ '<div class="file-hint">'+_('Select/drop/paste files here')+'</div>'+
+ '<div class="file-thumbs"></div>'+
+ '</div>'+
+ '</div>'+
+'</div>').prependTo('#upload td');
+
+var files = [];
+$('#upload_file').remove(); // remove the original file selector
+$('.dropzone-wrap').css('user-select', 'none').show(); // let jquery add browser specific prefix
+
+function addFile(file) {
+ if (files.length == max_images)
+ return;
+
+ files.push(file);
+ addThumb(file);
+}
+
+function removeFile(file) {
+ files.splice(files.indexOf(file), 1);
+}
+
+function getThumbElement(file) {
+ return $('.tmb-container').filter(function(){return($(this).data('file-ref')==file);});
+}
+
+function addThumb(file) {
+
+ var fileName = (file.name.length < 24) ? file.name : file.name.substr(0, 22) + '…';
+ var fileType = file.type.split('/')[0];
+ var fileExt = file.type.split('/')[1];
+ var $container = $('<div>')
+ .addClass('tmb-container')
+ .data('file-ref', file)
+ .append(
+ $('<div>').addClass('remove-btn').html('✖'),
+ $('<div>').addClass('file-tmb'),
+ $('<div>').addClass('tmb-filename').html(fileName)
+ )
+ .appendTo('.file-thumbs');
+
+ var $fileThumb = $container.find('.file-tmb');
+ if (fileType == 'image') {
+ // if image file, generate thumbnail
+ var objURL = window.URL.createObjectURL(file);
+ $fileThumb.css('background-image', 'url('+ objURL +')');
+ } else {
+ $fileThumb.html('<span>' + fileExt.toUpperCase() + '</span>');
+ }
+}
+
+$(document).on('ajax_before_post', function (e, formData) {
+ for (var i=0; i<max_images; i++) {
+ var key = 'file';
+ if (i > 0) key += i + 1;
+ if (typeof files[i] === 'undefined') break;
+ formData.append(key, files[i]);
+ }
+});
+
+// clear file queue and UI on success
+$(document).on('ajax_after_post', function () {
+ files = [];
+ $('.file-thumbs').empty();
+});
+
+var dragCounter = 0;
+var dropHandlers = {
+ dragenter: function (e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ if (dragCounter === 0) $('.dropzone').addClass('dragover');
+ dragCounter++;
+ },
+ dragover: function (e) {
+ // needed for webkit to work
+ e.stopPropagation();
+ e.preventDefault();
+ },
+ dragleave: function (e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ dragCounter--;
+ if (dragCounter === 0) $('.dropzone').removeClass('dragover');
+ },
+ drop: function (e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ $('.dropzone').removeClass('dragover');
+ dragCounter = 0;
+
+ var fileList = e.originalEvent.dataTransfer.files;
+ for (var i=0; i<fileList.length; i++) {
+ addFile(fileList[i]);
+ }
+ }
+};
+
+
+// attach handlers
+$(document).on(dropHandlers);
+
+$(document).on('click', '.dropzone .remove-btn', function (e) {
+ e.stopPropagation();
+
+ var file = $(e.target).parent().data('file-ref');
+
+ getThumbElement(file).remove();
+ removeFile(file);
+});
+
+$(document).on('keypress click', '.dropzone', function (e) {
+ e.stopPropagation();
+
+ // accept mouse click or Enter
+ if ((e.which != 1 || e.target.className != 'file-hint') &&
+ e.which != 13)
+ return;
+
+ var $fileSelector = $('<input type="file" multiple>');
+
+ $fileSelector.on('change', function (e) {
+ if (this.files.length > 0) {
+ for (var i=0; i<this.files.length; i++) {
+ addFile(this.files[i]);
+ }
+ }
+ $(this).remove();
+ });
+
+ $fileSelector.click();
+});
+
+$(document).on('paste', function (e) {
+ var clipboard = e.originalEvent.clipboardData;
+ if (typeof clipboard.items != 'undefined' && clipboard.items.length != 0) {
+
+ //Webkit
+ for (var i=0; i<clipboard.items.length; i++) {
+ if (clipboard.items[i].kind != 'file')
+ continue;
+
+ //convert blob to file
+ var file = new File([clipboard.items[i].getAsFile()], 'ClipboardImage.png', {type: 'image/png'});
+ addFile(file);
+ }
+ }
+});
+
+}
diff --git a/js/forced-anon.js b/js/forced-anon.js
index 5ea68199..11327ec9 100644
--- a/js/forced-anon.js
+++ b/js/forced-anon.js
@@ -64,7 +64,7 @@ $(document).ready(function() {
if (window.Options && Options.get_tab('general')) {
selector = '#forced-anon';
event = 'change';
- Options.extend_tab("general", "<label id='forced-anon'><input type='checkbox' /> "+_('Forced anonymity')+"</label>");
+ Options.extend_tab("general", "<label id='forced-anon'><input type='checkbox' />"+_('Forced anonymity')+"</label>");
}
else {
selector = '#forced-anon';
diff --git a/js/gallery-view.js b/js/gallery-view.js
new file mode 100644
index 00000000..2d7d85b4
--- /dev/null
+++ b/js/gallery-view.js
@@ -0,0 +1,165 @@
+if (active_page == 'index' || active_page == 'thread')
+$(function(){
+
+ var gallery_view = false;
+
+ $('hr:first').before('<div id="gallery-view" style="text-align:right"><a class="unimportant" href="javascript:void(0)">-</a></div>');
+ $('#gallery-view a').html(gallery_view ? _("Disable gallery mode") : _("Enable gallery mode")).click(function() {
+ gallery_view = !gallery_view;
+ $(this).html(gallery_view ? _("Disable gallery mode") : _("Enable gallery mode"));
+ toggle_gview(document);
+ });
+
+ var toggle_gview = function(elem) {
+ if (gallery_view) {
+ $(elem).find('img.post-image').parent().each(function() {
+ this.oldonclick = this.onclick;
+ this.onclick = handle_click;
+ $(this).attr('data-galid', Math.random());
+ });
+ }
+ else {
+ $(elem).find('img.post-image').parent().each(function() {
+ if (this.onclick == handle_click) this.onclick = this.oldonclick;
+ });
+ }
+ };
+
+ $(document).on('new_post', toggle_gview);
+
+ var gallery_opened = false;
+
+ var handle_click = function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ if (!gallery_opened) open_gallery();
+
+ gallery_setimage($(this).attr('data-galid'));
+ };
+
+ var handler, images, active, toolbar;
+
+ var open_gallery = function() {
+ $('body').css('overflow', 'hidden');
+
+ gallery_opened = true;
+
+ handler = $("<div id='alert_handler'></div>").hide().appendTo('body').css('text-align', 'left');
+
+ $("<div id='alert_background'></div>").click(close_gallery).appendTo(handler);
+
+ images = $("<div id='gallery_images'></div>").appendTo(handler);
+ toolbar = $("<div id='gallery_toolbar'></div>").appendTo(handler);
+ active = $("<div id='gallery_main'></div>").appendTo(handler);
+
+ active.on('click', function() {
+ close_gallery();
+ });
+
+ $('img.post-image').parent().each(function() {
+ var thumb = $(this).find('img').attr('src');
+
+ var i = $('<img>').appendTo(images);
+ i.attr('src', thumb);
+ i.attr('data-galid-th', $(this).attr('data-galid'));
+
+ i.on('click', function(e) {
+ gallery_setimage($(this).attr('data-galid-th'));
+ });
+ });
+
+ $("<a href='javascript:void(0)'><i class='fa fa-times'></i></div>")
+ .click(close_gallery).appendTo(toolbar);
+
+ $('body').on('keydown.gview', function(e) {
+ if (e.which == 39 || e.which == 40) { // right or down arrow
+ gallery_setimage(+1);
+ e.preventDefault();
+ }
+ else if (e.which == 37 || e.which == 38) { // left or up arrow
+ gallery_setimage(-1);
+ e.preventDefault();
+ }
+ });
+
+ handler.fadeIn(400);
+ };
+
+ var gallery_setimage = function(a) {
+ if (a == +1 || a == -1) {
+ var meth = (a == -1) ? 'prev' : 'next';
+ a = $('#gallery_images img.active')[meth]().attr('data-galid-th');
+ if (!a) return;
+ }
+
+ $('#gallery_images img.active').removeClass('active');
+
+ var thumb = $('#gallery_images [data-galid-th="'+a+'"]');
+ var elem = $('a[data-galid="'+a+'"]');
+
+ thumb.addClass('active');
+
+ var topscroll = thumb.position().top + images.scrollTop();
+ topscroll -= images.height() / 2;
+ topscroll += thumb.height() / 2;
+ images.animate({'scrollTop': topscroll}, 300);
+
+ var img = elem.attr('href');
+
+ active.find('img, video').fadeOut(200, function() { $(this).remove(); });
+
+ var i;
+ if (img.match(/player\.php/)) {
+ img = img.replace(/.*player\.php\?v=|&t=.*/g, '');
+ }
+ if (img.match(/\.webm$|\.mp4$|\.ogv$/i)) { // We are handling video nao
+ i = $('<video>');
+ i.attr('src', img);
+ i.attr('autoplay', true);
+ i.attr('controls', true);
+ i.appendTo(active);
+ i.hide();
+ }
+ else { // Just a plain image
+ i = $('<img>');
+ i.attr('src', img);
+ i.appendTo(active);
+ i.hide();
+ }
+
+ // Let's actually preload the next few images
+ var nextimg = $('#gallery_images active');
+ for (var j = 0; j < 3; j++) {
+ nextimg = nextimg.next();
+ var attr;
+ if (attr = nextimg.attr('data-gaild-th')) {
+ var href = $('a[data-galid="'+attr+'"]').attr('href');
+ if (href.match(/\.webm|\.mp4|\.ogv/i)) { j--; continue; }
+ if ($('[data-galid-preload="'+attr+'"]').length) continue;
+ var img = $('<img>').attr('src', href).attr('data-galid-preload', attr).hide().appendTo('body').on('load', function() { $(this).remove(); });
+ }
+ else break;
+ }
+
+ i.one('load canplay', function() {
+ i.css('left', 'calc(50% - '+i.width()+'px / 2)');
+ i.css('top', 'calc(50% - '+i.height()+'px / 2)');
+ i.fadeIn(200);
+ }).on('click', function(e) {
+ e.stopPropagation();
+ gallery_setimage(+1);
+ });
+ };
+
+ var close_gallery = function() {
+ $('body').css('overflow', 'auto');
+
+ gallery_opened = false;
+
+ $('body').off('keydown.gview');
+
+ handler.fadeOut(400, function() { handler.remove(); });
+ };
+
+});
diff --git a/js/hide-images.js b/js/hide-images.js
index 023c166c..323a1a1f 100644
--- a/js/hide-images.js
+++ b/js/hide-images.js
@@ -93,9 +93,9 @@ $(document).ready(function(){
$(this).parent().prev().find('.hide-image-link').click();
};
- $('div.post > a > img.post-image, div > a > img.post-image').each(handle_images);
+ $('div.post > a > img.post-image, div.post > a > video.post-image, div > a > img.post-image, div > a > video.post-image').each(handle_images);
$(document).on('new_post', function(e, post) {
- $(post).find('a > img.post-image').each(handle_images);
+ $(post).find('a > img.post-image, a > video.post-image').each(handle_images);
});
});
diff --git a/js/image-hover.js b/js/image-hover.js
new file mode 100644
index 00000000..93d61702
--- /dev/null
+++ b/js/image-hover.js
@@ -0,0 +1,182 @@
+/* image-hover.js
+ * This script is copied almost verbatim from https://github.com/Pashe/8chanX/blob/2-0/8chan-x.user.js
+ * All I did was remove the sprintf dependency and integrate it into 8chan's Options as opposed to Pashe's.
+ * I also changed initHover() to also bind on new_post.
+ * Thanks Pashe for using WTFPL.
+ */
+
+if (active_page === "catalog" || active_page === "thread" || active_page === "index") {
+$(document).on('ready', function(){
+
+if (window.Options && Options.get_tab('general')) {
+ Options.extend_tab("general",
+ "<fieldset><legend>Image hover</legend>"
+ + ("<label class='image-hover' id='imageHover'><input type='checkbox' /> "+_('Image hover')+"</label>")
+ + ("<label class='image-hover' id='catalogImageHover'><input type='checkbox' /> "+_('Image hover on catalog')+"</label>")
+ + ("<label class='image-hover' id='imageHoverFollowCursor'><input type='checkbox' /> "+_('Image hover should follow cursor')+"</label>")
+ + "</fieldset>");
+}
+
+$('.image-hover').on('change', function(){
+ var setting = $(this).attr('id');
+
+ localStorage[setting] = $(this).children('input').is(':checked');
+});
+
+if (!localStorage.imageHover || !localStorage.catalogImageHover || !localStorage.imageHoverFollowCursor) {
+ localStorage.imageHover = 'false';
+ localStorage.catalogImageHover = 'false';
+ localStorage.imageHoverFollowCursor = 'false';
+}
+
+if (getSetting('imageHover')) $('#imageHover>input').prop('checked', 'checked');
+if (getSetting('catalogImageHover')) $('#catalogImageHover>input').prop('checked', 'checked');
+if (getSetting('imageHoverFollowCursor')) $('#imageHoverFollowCursor>input').prop('checked', 'checked');
+
+function getFileExtension(filename) { //Pashe, WTFPL
+ if (filename.match(/\.([a-z0-9]+)(&loop.*)?$/i) !== null) {
+ return filename.match(/\.([a-z0-9]+)(&loop.*)?$/i)[1];
+ } else if (filename.match(/https?:\/\/(www\.)?youtube.com/)) {
+ return 'Youtube';
+ } else {
+ return "unknown: " + filename;
+ }
+}
+
+function isImage(fileExtension) { //Pashe, WTFPL
+ return ($.inArray(fileExtension, ["jpg", "jpeg", "gif", "png"]) !== -1);
+}
+
+function isVideo(fileExtension) { //Pashe, WTFPL
+ return ($.inArray(fileExtension, ["webm", "mp4"]) !== -1);
+}
+
+function isOnCatalog() {
+ return window.active_page === "catalog";
+}
+
+function isOnThread() {
+ return window.active_page === "thread";
+}
+
+function getSetting(key) {
+ return (localStorage[key] == 'true');
+}
+
+function initImageHover() { //Pashe, influenced by tux, et al, WTFPL
+ if (!getSetting("imageHover") && !getSetting("catalogImageHover")) {return;}
+
+ var selectors = [];
+
+ if (getSetting("imageHover")) {selectors.push("img.post-image", "canvas.post-image");}
+ if (getSetting("catalogImageHover") && isOnCatalog()) {
+ selectors.push(".thread-image");
+ $(".theme-catalog div.thread").css("position", "inherit");
+ }
+
+ function bindEvents(el) {
+ $(el).find(selectors.join(", ")).each(function () {
+ if ($(this).parent().data("expanded")) {return;}
+
+ var $this = $(this);
+
+ $this.on("mousemove", imageHoverStart);
+ $this.on("mouseout", imageHoverEnd);
+ $this.on("click", imageHoverEnd);
+ });
+ }
+
+ bindEvents(document.body);
+ $(document).on('new_post', function(e, post) {
+ bindEvents(post);
+ });
+}
+
+function imageHoverStart(e) { //Pashe, anonish, WTFPL
+ var hoverImage = $("#chx_hoverImage");
+
+ if (hoverImage.length) {
+ if (getSetting("imageHoverFollowCursor")) {
+ var scrollTop = $(window).scrollTop();
+ var imgY = e.pageY;
+ var imgTop = imgY;
+ var windowWidth = $(window).width();
+ var imgWidth = hoverImage.width() + e.pageX;
+
+ if (imgY < scrollTop + 15) {
+ imgTop = scrollTop;
+ } else if (imgY > scrollTop + $(window).height() - hoverImage.height() - 15) {
+ imgTop = scrollTop + $(window).height() - hoverImage.height() - 15;
+ }
+
+ if (imgWidth > windowWidth) {
+ hoverImage.css({
+ 'left': (e.pageX + (windowWidth - imgWidth)),
+ 'top' : imgTop,
+ });
+ } else {
+ hoverImage.css({
+ 'left': e.pageX,
+ 'top' : imgTop,
+ });
+ }
+
+ hoverImage.appendTo($("body"));
+ }
+
+ return;
+ }
+
+ var $this = $(this);
+
+ var fullUrl;
+ if ($this.parent().attr("href").match("src")) {
+ fullUrl = $this.parent().attr("href");
+ } else if (isOnCatalog()) {
+ fullUrl = $this.attr("data-fullimage");
+ if (!isImage(getFileExtension(fullUrl))) {fullUrl = $this.attr("src");}
+ }
+
+ if (isVideo(getFileExtension(fullUrl))) {return;}
+
+ hoverImage = $('<img id="chx_hoverImage" src="'+fullUrl+'" />');
+
+ if (getSetting("imageHoverFollowCursor")) {
+ var size = $this.parents('.file').find('.unimportant').text().match(/\b(\d+)x(\d+)\b/),
+ maxWidth = $(window).width(),
+ maxHeight = $(window).height();
+
+ var scale = Math.min(1, maxWidth / size[1], maxHeight / size[2]);
+ hoverImage.css({
+ "position" : "absolute",
+ "z-index" : 101,
+ "pointer-events": "none",
+ "width" : size[1] + "px",
+ "height" : size[2] + "px",
+ "max-width" : (size[1] * scale) + "px",
+ "max-height" : (size[2] * scale) + "px",
+ 'left' : e.pageX,
+ 'top' : imgTop,
+ });
+ } else {
+ hoverImage.css({
+ "position" : "fixed",
+ "top" : 0,
+ "right" : 0,
+ "z-index" : 101,
+ "pointer-events": "none",
+ "max-width" : "100%",
+ "max-height" : "100%",
+ });
+ }
+ hoverImage.appendTo($("body"));
+ if (isOnThread()) {$this.css("cursor", "none");}
+}
+
+function imageHoverEnd() { //Pashe, WTFPL
+ $("#chx_hoverImage").remove();
+}
+
+initImageHover();
+});
+}
diff --git a/js/live-index.js b/js/live-index.js
index 463f7596..017d0c1f 100644
--- a/js/live-index.js
+++ b/js/live-index.js
@@ -58,7 +58,7 @@ if (active_page == 'index' && (""+document.location).match(/\/(index\.html)?(\?|
update_new_threads(new_threads);
});
- }, 1000);
+ }, 20000);
});
$(document).on("new_post", function(e, post) {
diff --git a/js/no-animated-gif.js b/js/no-animated-gif.js
index 45a55f97..a10a6497 100644
--- a/js/no-animated-gif.js
+++ b/js/no-animated-gif.js
@@ -57,7 +57,7 @@ if (active_page == 'thread' || active_page == 'index' || active_page == 'ukko' |
if (window.Options && Options.get_tab('general')) {
selector = '#no-animated-gif>input';
event = 'change';
- Options.extend_tab("general", "<label id='no-animated-gif'><input type='checkbox' /> "+_('Unanimate GIFs')+"</label>");
+ Options.extend_tab("general", "<label id='no-animated-gif'><input type='checkbox' />"+_('Unanimate GIFs')+"</label>");
}
else {
selector = '#no-animated-gif';
diff --git a/js/own-board.js b/js/own-board.js
new file mode 100644
index 00000000..497c568c
--- /dev/null
+++ b/js/own-board.js
@@ -0,0 +1,116 @@
+/*****************************************************************
+ * ------- WARNING! --------- *
+ *****************************************************************
+ * This script is at the current time undocumented and *
+ * unsupported. It is still a work in progress and will likely *
+ * change. You are on your own. *
+ *****************************************************************/
+
++function() {
+
+var uniq = function(a) {
+ var b = {};
+ var c = [];
+ a.forEach(function(i) {
+ if (!b[i]) {
+ c.push(i);
+ b[i] = true;
+ }
+ });
+ return c;
+};
+
+
+if (active_page == 'thread' || active_page == 'index') {
+ var board = null;
+
+ $(function() {
+ board = $('input[name="board"]').first().val();
+ });
+
+ $(document).on('ajax_after_post', function(e, r) {
+ var threads = JSON.parse(localStorage.obthreads || '[]');
+
+ var thread = null;
+ if (active_page == 'index') {
+ thread = r.id|0;
+ }
+ else {
+ thread = $('[id^="thread_"]').first().attr('id').replace("thread_", "")|0;
+ }
+
+ threads.push([board, thread]);
+ threads = uniq(threads);
+ localStorage.obthreads = JSON.stringify(threads);
+ });
+}
+
+var loaded = false;
+$(function() {
+ loaded = true;
+});
+
+var activate = function() {
+ if (document.location.hash != '#own') return false;
+
+ if (loaded) late_activate();
+ else $(function() { late_activate(); });
+
+ return true;
+};
+
+var late_activate = function() {
+ $('[id^="thread_"]').remove();
+
+ var threads = JSON.parse(localStorage.obthreads || '[]');
+
+ threads.forEach(function(v) {
+ var board = v[0];
+ var thread = v[1];
+ var url = "/"+board+"/res/"+thread+".html";
+
+ $.get(url, function(html) {
+ var s = $(html).find('[id^="thread_"]');
+
+ s[0].bumptime = (new Date(s.find("time").last().attr("datetime"))).getTime();
+
+ var added = false;
+ $('[id^="thread_"]').each(function() {
+ if (added) return;
+ if (s[0].bumptime > this.bumptime) {
+ added = true;
+ s.insertBefore(this);
+ }
+ });
+ if (!added) {
+ s.appendTo('[name="postcontrols"]');
+ }
+
+ s.find('.post.reply').addClass('hidden').hide().slice(-3).removeClass('hidden').show();
+
+ s.find('.post.reply.hidden').next().addClass('hidden').hide(); // Hide <br> elements
+
+ var posts_omitted = s.find('.post.reply.hidden').length;
+ var images_omitted = s.find('.post.reply.hidden img').length;
+
+ if (posts_omitted > 0) {
+ var omitted = $(fmt('<span class="omitted">'+_('{0} posts and {1} images omitted.')+' '+_('Click reply to view.')+'</span>',
+ [posts_omitted, images_omitted]));
+
+ omitted.appendTo(s.find('.post.op'));
+ }
+
+ var reply = $('<a href="'+url+'">['+_('Reply')+']</a>').appendTo(s.find('.intro').first());
+
+ $(document).trigger('new_post', s[0]);
+ });
+ });
+};
+
+$(window).on("hashchange", function() {
+ return !activate();
+});
+activate();
+
+
+}();
diff --git a/js/quick-reply.js b/js/quick-reply.js
index 07fe4aef..12cca366 100644
--- a/js/quick-reply.js
+++ b/js/quick-reply.js
@@ -83,11 +83,12 @@
}\
#quick-reply textarea {\
width: 100%;\
+ min-width: 100%;\
box-sizing: border-box;\
-webkit-box-sizing:border-box;\
-moz-box-sizing: border-box;\
font-size: 10pt;\
- resize: vertical;\
+ resize: vertical horizontal;\
}\
#quick-reply input, #quick-reply select, #quick-reply textarea {\
margin: 0 0 1px 0;\
@@ -115,7 +116,7 @@
#quick-reply td.recaptcha-response {\
padding: 0 0 1px 0;\
}\
- @media screen and (max-width: 800px) {\
+ @media screen and (max-width: 400px) {\
#quick-reply {\
display: none !important;\
}\
@@ -363,7 +364,7 @@
$(window).ready(function() {
if (settings.get('hide_at_top', true)) {
$(window).scroll(function() {
- if ($(this).width() <= 800)
+ if ($(this).width() <= 400)
return;
if ($(this).scrollTop() < $origPostForm.offset().top + $origPostForm.height() - 100)
$postForm.fadeOut(100);
@@ -384,7 +385,7 @@
};
$(window).on('cite', function(e, id, with_link) {
- if ($(this).width() <= 800)
+ if ($(this).width() <= 400)
return;
show_quick_reply();
if (with_link) {
@@ -439,7 +440,7 @@
$('.quick-reply-btn').hide();
$(window).scroll(function() {
- if ($(this).width() <= 800)
+ if ($(this).width() <= 400)
return;
if ($(this).scrollTop() < $('form[name="post"]:first').offset().top + $('form[name="post"]:first').height() - 100)
$('.quick-reply-btn').fadeOut(100);
diff --git a/js/thread-stats.js b/js/thread-stats.js
new file mode 100644
index 00000000..8873dbdb
--- /dev/null
+++ b/js/thread-stats.js
@@ -0,0 +1,116 @@
+/*
+ * thread-stats.js
+ * - Adds statistics of the thread below the posts area
+ * - Shows ID post count beside each postID on hover
+ *
+ * Usage:
+ * $config['additional_javascript'][] = 'js/jquery.min.js';
+ * $config['additional_javascript'][] = 'js/thread-stats.js';
+ */
+if (active_page == 'thread') {
+$(document).ready(function(){
+ //check if page uses unique ID
+ var IDsupport = ($('.poster_id').length > 0);
+ var thread_id = (document.location.pathname + document.location.search).split('/');
+ thread_id = thread_id[thread_id.length -1].split('+')[0].split('-')[0].split('.')[0];
+
+ $('.boardlist.bottom, footer')
+ .first()
+ .before('<div id="thread_stats"></div>');
+ var el = $('#thread_stats');
+ el.prepend(_('Page')+' <span id="thread_stats_page">?</span>');
+ if (IDsupport){
+ el.prepend('<span id="thread_stats_uids">0</span> UIDs |&nbsp;');
+ }
+ el.prepend('<span id="thread_stats_images">0</span> '+_('images')+' |&nbsp;');
+ el.prepend('<span id="thread_stats_posts">0</span> '+_('replies')+' |&nbsp;');
+ delete el;
+ function update_thread_stats(){
+ var op = $('#thread_'+ thread_id +' > div.post.op:not(.post-hover):not(.inline)').first();
+ var replies = $('#thread_'+ thread_id +' > div.post.reply:not(.post-hover):not(.inline)');
+ // post count
+ $('#thread_stats_posts').text(replies.length);
+ // image count
+ $('#thread_stats_images').text(replies.filter(function(){
+ return $(this).find('> .files').text().trim() != false;
+ }).length);
+ // unique ID count
+ if (IDsupport) {
+ var opID = op.find('> .intro > .poster_id').text();
+ var ids = {};
+ replies.each(function(){
+ var cur = $(this).find('> .intro > .poster_id');
+ var curID = cur.text();
+ if (ids[curID] === undefined) {
+ ids[curID] = 0;
+ }
+ ids[curID]++;
+ });
+ if (ids[opID] === undefined) {
+ ids[opID] = 0;
+ }
+ ids[opID]++;
+ var cur = op.find('>.intro >.poster_id');
+ cur.find('+.posts_by_id').remove();
+ cur.after('<span class="posts_by_id"> ('+ ids[cur.text()] +')</span>');
+ replies.each(function(){
+ cur = $(this).find('>.intro >.poster_id');
+ cur.find('+.posts_by_id').remove();
+ cur.after('<span class="posts_by_id"> ('+ ids[cur.text()] +')</span>');
+ });
+ var size = function(obj) {
+ var size = 0, key;
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) size++;
+ }
+ return size;
+ };
+ $('#thread_stats_uids').text(size(ids));
+ }
+ var board_name = $('input[name="board"]').val();
+ $.getJSON('//'+ document.location.host +'/'+ board_name +'/threads.json').success(function(data){
+ var found, page = '???';
+ for (var i=0;data[i];i++){
+ var threads = data[i].threads;
+ for (var j=0; threads[j]; j++){
+ if (parseInt(threads[j].no) == parseInt(thread_id)) {
+ page = data[i].page +1;
+ found = true;
+ break;
+ }
+ }
+ if (found) break;
+ }
+ $('#thread_stats_page').text(page);
+ if (!found) $('#thread_stats_page').css('color','red');
+ else $('#thread_stats_page').css('color','');
+ });
+ }
+ // load the current page the thread is on.
+ // uses ajax call so it gets loaded on a delay (depending on network resources available)
+ var thread_stats_page_timer = setInterval(function(){
+ var board_name = $('input[name="board"]').val();
+ $.getJSON('//'+ document.location.host +'/'+ board_name +'/threads.json').success(function(data){
+ var found, page = '???';
+ for (var i=0;data[i];i++){
+ var threads = data[i].threads;
+ for (var j=0; threads[j]; j++){
+ if (parseInt(threads[j].no) == parseInt(thread_id)) {
+ page = data[i].page +1;
+ found = true;
+ break;
+ }
+ }
+ if (found) break;
+ }
+ $('#thread_stats_page').text(page);
+ if (!found) $('#thread_stats_page').css('color','red');
+ else $('#thread_stats_page').css('color','');
+ });
+ },30000);
+ $('body').append('<style>.posts_by_id{display:none;}.poster_id:hover+.posts_by_id{display:initial}</style>');
+ update_thread_stats();
+ $('#update_thread').click(update_thread_stats);
+ $(document).on('new_post',update_thread_stats);
+});
+}
diff --git a/js/toggle-images.js b/js/toggle-images.js
index 20940ccf..b8940252 100644
--- a/js/toggle-images.js
+++ b/js/toggle-images.js
@@ -60,7 +60,7 @@ $(document).ready(function(){
if (window.Options && Options.get_tab('general')) {
selector = '#toggle-images>input';
event = 'change';
- Options.extend_tab("general", "<label id='toggle-images'><input type='checkbox' /> "+_('Hide images')+"</label>");
+ Options.extend_tab("general", "<label id='toggle-images'><input type='checkbox' />"+_('Hide images')+"</label>");
}
else {
selector = '#toggle-images a';
diff --git a/js/treeview.js b/js/treeview.js
index 78ad620b..1709debb 100644
--- a/js/treeview.js
+++ b/js/treeview.js
@@ -11,14 +11,28 @@
*
*/
-if (active_page == 'thread')
+if (active_page == 'thread' || active_page == 'ukko' || active_page == 'index')
$(function() {
- $('hr:first').before('<div id="treeview" style="text-align:right"><a class="unimportant" href="javascript:void(0)"></a></div>');
- $('div#treeview a')
- .text(_('Tree view'))
- .click(function(e) {
- e.preventDefault();
+ if (window.Options && Options.get_tab('general')) {
+ var selector = '#treeview-global>input';
+ Options.extend_tab("general", "<label id='treeview-global'><input type='checkbox' /> "+_('Use tree view by default')+"</label>");
+ $(selector).on('change', function() {
+ if (localStorage.treeview === 'true') {
+ localStorage.treeview = 'false';
+ } else {
+ localStorage.treeview = 'true';
+ }
+ });
+ if (localStorage.treeview === 'true') {
+ $(selector).attr('checked', 'checked');
+ }
+ }
+});
+if (active_page == 'thread')
+$(function() {
+ var treeview = function(enable) {
+ if (enable === true) {
$('.post.reply').each(function(){
var references = [];
$(this).find('.body a').each(function(){
@@ -26,7 +40,6 @@ $(function() {
references.push(parseInt($(this).html().replace('&gt;&gt;', '')));
}
});
-
var maxref = references.reduce(function(a,b) { return a > b ? a : b; }, 0);
var parent_post = $("#reply_"+maxref);
@@ -39,7 +52,24 @@ $(function() {
post.detach().css("margin-left", margin).insertAfter(parent_post.next());
br.detach().insertAfter(post);
-
});
- });
+ } else {
+ $('.post.reply').sort(function(a,b) {
+ return parseInt(a.id.replace('reply_', '')) - parseInt(b.id.replace('reply_', ''));
+ }).each(function () {
+ var post = $(this);
+ var br = post.next();
+ post.detach().css('margin-left', '').appendTo('.thread');
+ br.detach().insertAfter(post);
+ });
+ }
+ }
+
+ $('hr:first').before('<div class="unimportant" style="text-align:right"><label for="treeview"><input type="checkbox" id="treeview"> '+_('Tree view')+'</label></div>');
+ $('input#treeview').on('change', function(e) { treeview($(this).is(':checked')); });
+
+ if (localStorage.treeview === 'true') {
+ treeview(true);
+ $('input#treeview').attr('checked', true);
+ }
});
diff --git a/js/upload-selection.js b/js/upload-selection.js
index e2032748..b342a134 100644
--- a/js/upload-selection.js
+++ b/js/upload-selection.js
@@ -25,6 +25,7 @@ $(function(){
$("#upload_url").hide();
$("#upload_embed").hide();
$(".add_image").hide();
+ $(".dropzone-wrap").hide();
$('[id^=upload_file]').each(function(i, v) {
$(v).val('');
@@ -40,6 +41,7 @@ $(function(){
enable_file = function() {
disable_all();
$("#upload").show();
+ $(".dropzone-wrap").show();
$(".file_separator").show();
$("[id^=upload_file]").show();
$(".add_image").show();
diff --git a/js/wPaint b/js/wPaint
-Subproject 2c272dffca0f3d7b7163bd82ba15629f5440927
+Subproject f11220032e7edb8349516d3751d3aaee0fd0de6
diff --git a/js/watch.js b/js/watch.js
index a202130f..07c6942a 100644
--- a/js/watch.js
+++ b/js/watch.js
@@ -98,6 +98,9 @@ $(function(){
else {
bc.threads = bc.threads || {};
bc.threads[thread] = Date.now();
+
+ bc.slugs = bc.slugs || {};
+ bc.slugs[thread] = document.location.pathname + document.location.search;
}
st[board] = bc;
storage_save(st);
@@ -121,7 +124,7 @@ $(function(){
var tag;
if (variant == 'desktop') {
- tag = $("<a href='"+modRoot+board+"/res/"+tid+".html'><span>#"+tid+"</span><span class='cb-uri watch-remove'>"+newposts+"</span>");
+ tag = $("<a href='"+((storage()[board].slugs && storage()[board].slugs[tid]) || (modRoot+board+"/res/"+tid+".html"))+"'><span>#"+tid+"</span><span class='cb-uri watch-remove'>"+newposts+"</span>");
tag.find(".watch-remove").mouseenter(function() {
this.oldval = $(this).html();
$(this).css("min-width", $(this).width());
@@ -132,7 +135,7 @@ $(function(){
})
}
else if (variant == 'mobile') {
- tag = $("<a href='"+modRoot+board+"/res/"+tid+".html'><span>#"+tid+"</span><span class='cb-uri'>"+newposts+"</span>"
+ tag = $("<a href='"+((storage()[board].slugs && storage()[board].slugs[tid]) || (modRoot+board+"/res/"+tid+".html"))+"'><span>#"+tid+"</span><span class='cb-uri'>"+newposts+"</span>"
+"<span class='cb-uri watch-remove'><i class='fa fa-minus'></i></span>");
}
@@ -245,7 +248,7 @@ $(function(){
var st = storage();
var sched = 0;
- var sched_diff = 300;
+ var sched_diff = 2000;
for (var i in st) {
if (st[i].watched) {
diff --git a/js/wpaint.js b/js/wpaint.js
index 9c619070..a245a22b 100644
--- a/js/wpaint.js
+++ b/js/wpaint.js
@@ -13,12 +13,7 @@
* $config['additional_javascript'][] = 'js/jquery.min.js';
* $config['additional_javascript'][] = 'js/jquery-ui.custom.min.js';
* $config['additional_javascript'][] = 'js/ajax.js';
- * $config['additional_javascript'][] = 'js/wPaint/lib/wColorPicker.min.js';
- * $config['additional_javascript'][] = 'js/wPaint/wPaint.min.js';
- * $config['additional_javascript'][] = 'js/wPaint/plugins/main/wPaint.menu.main.min.js';
- * $config['additional_javascript'][] = 'js/wPaint/plugins/text/wPaint.menu.text.min.js';
- * $config['additional_javascript'][] = 'js/wPaint/plugins/shapes/wPaint.menu.main.shapes.min.js';
- * $config['additional_javascript'][] = 'js/wPaint/plugins/file/wPaint.menu.main.file.min.js';
+ * $config['additional_javascript'][] = 'js/wPaint/8ch.js';
* $config['additional_javascript'][] = 'js/wpaint.js';
* $config['additional_javascript'][] = 'js/upload-selection.js';
*
@@ -49,7 +44,7 @@ oekaki.init = function() {
var oekaki_form = '<tr id="oekaki"><th>Oekaki</th><td><div id="wpaintctr"><div id="wpaintdiv"></div></div></td></tr>';
// Add oekaki after the file input
- $('form[name="post"]:not(#quick-reply) input[type="file"]').parent().parent().after(oekaki_form);
+ $('form[name="post"]:not(#quick-reply) [id="upload"]').after(oekaki_form);
$('<link class="wpaintcss" rel="stylesheet" href="'+configRoot+'js/wPaint/wPaint.min.css" />').appendTo($("head"));
$('<link class="wpaintcss" rel="stylesheet" href="'+configRoot+'js/wPaint/lib/wColorPicker.min.css" />').appendTo($("head"));