diff --git a/inc/config.php b/inc/config.php
index 5f9b7130..6be2519c 100644
--- a/inc/config.php
+++ b/inc/config.php
@@ -1254,7 +1254,7 @@
$config['embedding'] = [
[
'/^https?:\/\/(\w+\.)?youtube\.com\/watch\?v=([a-zA-Z0-9\-_]{10,11})?$/i',
- ''
+ ''
],
[
'/^https?:\/\/(\w+\.)?vimeo\.com\/(\d{2,10})(\?.+)?$/i',
diff --git a/js/auto-reload.js b/js/auto-reload.js
index b9cf3e23..8b6e286c 100644
--- a/js/auto-reload.js
+++ b/js/auto-reload.js
@@ -139,7 +139,12 @@ $(document).ready(function(){
var poll = function(manualUpdate) {
stop_auto_update();
- $('#update_secs').text(_("Updating..."));
+ let isScreenSmall = window.matchMedia('(max-width: 48em)').matches;
+ if (isScreenSmall) {
+ $('#update_secs').text('...');
+ } else {
+ $('#update_secs').text(_('Updating...'));
+ }
$.ajax({
url: document.location,
diff --git a/js/expand.js b/js/expand.js
index 4dde131b..8727ea91 100644
--- a/js/expand.js
+++ b/js/expand.js
@@ -20,7 +20,7 @@ $(document).ready(function() {
let doExpand = function() {
$(this)
- .html($(this).text().replace(_("Click reply to view."), '' + _("Click to expand") + '.'))
+ .html($(this).text().concat(' ' + _('Click to expand') + '.'))
.find('a').click(window.expandFun = function() {
let thread = $(this).parents('[id^="thread_"]');
$.ajax({
@@ -35,7 +35,8 @@ $(document).ready(function() {
if (lastExpanded) {
$(this).addClass('expanded').insertAfter(lastExpanded).before('
');
} else {
- $(this).addClass('expanded').insertAfter(thread.find('div.post:first')).after('
');
+ let opBr = thread.find('div.post').first().next();
+ $(this).addClass('expanded').insertAfter(opBr).after('
');
}
lastExpanded = $(this);
$(document).trigger('new_post', this);
diff --git a/js/hide-images.js b/js/hide-images.js
index 4fdad891..66d9b354 100644
--- a/js/hide-images.js
+++ b/js/hide-images.js
@@ -16,7 +16,7 @@
$(document).ready(function(){
$('').appendTo($('head'));
-
+
if (!localStorage.hiddenimages)
localStorage.hiddenimages = '{}';
@@ -47,9 +47,9 @@ $(document).ready(function(){
if (!hidden_data[board]) {
hidden_data[board] = {}; // id : timestamp
}
-
- var replacement = $(''+_('File')+' (');
-
+
+ var replacement = $(' ): ');
+
replacement.find('a').click(function() {
if (hidden_data[board][id]) {
hidden_data[board][id]['ts'] = Math.round(Date.now() / 1000);
@@ -59,36 +59,36 @@ $(document).ready(function(){
hidden_data[board][id] = {ts: Math.round(Date.now() / 1000), index: [index]};
}
store_data();
-
- var show_link = $(''+_('show')+'').click(function() {
+
+ var show_link = $('').click(function() {
var i = hidden_data[board][id]['index'].indexOf(index);
if (i > -1) hidden_data[board][id]['index'].splice(i,1);
-
+
if (hidden_data[board][id]['index'].length === 0)
delete hidden_data[board][id];
store_data();
-
+
$(img)
.removeClass('hidden')
.attr('src', $(img).data('orig'));
$(this).prev().show();
$(this).remove();
});
-
+
$(this).hide().after(show_link);
-
+
if ($(img).parent().data('expanded') == 'true') {
$(img).parent().click();
}
-
+
$(img)
.data('orig', img.src)
.attr('src', 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==')
.addClass('hidden');
});
-
+
$(this).parent().prev().contents().first().replaceWith(replacement);
-
+
if (hidden_data[board][id] && hidden_data[board][id]['index'].indexOf(index) !== -1)
$(this).parent().prev().find('.hide-image-link').click();
};
diff --git a/js/mobile-style.js b/js/mobile-style.js
index e35dc402..72e0c971 100644
--- a/js/mobile-style.js
+++ b/js/mobile-style.js
@@ -11,11 +11,7 @@
* $config['additional_javascript'][] = 'js/mobile-style.js';
*/
-if(navigator.userAgent.match(/iPhone|iPod|iPad|Android|Opera Mini|Blackberry|PlayBook|Windows Phone|Tablet PC|Windows CE|IEMobile/i)) {
- $('html').addClass("mobile-style");
- device_type = "mobile";
-}
-else {
+if (!navigator.userAgent.match(/iPhone|iPod|iPad|Android|Opera Mini|Blackberry|PlayBook|Windows Phone|Tablet PC|Windows CE|IEMobile/i)) {
$('html').addClass("desktop-style");
device_type = "desktop";
}
diff --git a/js/post-filter.js b/js/post-filter.js
index 12ae2cd7..f5437e49 100644
--- a/js/post-filter.js
+++ b/js/post-filter.js
@@ -182,13 +182,13 @@ if (active_page === 'thread' || active_page === 'index' || active_page === 'cata
$(ele).data('hidden', true);
if ($ele.hasClass('op')) {
- $ele.parent().find('.body, .files, .video-container').not($ele.children('.reply').children()).hide();
+ $ele.parent().find('.head, .body, .files, .video-container').not($ele.children('.reply').children()).hide();
// hide thread replies on index view
if (active_page == 'index' || active_page == 'ukko') $ele.parent().find('.omitted, .reply:not(.hidden), post_no, .mentioned, br').hide();
} else {
// normal posts
- $ele.children('.body, .files, .video-container').hide();
+ $ele.children('.head, .body, .files, .video-container').hide();
}
}
function show(ele) {
@@ -196,11 +196,11 @@ if (active_page === 'thread' || active_page === 'index' || active_page === 'cata
$(ele).data('hidden', false);
if ($ele.hasClass('op')) {
- $ele.parent().find('.body, .files, .video-container').show();
+ $ele.parent().find('.head, .body, .files, .video-container').show();
if (active_page == 'index') $ele.parent().find('.omitted, .reply:not(.hidden), post_no, .mentioned, br').show();
} else {
// normal posts
- $ele.children('.body, .files, .video-container').show();
+ $ele.children('.head, .body, .files, .video-container').show();
}
}
@@ -226,18 +226,19 @@ if (active_page === 'thread' || active_page === 'index' || active_page === 'cata
submenu.add_item('filter-remove-trip', _('Tripcode'));
Menu.onclick(function (e, $buffer) {
- var ele = e.target.parentElement.parentElement;
- var $ele = $(ele);
+ let ele = e.target.parentElement.parentElement.parentElement;
+ let $ele = $(ele);
- var threadId = $ele.parent().attr('id').replace('thread_', '');
- var boardId = $ele.parent().data('board');
- var postId = $ele.find('.post_no').not('[id]').text();
+ let threadNode = $ele.parent('.thread');
+ let threadId = threadNode.attr('id').replace('thread_', '');
+ let boardId = $ele.parent().data('board');
+ let postId = $ele.find('.post_no').not('[id]').text();
if (pageData.hasUID) {
var postUid = $ele.find('.poster_id').text();
}
- var postName;
- var postTrip = '';
+ let postName;
+ let postTrip = '';
if (!pageData.forcedAnon) {
postName = (typeof $ele.find('.name').contents()[0] == 'undefined') ? '' : nameSpanToString($ele.find('.name')[0]);
postTrip = $ele.find('.trip').text();
diff --git a/js/post-hover.js b/js/post-hover.js
index d7970871..b30c35b4 100644
--- a/js/post-hover.js
+++ b/js/post-hover.js
@@ -13,165 +13,217 @@
*
*/
-onReady(function() {
- let dontFetchAgain = [];
- initHover = function() {
- let link = $(this);
- let id;
- let matches;
+/*
+ * Unknown media types always return false, so old browsers (css media 3 or prior to css media) which do support
+ * any-hover or css media queries may return false negatives.
+ * Handle it by checking if the query is explicitly NOT supported.
+ */
+if (!window.matchMedia('(any-hover: none)').matches) {
+ onReady(function() {
+ let isScreenSmall = false
+ /*
+ * Set up screen size detection.
+ * If the method is not defined, suppose the screen is always not-small.
+ */
+ if (window.matchMedia) {
+ let query = window.matchMedia('(max-width: 48em)');
- if (link.is('[data-thread]')) {
- id = link.attr('data-thread');
- } else if (matches = link.text().match(/^>>(?:>\/([^\/]+)\/)?(\d+)$/)) {
- id = matches[2];
- } else {
- return;
+ query.addEventListener('change', (e) => isScreenSmall = e.matches);
+ isScreenSmall = query.matches;
}
- let board = $(this);
- while (board.data('board') === undefined) {
- board = board.parent();
- }
- let threadid;
- if (link.is('[data-thread]')) {
- threadid = 0;
- } else {
- threadid = board.attr('id').replace("thread_", "");
- }
+ let dontFetchAgain = [];
+ initHover = function() {
+ let link = $(this);
+ let id;
+ let matches;
- board = board.data('board');
+ if (link.is('[data-thread]')) {
+ id = link.attr('data-thread');
+ } else if (matches = link.text().match(/^>>(?:>\/([^\/]+)\/)?(\d+)$/)) {
+ id = matches[2];
+ } else {
+ return;
+ }
- let parentboard = board;
+ let board = $(this);
+ while (board.data('board') === undefined) {
+ board = board.parent();
+ }
+ let threadid;
+ if (link.is('[data-thread]')) {
+ threadid = 0;
+ } else {
+ threadid = board.attr('id').replace("thread_", "");
+ }
- if (link.is('[data-thread]')) {
- parentboard = $('form[name="post"] input[name="board"]').val();
- } else if (matches[1] !== undefined) {
- board = matches[1];
- }
+ board = board.data('board');
- let post = false;
- let hovering = false;
- let hoveredAt;
- link.hover(function(e) {
- hovering = true;
- hoveredAt = {'x': e.pageX, 'y': e.pageY};
+ let parentboard = board;
- let startHover = function(link) {
- if (post.is(':visible') &&
- post.offset().top >= $(window).scrollTop() &&
- post.offset().top + post.height() <= $(window).scrollTop() + $(window).height()) {
- // post is in view
- post.addClass('highlighted');
- } else {
- let newPost = post.clone();
- newPost.find('>.reply, >br').remove();
- newPost.find('span.mentioned').remove();
- newPost.find('a.post_anchor').remove();
+ if (link.is('[data-thread]')) {
+ parentboard = $('form[name="post"] input[name="board"]').val();
+ } else if (matches[1] !== undefined) {
+ board = matches[1];
+ }
- newPost
- .attr('id', 'post-hover-' + id)
- .attr('data-board', board)
- .addClass('post-hover')
- .css('border-style', 'solid')
- .css('box-shadow', '1px 1px 1px #999')
- .css('display', 'block')
- .css('position', 'absolute')
- .css('font-style', 'normal')
- .css('z-index', '100')
- .addClass('reply').addClass('post')
- .insertAfter(link.parent())
+ let post = false;
+ let hovering = false;
+ let hoveredAt;
- link.trigger('mousemove');
+ let updatePreviewPosition = function(pageX, pageY, hoverPreview) {
+ let scrollTop = $(window).scrollTop();
+ if (link.is("[data-thread]")) {
+ scrollTop = 0;
}
+ let epy = pageY;
+ if (link.is("[data-thread]")) {
+ epy -= $(window).scrollTop();
+ }
+
+ let top = (epy ? epy : hoveredAt['y']) - 10;
+
+ if (epy < scrollTop + 15) {
+ top = scrollTop;
+ } else if (epy > scrollTop + $(window).height() - hoverPreview.height() - 15) {
+ top = scrollTop + $(window).height() - hoverPreview.height() - 15;
+ }
+
+ let hovery = pageY ? pageY : hoveredAt['y'];
+ if ((hovery - top) > 20){
+ top = hovery;
+ }
+
+ let previewX;
+ if (isScreenSmall) {
+ previewX = 0;
+ } else {
+ previewX = (pageX ? pageX : hoveredAt['x']) + 1
+ }
+
+ hoverPreview.css('left', previewX).css('top', top);
};
- post = $('[data-board="' + board + '"] div.post#reply_' + id + ', [data-board="' + board + '"]div#thread_' + id);
- if (post.length > 0) {
- startHover($(this));
- } else {
- let url = link.attr('href').replace(/#.*$/, '');
+ link.hover(function(e) {
+ hovering = true;
+ hoveredAt = {'x': e.pageX, 'y': e.pageY};
- if ($.inArray(url, dontFetchAgain) != -1) {
+ let startHover = function(link) {
+ if ($.contains(post[0], link[0])) {
+ // link links to itself or to op; ignore
+ } else if (post.is(':visible') &&
+ post.offset().top >= $(window).scrollTop() &&
+ post.offset().top + post.height() <= $(window).scrollTop() + $(window).height()) {
+ // Post is in view, highlight it.
+ post.addClass('highlighted');
+ } else {
+ // Creates the preview, and displays it,
+ let hoverPreview = post.clone();
+ hoverPreview.find('>.reply, >br').remove();
+ hoverPreview.find('a.post_anchor').remove();
+
+ hoverPreview
+ .attr('id', 'post-hover-' + id)
+ .attr('data-board', board)
+ .addClass('post-hover')
+ .css('border-style', 'solid')
+ .css('display', 'inline-block')
+ .css('position', 'absolute')
+ .css('font-style', 'normal')
+ .css('z-index', '100');
+
+ if (isScreenSmall) {
+ hoverPreview
+ .css('margin-top', '1em')
+ .css('border-left-style', 'none')
+ .css('border-right-style', 'none');
+ } else {
+ hoverPreview.css('margin-left', '1em');
+ }
+
+ hoverPreview.addClass('reply').addClass('post')
+ .insertAfter(link.parent())
+
+ updatePreviewPosition(e.pageX, e.pageY, hoverPreview);
+ }
+ };
+
+ post = $('[data-board="' + board + '"] div.post#reply_' + id + ', [data-board="' + board + '"]div#thread_' + id);
+ if (post.length > 0) {
+ startHover($(this));
+ } else {
+ let url = link.attr('href').replace(/#.*$/, '');
+
+ if ($.inArray(url, dontFetchAgain) != -1) {
+ return;
+ }
+ dontFetchAgain.push(url);
+
+ $.ajax({
+ url: url,
+ context: document.body,
+ success: function(data) {
+ let mythreadid = $(data).find('div[id^="thread_"]').attr('id').replace("thread_", "");
+
+ if (mythreadid == threadid && parentboard == board) {
+ $(data).find('div.post.reply').each(function() {
+ if ($('[data-board="' + board + '"] #' + $(this).attr('id')).length == 0) {
+ $('[data-board="' + board + '"]#thread_' + threadid + " .post.reply:first").before($(this).hide().addClass('hidden'));
+ }
+ });
+ } else if ($('[data-board="' + board + '"]#thread_' + mythreadid).length > 0) {
+ $(data).find('div.post.reply').each(function() {
+ if ($('[data-board="' + board + '"] #' + $(this).attr('id')).length == 0) {
+ $('[data-board="' + board + '"]#thread_' + mythreadid + " .post.reply:first").before($(this).hide().addClass('hidden'));
+ }
+ });
+ } else {
+ $(data).find('div[id^="thread_"]').hide().attr('data-cached', 'yes').prependTo('form[name="postcontrols"]');
+ }
+
+ post = $('[data-board="' + board + '"] div.post#reply_' + id + ', [data-board="' + board + '"]div#thread_' + id);
+
+ if (hovering && post.length > 0) {
+ startHover(link);
+ }
+ }
+ });
+ }
+ }, function() {
+ // Remove the preview.
+
+ hovering = false;
+ if (!post) {
return;
}
- dontFetchAgain.push(url);
- $.ajax({
- url: url,
- context: document.body,
- success: function(data) {
- let mythreadid = $(data).find('div[id^="thread_"]').attr('id').replace("thread_", "");
+ post.removeClass('highlighted');
+ if (post.hasClass('hidden') || post.data('cached') == 'yes') {
+ post.css('display', 'none');
+ }
+ $('.post-hover').remove();
+ }).mousemove(function(e) {
+ // Update the preview position if the mouse moves.
- if (mythreadid == threadid && parentboard == board) {
- $(data).find('div.post.reply').each(function() {
- if ($('[data-board="' + board + '"] #' + $(this).attr('id')).length == 0) {
- $('[data-board="' + board + '"]#thread_' + threadid + " .post.reply:first").before($(this).hide().addClass('hidden'));
- }
- });
- } else if ($('[data-board="' + board + '"]#thread_' + mythreadid).length > 0) {
- $(data).find('div.post.reply').each(function() {
- if ($('[data-board="' + board + '"] #' + $(this).attr('id')).length == 0) {
- $('[data-board="' + board + '"]#thread_' + mythreadid + " .post.reply:first").before($(this).hide().addClass('hidden'));
- }
- });
- } else {
- $(data).find('div[id^="thread_"]').hide().attr('data-cached', 'yes').prependTo('form[name="postcontrols"]');
- }
+ if (!post) {
+ return;
+ }
- post = $('[data-board="' + board + '"] div.post#reply_' + id + ', [data-board="' + board + '"]div#thread_' + id);
+ // The actual displayed preview.
+ let hoverPreview = $('#post-hover-' + id + '[data-board="' + board + '"]');
+ if (hoverPreview.length === 0) {
+ return;
+ }
- if (hovering && post.length > 0) {
- startHover(link);
- }
- }
- });
- }
- }, function() {
- hovering = false;
- if (!post) {
- return;
- }
+ updatePreviewPosition(e.pageX, e.pageY, hoverPreview);
+ });
+ };
- post.removeClass('highlighted');
- if (post.hasClass('hidden') || post.data('cached') == 'yes') {
- post.css('display', 'none');
- }
- $('.post-hover').remove();
- }).mousemove(function(e) {
- if (!post) {
- return;
- }
+ $('div.body a:not([rel="nofollow"])').each(initHover);
- let hover = $('#post-hover-' + id + '[data-board="' + board + '"]');
- if (hover.length == 0) {
- return;
- }
-
- let scrollTop = $(window).scrollTop();
- if (link.is("[data-thread]")) {
- scrollTop = 0;
- }
- let epy = e.pageY;
- if (link.is("[data-thread]")) {
- epy -= $(window).scrollTop();
- }
-
- let top = (epy ? epy : hoveredAt['y']) - 10;
-
- if (epy < scrollTop + 15) {
- top = scrollTop;
- } else if (epy > scrollTop + $(window).height() - hover.height() - 15) {
- top = scrollTop + $(window).height() - hover.height() - 15;
- }
-
- hover.css('left', (e.pageX ? e.pageX : hoveredAt['x'])).css('top', top);
+ // allow to work with auto-reload.js, etc.
+ $(document).on('new_post', function(e, post) {
+ $(post).find('div.body a:not([rel="nofollow"])').each(initHover);
});
- };
-
- $('div.body a:not([rel="nofollow"])').each(initHover);
-
- // allow to work with auto-reload.js, etc.
- $(document).on('new_post', function(e, post) {
- $(post).find('div.body a:not([rel="nofollow"])').each(initHover);
});
-});
+}
diff --git a/js/post-menu.js b/js/post-menu.js
index 6018dfdb..e6701e5b 100644
--- a/js/post-menu.js
+++ b/js/post-menu.js
@@ -21,7 +21,7 @@
* submenu = Menu.add_submenu('filter-menu-add', 'Add filter');
* submenu.add_item('filter-add-post-plus', 'Post +', 'Hide post and all replies');
* submenu.add_item('filter-add-id', 'ID');
- *
+ *
* Usage:
* $config['additional_javascript'][] = 'js/jquery.min.js';
* $config['additional_javascript'][] = 'js/post-menu.js';
@@ -163,7 +163,7 @@ cssString =
'.post-menu li:hover>ul {display: block; left: 100%; margin-top: -3px;}\n' +
'.post-menu-arrow {float: right; margin-left: 10px;}\n' +
'.post-menu.hidden, .post-menu .hidden {display: none;}\n' +
- '.post-btn {transition: transform 0.1s; width: 15px; text-align: center; font-size: 10pt; opacity: 0.8; text-decoration: none; margin: -6px 0px 0px -5px !important; display: inline-block;}\n' +
+ '.post-btn {transition: transform 0.1s; width: 15px; text-align: center; font-size: 10pt; opacity: 0.8; text-decoration: none; margin: -6px 0px 0px 0px !important; display: inline-block;}\n' +
'.post-btn:hover {opacity: 1;}\n' +
'.post-btn-open {transform: rotate(90deg);}\n';
diff --git a/js/quick-post-controls.js b/js/quick-post-controls.js
index c625fa85..f842f02d 100644
--- a/js/quick-post-controls.js
+++ b/js/quick-post-controls.js
@@ -14,19 +14,17 @@
$(document).ready(function() {
let open_form = function() {
- let thread = $(this).parent().parent().hasClass('op');
let id = $(this).attr('name').match(/^delete_(\d+)$/)[1];
if (this.checked) {
let post_form = $('