diff --git a/inc/bans.php b/inc/bans.php
index cf24f097..d860c02c 100644
--- a/inc/bans.php
+++ b/inc/bans.php
@@ -253,7 +253,7 @@ class Bans {
modLog('Created a new ' .
($length > 0 ? preg_replace('/^(\d+) (\w+?)s?$/', '$1-$2', until($length)) : 'permanent') .
' ban on ' .
- ($board ? '/' . $board . '/' : 'all boards') .
+ ($ban_board ? '/' . $ban_board . '/' : 'all boards') .
' for ' .
(filter_var($mask, FILTER_VALIDATE_IP) !== false ? "$mask " : $mask) .
' (#' . $pdo->lastInsertId() . ' )' .
diff --git a/js/ajax.js b/js/ajax.js
index ee2ff7b5..8f0f7258 100644
--- a/js/ajax.js
+++ b/js/ajax.js
@@ -12,6 +12,7 @@
*/
$(window).ready(function() {
+ var settings = new script_settings('ajax');
var do_not_ajax = false;
var setup_form = function($form) {
@@ -68,7 +69,8 @@ $(window).ready(function() {
$(form).find('input[type="submit"]').removeAttr('disabled');
}
} else if (post_response.redirect && post_response.id) {
- if (!$(form).find('input[name="thread"]').length) {
+ if (!$(form).find('input[name="thread"]').length
+ || (!settings.get('always_noko_replies', true) && !post_response.noko)) {
document.location = post_response.redirect;
} else {
$.ajax({
diff --git a/js/quick-reply.js b/js/quick-reply.js
index b87b5050..19977b1d 100644
--- a/js/quick-reply.js
+++ b/js/quick-reply.js
@@ -12,361 +12,418 @@
*
*/
-var do_css = function() {
- $('#quick-reply-css').remove();
+(function() {
+ var settings = new script_settings('quick-reply');
- // Find background of reply posts
- var dummy_reply = $('
').appendTo($('body'));
- var reply_background = dummy_reply.css('backgroundColor');
- var reply_border_style = dummy_reply.css('borderStyle');
- var reply_border_color = dummy_reply.css('borderColor');
- var reply_border_width = dummy_reply.css('borderWidth');
- dummy_reply.remove();
-
- $('').appendTo($('head'));
-};
-
-var show_quick_reply = function(){
- if($('div.banner').length == 0)
- return;
- if($('#quick-reply').length != 0)
- return;
+ #quick-reply table {\
+ border-collapse: collapse;\
+ background: ' + reply_background + ';\
+ border-style: ' + reply_border_style + ';\
+ border-width: ' + reply_border_width + ';\
+ border-color: ' + reply_border_color + ';\
+ margin: 0;\
+ width: 100%;\
+ }\
+ #quick-reply tr td:nth-child(2) {\
+ white-space: nowrap;\
+ text-align: right;\
+ padding-right: 4px;\
+ }\
+ #quick-reply tr td:nth-child(2) input[type="submit"] {\
+ width: 100%;\
+ }\
+ #quick-reply th, #quick-reply td {\
+ margin: 0;\
+ padding: 0;\
+ }\
+ #quick-reply th {\
+ text-align: center;\
+ padding: 2px 0;\
+ border: 1px solid #222;\
+ }\
+ #quick-reply th .handle {\
+ float: left;\
+ width: 100%;\
+ display: inline-block;\
+ }\
+ #quick-reply th .close-btn {\
+ float: right;\
+ padding: 0 5px;\
+ }\
+ #quick-reply input[type="text"], #quick-reply select {\
+ width: 100%;\
+ padding: 2px;\
+ font-size: 10pt;\
+ box-sizing: border-box;\
+ -webkit-box-sizing:border-box;\
+ -moz-box-sizing: border-box;\
+ }\
+ #quick-reply textarea {\
+ width: 100%;\
+ box-sizing: border-box;\
+ -webkit-box-sizing:border-box;\
+ -moz-box-sizing: border-box;\
+ font-size: 10pt;\
+ resize: vertical;\
+ }\
+ #quick-reply input, #quick-reply select, #quick-reply textarea {\
+ margin: 0 0 1px 0;\
+ }\
+ #quick-reply input[type="file"] {\
+ padding: 5px 2px;\
+ }\
+ #quick-reply .nonsense {\
+ display: none;\
+ }\
+ #quick-reply td.submit {\
+ width: 1%;\
+ }\
+ #quick-reply td.recaptcha {\
+ text-align: center;\
+ padding: 0 0 1px 0;\
+ }\
+ #quick-reply td.recaptcha span {\
+ display: inline-block;\
+ width: 100%;\
+ background: white;\
+ border: 1px solid #ccc;\
+ cursor: pointer;\
+ }\
+ #quick-reply td.recaptcha-response {\
+ padding: 0 0 1px 0;\
+ }\
+ @media screen and (max-width: 800px) {\
+ #quick-reply {\
+ display: none !important;\
+ }\
+ }\
+ ').appendTo($('head'));
+ };
- do_css();
+ var show_quick_reply = function(){
+ if($('div.banner').length == 0)
+ return;
+ if($('#quick-reply').length != 0)
+ return;
+
+ do_css();
+
+ var $postForm = $('form[name="post"]').clone();
+
+ $postForm.clone();
+
+ $dummyStuff = $('
').appendTo($postForm);
+
+ $postForm.find('table tr').each(function() {
+ var $th = $(this).children('th:first');
+ var $td = $(this).children('td:first');
+ if ($th.length && $td.length) {
+ $td.attr('colspan', 2);
- var $postForm = $('form[name="post"]').clone();
-
- $postForm.clone();
-
- $dummyStuff = $('
').appendTo($postForm);
-
- $postForm.find('table tr').each(function() {
- var $th = $(this).children('th:first');
- var $td = $(this).children('td:first');
- if ($th.length && $td.length) {
- $td.attr('colspan', 2);
-
- if ($td.find('input[type="text"]').length) {
- // Replace with input placeholders
- $td.find('input[type="text"]')
- .removeAttr('size')
- .attr('placeholder', $th.clone().children().remove().end().text());
- }
-
- // Move anti-spam nonsense and remove
- $th.contents().filter(function() {
- return this.nodeType == 3; // Node.TEXT_NODE
- }).remove();
- $th.contents().appendTo($dummyStuff);
- $th.remove();
-
- if ($td.find('input[name="password"]').length) {
- // Hide password field
- $(this).hide();
- }
-
- // Fix submit button
- if ($td.find('input[type="submit"]').length) {
- $td.removeAttr('colspan');
- $(' ').append($td.find('input[type="submit"]')).insertAfter($td);
- }
-
- // reCAPTCHA
- if ($td.find('#recaptcha_widget_div').length) {
- // Just show the image, and have it interact with the real form.
- var $captchaimg = $td.find('#recaptcha_image img');
-
- $captchaimg
- .removeAttr('id')
- .removeAttr('style')
- .addClass('recaptcha_image')
- .click(function() {
- $('#recaptcha_reload').click();
- });
-
- // When we get a new captcha...
- $('#recaptcha_response_field').focus(function() {
- if ($captchaimg.attr('src') != $('#recaptcha_image img').attr('src')) {
- $captchaimg.attr('src', $('#recaptcha_image img').attr('src'));
- $postForm.find('input[name="recaptcha_challenge_field"]').val($('#recaptcha_challenge_field').val());
- $postForm.find('input[name="recaptcha_response_field"]').val('').focus();
- }
- });
-
- $postForm.submit(function() {
- setTimeout(function() {
- $('#recaptcha_reload').click();
- }, 200);
- });
-
- // Make a new row for the response text
- var $newRow = $(' ');
- $newRow.children().first().append(
- $td.find('input').removeAttr('style')
- );
- $newRow.find('#recaptcha_response_field')
- .removeAttr('id')
- .addClass('recaptcha_response_field')
- .attr('placeholder', $('#recaptcha_response_field').attr('placeholder'));
-
- $('#recaptcha_response_field').addClass('recaptcha_response_field')
-
- $td.replaceWith($(' ').append($(' ').append($captchaimg)));
-
- $newRow.insertAfter(this);
- }
-
- // Upload section
- if ($td.find('input[type="file"]').length) {
- if ($td.find('input[name="file_url"]').length) {
- $file_url = $td.find('input[name="file_url"]');
-
- // Make a new row for it
- var $newRow = $(' ');
-
- $file_url.clone().attr('placeholder', _('Upload URL')).appendTo($newRow.find('td'));
- $file_url.parent().remove();
-
- $newRow.insertBefore(this);
-
- $td.find('label').remove();
- $td.contents().filter(function() {
- return this.nodeType == 3; // Node.TEXT_NODE
- }).remove();
- $td.find('input[name="file_url"]').removeAttr('id');
+ if ($td.find('input[type="text"]').length) {
+ // Replace with input placeholders
+ $td.find('input[type="text"]')
+ .removeAttr('size')
+ .attr('placeholder', $th.clone().children().remove().end().text());
}
-
- if ($(this).find('input[name="spoiler"]').length) {
+
+ // Move anti-spam nonsense and remove
+ $th.contents().filter(function() {
+ return this.nodeType == 3; // Node.TEXT_NODE
+ }).remove();
+ $th.contents().appendTo($dummyStuff);
+ $th.remove();
+
+ if ($td.find('input[name="password"]').length) {
+ // Hide password field
+ $(this).hide();
+ }
+
+ // Fix submit button
+ if ($td.find('input[type="submit"]').length) {
$td.removeAttr('colspan');
+ $(' ').append($td.find('input[type="submit"]')).insertAfter($td);
}
- }
-
- // Remove oekaki if existent
- if ($(this).is('#oekaki')) {
- $(this).remove();
- }
-
- // Remove mod controls, because it looks shit.
- if ($td.find('input[type="checkbox"]').length) {
- var tr = this;
- $td.find('input[type="checkbox"]').each(function() {
- if ($(this).attr('name') == 'spoiler') {
+
+ // reCAPTCHA
+ if ($td.find('#recaptcha_widget_div').length) {
+ // Just show the image, and have it interact with the real form.
+ var $captchaimg = $td.find('#recaptcha_image img');
+
+ $captchaimg
+ .removeAttr('id')
+ .removeAttr('style')
+ .addClass('recaptcha_image')
+ .click(function() {
+ $('#recaptcha_reload').click();
+ });
+
+ // When we get a new captcha...
+ $('#recaptcha_response_field').focus(function() {
+ if ($captchaimg.attr('src') != $('#recaptcha_image img').attr('src')) {
+ $captchaimg.attr('src', $('#recaptcha_image img').attr('src'));
+ $postForm.find('input[name="recaptcha_challenge_field"]').val($('#recaptcha_challenge_field').val());
+ $postForm.find('input[name="recaptcha_response_field"]').val('').focus();
+ }
+ });
+
+ $postForm.submit(function() {
+ setTimeout(function() {
+ $('#recaptcha_reload').click();
+ }, 200);
+ });
+
+ // Make a new row for the response text
+ var $newRow = $(' ');
+ $newRow.children().first().append(
+ $td.find('input').removeAttr('style')
+ );
+ $newRow.find('#recaptcha_response_field')
+ .removeAttr('id')
+ .addClass('recaptcha_response_field')
+ .attr('placeholder', $('#recaptcha_response_field').attr('placeholder'));
+
+ $('#recaptcha_response_field').addClass('recaptcha_response_field')
+
+ $td.replaceWith($(' ').append($(' ').append($captchaimg)));
+
+ $newRow.insertAfter(this);
+ }
+
+ // Upload section
+ if ($td.find('input[type="file"]').length) {
+ if ($td.find('input[name="file_url"]').length) {
+ $file_url = $td.find('input[name="file_url"]');
+
+ // Make a new row for it
+ var $newRow = $(' ');
+
+ $file_url.clone().attr('placeholder', _('Upload URL')).appendTo($newRow.find('td'));
+ $file_url.parent().remove();
+
+ $newRow.insertBefore(this);
+
$td.find('label').remove();
- $(this).attr('id', 'q-spoiler-image');
- $postForm.find('input[type="file"]').parent()
- .removeAttr('colspan')
- .after($(' ').append(this, ' ', $('').text(_('Spoiler Image'))));
- } else {
- $(tr).remove();
+ $td.contents().filter(function() {
+ return this.nodeType == 3; // Node.TEXT_NODE
+ }).remove();
+ $td.find('input[name="file_url"]').removeAttr('id');
}
- });
+
+ if ($(this).find('input[name="spoiler"]').length) {
+ $td.removeAttr('colspan');
+ }
+ }
+
+ // Remove oekaki if existent
+ if ($(this).is('#oekaki')) {
+ $(this).remove();
+ }
+
+ // Remove mod controls, because it looks shit.
+ if ($td.find('input[type="checkbox"]').length) {
+ var tr = this;
+ $td.find('input[type="checkbox"]').each(function() {
+ if ($(this).attr('name') == 'spoiler') {
+ $td.find('label').remove();
+ $(this).attr('id', 'q-spoiler-image');
+ $postForm.find('input[type="file"]').parent()
+ .removeAttr('colspan')
+ .after($(' ').append(this, ' ', $('').text(_('Spoiler Image'))));
+ } else {
+ $(tr).remove();
+ }
+ });
+ }
+
+ $td.find('small').hide();
+ }
+ });
+
+ $postForm.find('textarea[name="body"]').removeAttr('id').removeAttr('cols').attr('placeholder', _('Comment'));
+
+ $postForm.find('textarea:not([name="body"]),input[type="hidden"]').removeAttr('id').appendTo($dummyStuff);
+
+ $postForm.find('br').remove();
+ $postForm.find('table').prepend('\
+ \
+ X \
+ ' + _('Quick Reply') + '\
+ \
+ ');
+
+ $postForm.attr('id', 'quick-reply');
+
+ $postForm.appendTo($('body')).hide();
+ $origPostForm = $('form[name="post"]:first');
+
+ // Synchronise body text with original post form
+ $origPostForm.find('textarea[name="body"]').bind('change input propertychange', function() {
+ $postForm.find('textarea[name="body"]').val($(this).val());
+ });
+ $postForm.find('textarea[name="body"]').bind('change input propertychange', function() {
+ $origPostForm.find('textarea[name="body"]').val($(this).val());
+ });
+ $postForm.find('textarea[name="body"]').focus(function() {
+ $origPostForm.find('textarea[name="body"]').removeAttr('id');
+ $(this).attr('id', 'body');
+ });
+ $origPostForm.find('textarea[name="body"]').focus(function() {
+ $postForm.find('textarea[name="body"]').removeAttr('id');
+ $(this).attr('id', 'body');
+ });
+ // Synchronise other inputs
+ $origPostForm.find('input[type="text"],select').bind('change input propertychange', function() {
+ $postForm.find('[name="' + $(this).attr('name') + '"]').val($(this).val());
+ });
+ $postForm.find('input[type="text"],select').bind('change input propertychange', function() {
+ $origPostForm.find('[name="' + $(this).attr('name') + '"]').val($(this).val());
+ });
+
+ if (typeof $postForm.draggable != 'undefined') {
+ if (localStorage.quickReplyPosition) {
+ var offset = JSON.parse(localStorage.quickReplyPosition);
+ if (offset.top < 0)
+ offset.top = 0;
+ if (offset.right > $(window).width() - $postForm.width())
+ offset.right = $(window).width() - $postForm.width();
+ if (offset.top > $(window).height() - $postForm.height())
+ offset.top = $(window).height() - $postForm.height();
+ $postForm.css('right', offset.right).css('top', offset.top);
+ }
+ $postForm.draggable({
+ handle: 'th .handle',
+ containment: 'window',
+ distance: 10,
+ scroll: false,
+ stop: function() {
+ var offset = {
+ top: $(this).offset().top - $(window).scrollTop(),
+ right: $(window).width() - $(this).offset().left - $(this).width(),
+ };
+ localStorage.quickReplyPosition = JSON.stringify(offset);
+
+ $postForm.css('right', offset.right).css('top', offset.top).css('left', 'auto');
+ }
+ });
+ $postForm.find('th .handle').css('cursor', 'move');
+ }
+
+ $postForm.find('th .close-btn').click(function() {
+ $origPostForm.find('textarea[name="body"]').attr('id', 'body');
+ $postForm.remove();
+ floating_link();
+ });
+
+ // Fix bug when table gets too big for form. Shouldn't exist, but crappy CSS etc.
+ $postForm.show();
+ $postForm.width($postForm.find('table').width());
+ $postForm.hide();
+
+ $(window).trigger('quick-reply');
+
+ $(window).ready(function() {
+ if (settings.get('hide_at_top', true)) {
+ $(window).scroll(function() {
+ if ($(this).width() <= 800)
+ return;
+ if ($(this).scrollTop() < $origPostForm.offset().top + $origPostForm.height() - 100)
+ $postForm.fadeOut(100);
+ else
+ $postForm.fadeIn(100);
+ }).scroll();
+ } else {
+ $postForm.show();
}
- $td.find('small').hide();
- }
- });
-
- $postForm.find('textarea[name="body"]').removeAttr('id').removeAttr('cols').attr('placeholder', _('Comment'));
-
- $postForm.find('textarea:not([name="body"]),input[type="hidden"]').removeAttr('id').appendTo($dummyStuff);
-
- $postForm.find('br').remove();
- $postForm.find('table').prepend('\
- \
- X \
- ' + _('Quick Reply') + '\
- \
- ');
-
- $postForm.attr('id', 'quick-reply');
-
- $postForm.appendTo($('body')).hide();
- $origPostForm = $('form[name="post"]:first');
-
- // Synchronise body text with original post form
- $origPostForm.find('textarea[name="body"]').bind('change input propertychange', function() {
- $postForm.find('textarea[name="body"]').val($(this).val());
- });
- $postForm.find('textarea[name="body"]').bind('change input propertychange', function() {
- $origPostForm.find('textarea[name="body"]').val($(this).val());
- });
- $postForm.find('textarea[name="body"]').focus(function() {
- $origPostForm.find('textarea[name="body"]').removeAttr('id');
- $(this).attr('id', 'body');
- });
- $origPostForm.find('textarea[name="body"]').focus(function() {
- $postForm.find('textarea[name="body"]').removeAttr('id');
- $(this).attr('id', 'body');
- });
- // Synchronise other inputs
- $origPostForm.find('input[type="text"],select').bind('change input propertychange', function() {
- $postForm.find('[name="' + $(this).attr('name') + '"]').val($(this).val());
- });
- $postForm.find('input[type="text"],select').bind('change input propertychange', function() {
- $origPostForm.find('[name="' + $(this).attr('name') + '"]').val($(this).val());
- });
-
- if (typeof $postForm.draggable != 'undefined') {
- if (localStorage.quickReplyPosition) {
- var offset = JSON.parse(localStorage.quickReplyPosition);
- if (offset.top < 0)
- offset.top = 10;
- if (offset.right > $(window).width() - $postForm.width())
- offset.right = $(window).width() - $postForm.width();
- if (offset.top > $(window).height() - $postForm.height())
- offset.top = $(window).height() - $postForm.height();
- $postForm.css('right', offset.right).css('top', offset.top);
- }
- $postForm.draggable({
- handle: 'th .handle',
- containment: 'window',
- distance: 10,
- scroll: false,
- stop: function() {
- var offset = {
- top: $(this).offset().top - $(window).scrollTop(),
- right: $(window).width() - $(this).offset().left - $(this).width(),
- };
- localStorage.quickReplyPosition = JSON.stringify(offset);
-
- $postForm.css('right', offset.right).css('top', offset.top).css('left', 'auto');
- }
+ $(window).on('stylesheet', function() {
+ do_css();
+ if ($('link#stylesheet').attr('href')) {
+ $('link#stylesheet')[0].onload = do_css;
+ }
+ });
});
- $postForm.find('th .handle').css('cursor', 'move');
- }
+ };
- $postForm.find('th .close-btn').click(function() {
- $origPostForm.find('textarea[name="body"]').attr('id', 'body');
- $postForm.remove();
+ $(window).on('cite', function(e, id, with_link) {
+ if ($(this).width() <= 800)
+ return;
+ show_quick_reply();
+ $('#quick-reply textarea').focus();
+ if (with_link) {
+ $(window).ready(function() {
+ if ($('#' + id).length) {
+ highlightReply(id);
+ $(window).scrollTop($('#' + id).offset().top);
+ }
+ });
+ }
});
- // Fix bug when table gets too big for form. Shouldn't exist, but crappy CSS etc.
- $postForm.show();
- $postForm.width($postForm.find('table').width());
- $postForm.hide();
+ var floating_link = function() {
+ if (!settings.get('floating_link', false))
+ return;
+ $('Quick Reply ')
+ .click(function() {
+ show_quick_reply();
+ $(this).remove();
+ }).prependTo($('body'));
+
+ $(window).on('quick-reply', function() {
+ $('.quick-reply-btn').remove();
+ });
+ };
- $(window).trigger('quick-reply');
-
- $(window).ready(function() {
- $(window).scroll(function() {
- if ($(this).width() <= 800)
- return;
- if ($(this).scrollTop() < $origPostForm.offset().top + $origPostForm.height() - 100)
- $postForm.fadeOut(100);
- else
- $postForm.fadeIn(100);
- }).on('stylesheet', function() {
- do_css();
- if ($('link#stylesheet').attr('href')) {
- $('link#stylesheet')[0].onload = do_css;
- }
- }).scroll();
- });
-};
-
-$(window).on('cite', function(e, id, with_link) {
- if ($(this).width() <= 800)
- return;
- show_quick_reply();
- $('#quick-reply textarea').focus();
- if (with_link) {
+ if (settings.get('floating_link', false)) {
$(window).ready(function() {
- if ($('#' + id).length) {
- highlightReply(id);
- $(window).scrollTop($('#' + id).offset().top);
+ if($('div.banner').length == 0)
+ return;
+ $('').appendTo($('head'));
+
+ floating_link();
+
+ if (settings.get('hide_at_top', true)) {
+ $('.quick-reply-btn').hide();
+
+ $(window).scroll(function() {
+ if ($(this).width() <= 800)
+ return;
+ if ($(this).scrollTop() < $('form[name="post"]:first').offset().top + $('form[name="post"]:first').height() - 100)
+ $('.quick-reply-btn').fadeOut(100);
+ else
+ $('.quick-reply-btn').fadeIn(100);
+ }).scroll();
}
});
}
-});
+})();
diff --git a/js/settings.js b/js/settings.js
new file mode 100644
index 00000000..e98b35ae
--- /dev/null
+++ b/js/settings.js
@@ -0,0 +1,40 @@
+/*
+* settings.js
+* https://github.com/savetheinternet/Tinyboard/blob/master/js/settings.js
+*
+* Optional settings. Used to customize some scripts without needing to tweak their code.
+* Notes:
+* - You must include this script first.
+* - This file is just an example.
+* - You should copy settings.js to something like instance.settings.js to prevent conflicts when upgrading.
+* - This file should always be optional.
+*
+* Released under the MIT license
+* Copyright (c) 2013 Michael Save
+*
+* Usage:
+* $config['additional_javascript'][] = 'js/jquery.min.js';
+* $config['additional_javascript'][] = 'js/instance.settings.js';
+* // $config['additional_javascript'][] = 'js/quick-reply.js';
+*
+* Usage in scripts:
+* var settings = new script_settings('my-script');
+* var some_value = settings.get('option', 'default value');
+*
+*/
+
+var tb_settings = {};
+
+// quick-reply.js
+tb_settings['quick-reply'] = {
+ // Hide form when scrolled to top of page (where original form is visible)
+ hide_at_top: true,
+ // "Quick reply" button floating at the top right hand corner of the page at all times
+ floating_link: true
+};
+
+// ajax.js
+tb_settings['ajax'] = {
+ // Always act as if "noko" was typed when posting replies with the ajax script
+ always_noko_replies: false
+};
diff --git a/post.php b/post.php
index f7789e59..556de639 100644
--- a/post.php
+++ b/post.php
@@ -775,6 +775,7 @@ if (isset($_POST['delete'])) {
header('Content-Type: text/json; charset=utf-8');
echo json_encode(array(
'redirect' => $redirect,
+ 'noko' => $config['always_noko'] || $noko,
'id' => $id
));
}
diff --git a/templates/main.js b/templates/main.js
index 6136b11f..52c06cea 100644
--- a/templates/main.js
+++ b/templates/main.js
@@ -249,6 +249,17 @@ function rememberStuff() {
}
}
+var script_settings = function(script_name) {
+ this.script_name = script_name;
+ this.get = function(var_name, default_val) {
+ if (typeof tb_settings == 'undefined' ||
+ typeof tb_settings[this.script_name] == 'undefined' ||
+ typeof tb_settings[this.script_name][var_name] == 'undefined')
+ return default_val;
+ return tb_settings[this.script_name][var_name];
+ }
+};
+
function init() {
init_stylechooser();