Benjamin Southall
8 years ago
114 changed files with 5568 additions and 886 deletions
@ -1,3 +1,9 @@ |
|||||
[submodule "js/wPaint"] |
[submodule "js/wPaint"] |
||||
path = js/wPaint |
path = js/wPaint |
||||
url = https://github.com/vichan-devel/wPaint.git |
url = https://github.com/vichan-devel/wPaint.git |
||||
|
branch = master |
||||
|
|
||||
|
[submodule "inc/lib/parsedown"] |
||||
|
path = inc/lib/parsedown |
||||
|
url = https://github.com/vichan-devel/parsedown |
||||
|
branch = master |
||||
|
@ -0,0 +1,108 @@ |
|||||
|
<?php |
||||
|
|
||||
|
// This file contains the controller part of vichan |
||||
|
|
||||
|
// don't bother with that unless you use smart build or advanced build |
||||
|
// you can use those parts for your own implementations though :^) |
||||
|
|
||||
|
defined('TINYBOARD') or exit; |
||||
|
|
||||
|
function sb_board($b, $page = 1) { global $config, $build_pages; $page = (int)$page; |
||||
|
if ($page < 1) return false; |
||||
|
if (!openBoard($b)) return false; |
||||
|
if ($page > $config['max_pages']) return false; |
||||
|
$config['try_smarter'] = true; |
||||
|
$build_pages = array($page); |
||||
|
buildIndex("skip"); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
function sb_api_board($b, $page = 0) { $page = (int)$page; |
||||
|
return sb_board($b, $page + 1); |
||||
|
} |
||||
|
|
||||
|
function sb_thread($b, $thread, $slugcheck = false) { global $config; $thread = (int)$thread; |
||||
|
if ($thread < 1) return false; |
||||
|
|
||||
|
if (!preg_match('/^'.$config['board_regex'].'$/u', $b)) return false; |
||||
|
|
||||
|
if (Cache::get("thread_exists_".$b."_".$thread) == "no") return false; |
||||
|
|
||||
|
$query = prepare(sprintf("SELECT MAX(`id`) AS `max` FROM ``posts_%s``", $b)); |
||||
|
if (!$query->execute()) return false; |
||||
|
|
||||
|
$s = $query->fetch(PDO::FETCH_ASSOC); |
||||
|
$max = $s['max']; |
||||
|
|
||||
|
if ($thread > $max) return false; |
||||
|
|
||||
|
$query = prepare(sprintf("SELECT `id` FROM ``posts_%s`` WHERE `id` = :id AND `thread` IS NULL", $b)); |
||||
|
$query->bindValue(':id', $thread); |
||||
|
|
||||
|
if (!$query->execute() || !$query->fetch(PDO::FETCH_ASSOC) ) { |
||||
|
Cache::set("thread_exists_".$b."_".$thread, "no", 3600); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if ($slugcheck && $config['slugify']) { |
||||
|
global $request; |
||||
|
|
||||
|
$link = link_for(array("id" => $thread), $slugcheck === 50, array("uri" => $b)); |
||||
|
$link = "/".$b."/".$config['dir']['res'].$link; |
||||
|
|
||||
|
if ($link != $request) { |
||||
|
header("Location: $link", true, 301); |
||||
|
die(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if ($slugcheck == 50) { // Should we really generate +50 page? Maybe there are not enough posts anyway |
||||
|
global $request; |
||||
|
$r = str_replace("+50", "", $request); |
||||
|
$r = substr($r, 1); // Cut the slash |
||||
|
|
||||
|
if (file_exists($r)) return false; |
||||
|
} |
||||
|
|
||||
|
if (!openBoard($b)) return false; |
||||
|
buildThread($thread); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
function sb_thread_slugcheck($b, $thread) { |
||||
|
return sb_thread($b, $thread, true); |
||||
|
} |
||||
|
function sb_thread_slugcheck50($b, $thread) { |
||||
|
return sb_thread($b, $thread, 50); |
||||
|
} |
||||
|
|
||||
|
function sb_api($b) { global $config, $build_pages; |
||||
|
if (!openBoard($b)) return false; |
||||
|
$config['try_smarter'] = true; |
||||
|
$build_pages = array(-1); |
||||
|
buildIndex(); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
function sb_ukko() { |
||||
|
rebuildTheme("ukko", "post-thread"); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
function sb_catalog($b) { |
||||
|
if (!openBoard($b)) return false; |
||||
|
|
||||
|
rebuildTheme("catalog", "post-thread", $b); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
function sb_recent() { |
||||
|
rebuildTheme("recent", "post-thread"); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
function sb_sitemap() { |
||||
|
rebuildTheme("sitemap", "all"); |
||||
|
return true; |
||||
|
} |
||||
|
|
@ -0,0 +1,39 @@ |
|||||
|
<?php |
||||
|
class Lock { |
||||
|
function __construct($key) { global $config; |
||||
|
if ($config['lock']['enabled'] == 'fs') { |
||||
|
$key = str_replace('/', '::', $key); |
||||
|
$key = str_replace("\0", '', $key); |
||||
|
|
||||
|
$this->f = fopen("tmp/locks/$key", "w"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Get a shared lock |
||||
|
function get($nonblock = false) { global $config; |
||||
|
if ($config['lock']['enabled'] == 'fs') { |
||||
|
$wouldblock = false; |
||||
|
flock($this->f, LOCK_SH | ($nonblock ? LOCK_NB : 0), $wouldblock); |
||||
|
if ($nonblock && $wouldblock) return false; |
||||
|
} |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
// Get an exclusive lock |
||||
|
function get_ex($nonblock = false) { global $config; |
||||
|
if ($config['lock']['enabled'] == 'fs') { |
||||
|
$wouldblock = false; |
||||
|
flock($this->f, LOCK_EX | ($nonblock ? LOCK_NB : 0), $wouldblock); |
||||
|
if ($nonblock && $wouldblock) return false; |
||||
|
} |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
// Free a lock |
||||
|
function free() { global $config; |
||||
|
if ($config['lock']['enabled'] == 'fs') { |
||||
|
flock($this->f, LOCK_UN); |
||||
|
} |
||||
|
return $this; |
||||
|
} |
||||
|
} |
@ -0,0 +1,152 @@ |
|||||
|
<?php |
||||
|
/* |
||||
|
* Copyright (c) 2016 vichan-devel |
||||
|
*/ |
||||
|
|
||||
|
defined('TINYBOARD') or exit; |
||||
|
|
||||
|
function gen_msgid($board, $id) { |
||||
|
global $config; |
||||
|
|
||||
|
$b = preg_replace("/[^0-9a-zA-Z$]/", 'x', $board); |
||||
|
$salt = sha1($board . "|" . $id . "|" . $config['nntpchan']['salt']); |
||||
|
$salt = substr($salt, 0, 7); |
||||
|
$salt = base_convert($salt, 16, 36); |
||||
|
|
||||
|
return "<$b.$id.$salt@".$config['nntpchan']['domain'].">"; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
function gen_nntp($headers, $files) { |
||||
|
if (count($files) == 0) { |
||||
|
} |
||||
|
else if (count($files) == 1 && $files[0]['type'] == 'text/plain') { |
||||
|
$content = $files[0]['text'] . "\r\n"; |
||||
|
$headers['Content-Type'] = "text/plain; charset=UTF-8"; |
||||
|
} |
||||
|
else { |
||||
|
$boundary = sha1($headers['Message-Id']); |
||||
|
$content = ""; |
||||
|
$headers['Content-Type'] = "multipart/mixed; boundary=$boundary"; |
||||
|
foreach ($files as $file) { |
||||
|
$content .= "--$boundary\r\n"; |
||||
|
if (isset($file['name'])) { |
||||
|
$file['name'] = preg_replace('/[\r\n\0"]/', '', $file['name']); |
||||
|
$content .= "Content-Disposition: form-data; filename=\"$file[name]\"; name=\"attachment\"\r\n"; |
||||
|
} |
||||
|
$type = explode('/', $file['type'])[0]; |
||||
|
if ($type == 'text') { |
||||
|
$file['type'] .= '; charset=UTF-8'; |
||||
|
} |
||||
|
$content .= "Content-Type: $file[type]\r\n"; |
||||
|
if ($type != 'text' && $type != 'message') { |
||||
|
$file['text'] = base64_encode($file['text']); |
||||
|
$content .= "Content-Transfer-Encoding: base64\r\n"; |
||||
|
} |
||||
|
$content .= "\r\n"; |
||||
|
$content .= $file['text']; |
||||
|
$content .= "\r\n"; |
||||
|
} |
||||
|
$content .= "--$boundary--\r\n"; |
||||
|
|
||||
|
$headers['Mime-Version'] = '1.0'; |
||||
|
} |
||||
|
//$headers['Content-Length'] = strlen($content); |
||||
|
$headers['Date'] = date('r', $headers['Date']); |
||||
|
$out = ""; |
||||
|
foreach ($headers as $id => $val) { |
||||
|
$val = str_replace("\n", "\n\t", $val); |
||||
|
$out .= "$id: $val\r\n"; |
||||
|
} |
||||
|
$out .= "\r\n"; |
||||
|
$out .= $content; |
||||
|
return $out; |
||||
|
} |
||||
|
|
||||
|
function nntp_publish($msg, $id) { |
||||
|
global $config; |
||||
|
$server = $config["nntpchan"]["server"]; |
||||
|
$s = fsockopen("tcp://$server"); |
||||
|
fgets($s); |
||||
|
fputs($s, "MODE STREAM\r\n"); |
||||
|
fgets($s); |
||||
|
fputs($s, "TAKETHIS $id\r\n"); |
||||
|
fputs($s, $msg); |
||||
|
fputs($s, "\r\n.\r\n"); |
||||
|
fgets($s); |
||||
|
fputs($s, "QUIT\r\n"); |
||||
|
fclose($s); |
||||
|
} |
||||
|
|
||||
|
function post2nntp($post, $msgid) { |
||||
|
global $config; |
||||
|
|
||||
|
$headers = array(); |
||||
|
$files = array(); |
||||
|
|
||||
|
$headers['Message-Id'] = $msgid; |
||||
|
$headers['Newsgroups'] = $config['nntpchan']['group']; |
||||
|
$headers['Date'] = time(); |
||||
|
$headers['Subject'] = $post['subject'] ? $post['subject'] : "None"; |
||||
|
$headers['From'] = $post['name'] . " <poster@" . $config['nntpchan']['domain'] . ">"; |
||||
|
|
||||
|
if ($post['email'] == 'sage') { |
||||
|
$headers['X-Sage'] = true; |
||||
|
} |
||||
|
|
||||
|
if (!$post['op']) { |
||||
|
// Get muh parent |
||||
|
$query = prepare("SELECT `message_id` FROM ``nntp_references`` WHERE `board` = :board AND `id` = :id"); |
||||
|
$query->bindValue(':board', $post['board']); |
||||
|
$query->bindValue(':id', $post['thread']); |
||||
|
$query->execute() or error(db_error($query)); |
||||
|
|
||||
|
if ($result = $query->fetch(PDO::FETCH_ASSOC)) { |
||||
|
$headers['References'] = $result['message_id']; |
||||
|
} |
||||
|
else { |
||||
|
return false; // We don't have OP. Discarding. |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Let's parse the body a bit. |
||||
|
$body = trim($post['body_nomarkup']); |
||||
|
$body = preg_replace('/\r?\n/', "\r\n", $body); |
||||
|
$body = preg_replace_callback('@>>(>/([a-zA-Z0-9_+-]+)/)?([0-9]+)@', function($o) use ($post) { |
||||
|
if ($o[1]) { |
||||
|
$board = $o[2]; |
||||
|
} |
||||
|
else { |
||||
|
$board = $post['board']; |
||||
|
} |
||||
|
$id = $o[3]; |
||||
|
|
||||
|
$query = prepare("SELECT `message_id_digest` FROM ``nntp_references`` WHERE `board` = :board AND `id` = :id"); |
||||
|
$query->bindValue(':board', $board); |
||||
|
$query->bindValue(':id', $id); |
||||
|
$query->execute() or error(db_error($query)); |
||||
|
|
||||
|
if ($result = $query->fetch(PDO::FETCH_ASSOC)) { |
||||
|
return ">>".substr($result['message_id_digest'], 0, 18); |
||||
|
} |
||||
|
else { |
||||
|
return $o[0]; // Should send URL imo |
||||
|
} |
||||
|
}, $body); |
||||
|
$body = preg_replace('/>>>>([0-9a-fA-F])+/', '>>\1', $body); |
||||
|
|
||||
|
|
||||
|
$files[] = array('type' => 'text/plain', 'text' => $body); |
||||
|
|
||||
|
foreach ($post['files'] as $id => $file) { |
||||
|
$fc = array(); |
||||
|
|
||||
|
$fc['type'] = $file['type']; |
||||
|
$fc['text'] = file_get_contents($file['file_path']); |
||||
|
$fc['name'] = $file['name']; |
||||
|
|
||||
|
$files[] = $fc; |
||||
|
} |
||||
|
|
||||
|
return array($headers, $files); |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
<?php |
||||
|
define('TINYBOARD', 'fuck yeah'); |
||||
|
require_once('nntpchan.php'); |
||||
|
|
||||
|
|
||||
|
die(); |
||||
|
|
||||
|
$time = time(); |
||||
|
echo "\n@@@@ Thread:\n"; |
||||
|
echo $m0 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.0000.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None"], |
||||
|
[['type' => 'text/plain', 'text' => "THIS IS A NEW TEST THREAD"]]); |
||||
|
echo "\n@@@@ Single msg:\n"; |
||||
|
echo $m1 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.1234.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"], |
||||
|
[['type' => 'text/plain', 'text' => "hello world, with no image :("]]); |
||||
|
echo "\n@@@@ Single msg and pseudoimage:\n"; |
||||
|
echo $m2 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.2137.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"], |
||||
|
[['type' => 'text/plain', 'text' => "hello world, now with an image!"], |
||||
|
['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif.gif"]]); |
||||
|
echo "\n@@@@ Single msg and two pseudoimages:\n"; |
||||
|
echo $m3 = gennntp(["From" => "czaks <marcin@6irc.net>", "Message-Id" => "<1234.1488.".$time."@example.vichan.net>", "Newsgroups" => "overchan.test", "Date" => time(), "Subject" => "None", "References" => "<1234.0000.".$time."@example.vichan.net>"], |
||||
|
[['type' => 'text/plain', 'text' => "hello world, now WITH TWO IMAGES!!!"], |
||||
|
['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif.gif"], |
||||
|
['type' => 'image/gif', 'text' => base64_decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="), 'name' => "urgif2.gif"]]); |
||||
|
shoveitup($m0, "<1234.0000.".$time."@example.vichan.net>"); |
||||
|
sleep(1); |
||||
|
shoveitup($m1, "<1234.1234.".$time."@example.vichan.net>"); |
||||
|
sleep(1); |
||||
|
shoveitup($m2, "<1234.2137.".$time."@example.vichan.net>"); |
||||
|
shoveitup($m3, "<1234.1488.".$time."@example.vichan.net>"); |
||||
|
|
@ -0,0 +1,28 @@ |
|||||
|
<?php |
||||
|
|
||||
|
// PHP 5.4 |
||||
|
|
||||
|
if (!function_exists('hex2bin')) { |
||||
|
function hex2bin($data) { |
||||
|
return pack("H*" , $hex_string); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// PHP 5.6 |
||||
|
|
||||
|
if (!function_exists('hash_equals')) { |
||||
|
function hash_equals($ours, $theirs) { |
||||
|
$ours = (string)$ours; |
||||
|
$theirs = (string)$theirs; |
||||
|
|
||||
|
$tlen = strlen($theirs); |
||||
|
$olen = strlen($ours); |
||||
|
|
||||
|
$answer = 0; |
||||
|
for ($i = 0; $i < $tlen; $i++) { |
||||
|
$answer |= ord($ours[$olen > $i ? $i : 0]) ^ ord($theirs[$i]); |
||||
|
} |
||||
|
|
||||
|
return $answer === 0 && $olen === $tlen; |
||||
|
} |
||||
|
} |
@ -0,0 +1,49 @@ |
|||||
|
<?php |
||||
|
|
||||
|
class Queue { |
||||
|
function __construct($key) { global $config; |
||||
|
if ($config['queue']['enabled'] == 'fs') { |
||||
|
$this->lock = new Lock($key); |
||||
|
$key = str_replace('/', '::', $key); |
||||
|
$key = str_replace("\0", '', $key); |
||||
|
$this->key = "tmp/queue/$key/"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function push($str) { global $config; |
||||
|
if ($config['queue']['enabled'] == 'fs') { |
||||
|
$this->lock->get_ex(); |
||||
|
file_put_contents($this->key.microtime(true), $str); |
||||
|
$this->lock->free(); |
||||
|
} |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
function pop($n = 1) { global $config; |
||||
|
if ($config['queue']['enabled'] == 'fs') { |
||||
|
$this->lock->get_ex(); |
||||
|
$dir = opendir($this->key); |
||||
|
$paths = array(); |
||||
|
while ($n > 0) { |
||||
|
$path = readdir($dir); |
||||
|
if ($path === FALSE) break; |
||||
|
elseif ($path == '.' || $path == '..') continue; |
||||
|
else { $paths[] = $path; $n--; } |
||||
|
} |
||||
|
$out = array(); |
||||
|
foreach ($paths as $v) { |
||||
|
$out []= file_get_contents($this->key.$v); |
||||
|
unlink($this->key.$v); |
||||
|
} |
||||
|
$this->lock->free(); |
||||
|
return $out; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Don't use the constructor. Use the get_queue function. |
||||
|
$queues = array(); |
||||
|
|
||||
|
function get_queue($name) { global $queues; |
||||
|
return $queues[$name] = isset ($queues[$name]) ? $queues[$name] : new Queue($name); |
||||
|
} |
@ -0,0 +1,65 @@ |
|||||
|
<?php |
||||
|
|
||||
|
// vichan's routing mechanism |
||||
|
|
||||
|
// don't bother with that unless you use smart build or advanced build |
||||
|
// you can use those parts for your own implementations though :^) |
||||
|
|
||||
|
defined('TINYBOARD') or exit; |
||||
|
|
||||
|
function route($path) { global $config; |
||||
|
$entrypoints = array(); |
||||
|
|
||||
|
$entrypoints['/%b/'] = 'sb_board'; |
||||
|
$entrypoints['/%b/'.$config['file_index']] = 'sb_board'; |
||||
|
$entrypoints['/%b/'.$config['file_page']] = 'sb_board'; |
||||
|
$entrypoints['/%b/%d.json'] = 'sb_api_board'; |
||||
|
if ($config['api']['enabled']) { |
||||
|
$entrypoints['/%b/threads.json'] = 'sb_api'; |
||||
|
$entrypoints['/%b/catalog.json'] = 'sb_api'; |
||||
|
} |
||||
|
|
||||
|
$entrypoints['/%b/'.$config['dir']['res'].$config['file_page']] = 'sb_thread_slugcheck'; |
||||
|
$entrypoints['/%b/'.$config['dir']['res'].$config['file_page50']] = 'sb_thread_slugcheck50'; |
||||
|
if ($config['slugify']) { |
||||
|
$entrypoints['/%b/'.$config['dir']['res'].$config['file_page_slug']] = 'sb_thread_slugcheck'; |
||||
|
$entrypoints['/%b/'.$config['dir']['res'].$config['file_page50_slug']] = 'sb_thread_slugcheck50'; |
||||
|
} |
||||
|
if ($config['api']['enabled']) { |
||||
|
$entrypoints['/%b/'.$config['dir']['res'].'%d.json'] = 'sb_thread'; |
||||
|
} |
||||
|
|
||||
|
$entrypoints['/*/'] = 'sb_ukko'; |
||||
|
$entrypoints['/*/index.html'] = 'sb_ukko'; |
||||
|
$entrypoints['/recent.html'] = 'sb_recent'; |
||||
|
$entrypoints['/%b/catalog.html'] = 'sb_catalog'; |
||||
|
$entrypoints['/%b/index.rss'] = 'sb_catalog'; |
||||
|
$entrypoints['/sitemap.xml'] = 'sb_sitemap'; |
||||
|
|
||||
|
$entrypoints = array_merge($entrypoints, $config['controller_entrypoints']); |
||||
|
|
||||
|
$reached = false; |
||||
|
|
||||
|
list($request) = explode('?', $path); |
||||
|
|
||||
|
foreach ($entrypoints as $id => $fun) { |
||||
|
$id = '@^' . preg_quote($id, '@') . '$@u'; |
||||
|
|
||||
|
$id = str_replace('%b', '('.$config['board_regex'].')', $id); |
||||
|
$id = str_replace('%d', '([0-9]+)', $id); |
||||
|
$id = str_replace('%s', '[a-zA-Z0-9-]+', $id); |
||||
|
|
||||
|
$matches = null; |
||||
|
|
||||
|
if (preg_match ($id, $request, $matches)) { |
||||
|
array_shift($matches); |
||||
|
|
||||
|
$reached = array($fun, $matches); |
||||
|
|
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return $reached; |
||||
|
} |
||||
|
|
@ -0,0 +1,27 @@ |
|||||
|
$('document').ready(function () { |
||||
|
var autoScroll = localStorage['autoScroll'] ? true : false; |
||||
|
if (window.Options && Options.get_tab('general')){ |
||||
|
Options.extend_tab('general','<label id=\'autoScroll\'><input type=\'checkbox\' />' + ' Scroll to new posts' + '</label>'); |
||||
|
$('#autoScroll').find('input').prop('checked', autoScroll); |
||||
|
} |
||||
|
$('#autoScroll').on('change', function() { |
||||
|
if(autoScroll) { |
||||
|
delete localStorage.autoScroll; |
||||
|
} else { |
||||
|
localStorage.autoScroll = true; |
||||
|
} |
||||
|
autoScroll =! autoScroll |
||||
|
if(active_page == 'thread') |
||||
|
$('input.auto-scroll').prop('checked', autoScroll); |
||||
|
}); |
||||
|
if (active_page == 'thread') { |
||||
|
$('span[id="updater"]').children('a').after(' (<input class="auto-scroll" type="checkbox"></input> Scroll to New posts)'); |
||||
|
$('input.auto-scroll').prop('checked', autoScroll); |
||||
|
$(document).on('new_post', function (e, post) { |
||||
|
if ($('input.auto-scroll').prop('checked')) |
||||
|
{ |
||||
|
scrollTo(0, $(post).offset().top - window.innerHeight + $(post).outerHeight(true)); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}); |
@ -0,0 +1,383 @@ |
|||||
|
/* |
||||
|
* comment-toolbar.js |
||||
|
* - Adds a toolbar above the commenting area containing most of 8Chan's formatting options |
||||
|
* - Press Esc to close quick-reply window when it's in focus |
||||
|
* |
||||
|
* Usage: |
||||
|
* $config['additional_javascript'][] = 'js/jquery.min.js'; |
||||
|
* $config['additional_javascript'][] = 'js/comment-toolbar.js'; |
||||
|
*/ |
||||
|
if (active_page == 'thread' || active_page == 'index') { |
||||
|
var formatText = (function($){ |
||||
|
"use strict"; |
||||
|
var self = {}; |
||||
|
self.rules = { |
||||
|
spoiler: { |
||||
|
text: _('Spoiler'), |
||||
|
key: 's', |
||||
|
multiline: false, |
||||
|
exclusiveline: false, |
||||
|
prefix:'**', |
||||
|
suffix:'**' |
||||
|
}, |
||||
|
italics: { |
||||
|
text: _('Italics'), |
||||
|
key: 'i', |
||||
|
multiline: false, |
||||
|
exclusiveline: false, |
||||
|
prefix: "''", |
||||
|
suffix: "''" |
||||
|
}, |
||||
|
bold: { |
||||
|
text: _('Bold'), |
||||
|
key: 'b', |
||||
|
multiline: false, |
||||
|
exclusiveline: false, |
||||
|
prefix: "'''", |
||||
|
suffix: "'''" |
||||
|
}, |
||||
|
underline: { |
||||
|
text: _('Underline'), |
||||
|
key: 'u', |
||||
|
multiline: false, |
||||
|
exclusiveline: false, |
||||
|
prefix:'__', |
||||
|
suffix:'__' |
||||
|
}, |
||||
|
code: { |
||||
|
text: _('Code'), |
||||
|
key: 'f', |
||||
|
multiline: true, |
||||
|
exclusiveline: false, |
||||
|
prefix: '[code]', |
||||
|
suffix: '[/code]' |
||||
|
}, |
||||
|
strike: { |
||||
|
text: _('Strike'), |
||||
|
key: 'd', |
||||
|
multiline:false, |
||||
|
exclusiveline:false, |
||||
|
prefix:'~~', |
||||
|
suffix:'~~' |
||||
|
}, |
||||
|
heading: { |
||||
|
text: _('Heading'), |
||||
|
key: 'r', |
||||
|
multiline:false, |
||||
|
exclusiveline:true, |
||||
|
prefix:'==', |
||||
|
suffix:'==' |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
self.toolbar_wrap = function(node) { |
||||
|
var parent = $(node).parents('form[name="post"]'); |
||||
|
self.wrap(parent.find('#body')[0],'textarea[name="body"]', parent.find('.format-text > select')[0].value, false); |
||||
|
}; |
||||
|
|
||||
|
self.wrap = function(ref, target, option, expandedwrap) { |
||||
|
// clean and validate arguments
|
||||
|
if (ref == null) return; |
||||
|
var settings = {multiline: false, exclusiveline: false, prefix:'', suffix: null}; |
||||
|
$.extend(settings,JSON.parse(localStorage.formatText_rules)[option]); |
||||
|
|
||||
|
// resolve targets into array of proper node elements
|
||||
|
// yea, this is overly verbose, oh well.
|
||||
|
var res = []; |
||||
|
if (target instanceof Array) { |
||||
|
for (var indexa in target) { |
||||
|
if (target.hasOwnProperty(indexa)) { |
||||
|
if (typeof target[indexa] == 'string') { |
||||
|
var nodes = $(target[indexa]); |
||||
|
for (var indexb in nodes) { |
||||
|
if (indexa.hasOwnProperty(indexb)) res.push(nodes[indexb]); |
||||
|
} |
||||
|
} else { |
||||
|
res.push(target[indexa]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
if (typeof target == 'string') { |
||||
|
var nodes = $(target); |
||||
|
for (var index in nodes) { |
||||
|
if (nodes.hasOwnProperty(index)) res.push(nodes[index]); |
||||
|
} |
||||
|
} else { |
||||
|
res.push(target); |
||||
|
} |
||||
|
} |
||||
|
target = res; |
||||
|
//record scroll top to restore it later.
|
||||
|
var scrollTop = ref.scrollTop; |
||||
|
|
||||
|
//We will restore the selection later, so record the current selection
|
||||
|
var selectionStart = ref.selectionStart; |
||||
|
var selectionEnd = ref.selectionEnd; |
||||
|
|
||||
|
var text = ref.value; |
||||
|
var before = text.substring(0, selectionStart); |
||||
|
var selected = text.substring(selectionStart, selectionEnd); |
||||
|
var after = text.substring(selectionEnd); |
||||
|
var whiteSpace = [" ","\t"]; |
||||
|
var breakSpace = ["\r","\n"]; |
||||
|
var cursor; |
||||
|
|
||||
|
// handles multiline selections on formatting that doesn't support spanning over multiple lines
|
||||
|
if (!settings.multiline) selected = selected.replace(/(\r|\n|\r\n)/g,settings.suffix +"$1"+ settings.prefix); |
||||
|
|
||||
|
// handles formatting that requires it to be on it's own line OR if the user wishes to expand the wrap to the nearest linebreak
|
||||
|
if (settings.exclusiveline || expandedwrap) { |
||||
|
// buffer the begining of the selection until a linebreak
|
||||
|
cursor = before.length -1; |
||||
|
while (cursor >= 0 && breakSpace.indexOf(before.charAt(cursor)) == -1) { |
||||
|
cursor--; |
||||
|
} |
||||
|
selected = before.substring(cursor +1) + selected; |
||||
|
before = before.substring(0, cursor +1); |
||||
|
|
||||
|
// buffer the end of the selection until a linebreak
|
||||
|
cursor = 0; |
||||
|
while (cursor < after.length && breakSpace.indexOf(after.charAt(cursor)) == -1) { |
||||
|
cursor++; |
||||
|
} |
||||
|
selected += after.substring(0, cursor); |
||||
|
after = after.substring(cursor); |
||||
|
} |
||||
|
|
||||
|
// set values
|
||||
|
var res = before + settings.prefix + selected + settings.suffix + after; |
||||
|
$(target).val(res); |
||||
|
|
||||
|
// restore the selection area and scroll of the reference
|
||||
|
ref.selectionEnd = before.length + settings.prefix.length + selected.length; |
||||
|
if (selectionStart === selectionEnd) { |
||||
|
ref.selectionStart = ref.selectionEnd; |
||||
|
} else { |
||||
|
ref.selectionStart = before.length + settings.prefix.length; |
||||
|
} |
||||
|
ref.scrollTop = scrollTop; |
||||
|
}; |
||||
|
|
||||
|
self.build_toolbars = function(){ |
||||
|
if (localStorage.formatText_toolbar == 'true'){ |
||||
|
// remove existing toolbars
|
||||
|
if ($('.format-text').length > 0) $('.format-text').remove(); |
||||
|
|
||||
|
// Place toolbar above each textarea input
|
||||
|
var name, options = '', rules = JSON.parse(localStorage.formatText_rules); |
||||
|
for (var index in rules) { |
||||
|
if (!rules.hasOwnProperty(index)) continue; |
||||
|
name = rules[index].text; |
||||
|
|
||||
|
//add hint if key exists
|
||||
|
if (rules[index].key) { |
||||
|
name += ' (CTRL + '+ rules[index].key.toUpperCase() +')'; |
||||
|
} |
||||
|
options += '<option value="'+ index +'">'+ name +'</option>'; |
||||
|
} |
||||
|
$('[name="body"]').before('<div class="format-text"><a href="javascript:;" onclick="formatText.toolbar_wrap(this);">Wrap</a><select>'+ options +'</select></div>'); |
||||
|
$('body').append('<style>#quick-reply .format-text>a{width:15%;display:inline-block;text-align:center;}#quick-reply .format-text>select{width:85%;};</style>'); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
self.add_rule = function(rule, index){ |
||||
|
if (rule === undefined) rule = { |
||||
|
text: 'New Rule', |
||||
|
key: '', |
||||
|
multiline:false, |
||||
|
exclusiveline:false, |
||||
|
prefix:'', |
||||
|
suffix:'' |
||||
|
} |
||||
|
|
||||
|
// generate an id for the rule
|
||||
|
if (index === undefined) { |
||||
|
var rules = JSON.parse(localStorage.formatText_rules); |
||||
|
while (rules[index] || index === undefined) { |
||||
|
index = '' |
||||
|
index +='abcdefghijklmnopqrstuvwxyz'.substr(Math.floor(Math.random()*26),1); |
||||
|
index +='abcdefghijklmnopqrstuvwxyz'.substr(Math.floor(Math.random()*26),1); |
||||
|
index +='abcdefghijklmnopqrstuvwxyz'.substr(Math.floor(Math.random()*26),1); |
||||
|
} |
||||
|
} |
||||
|
if (window.Options && Options.get_tab('formatting')){ |
||||
|
var html = $('<div class="format_rule" name="'+ index +'"></div>').html('\ |
||||
|
<input type="text" name="text" class="format_option" size="10" value=\"'+ rule.text.replace(/"/g, '"') +'\">\ |
||||
|
<input type="checkbox" name="multiline" class="format_option" '+ (rule.multiline ? 'checked' : '') +'>\ |
||||
|
<input type="checkbox" name="exclusiveline" class="format_option" '+ (rule.exclusiveline ? 'checked' : '') +'>\ |
||||
|
<input type="text" name="prefix" class="format_option" size="8" value=\"'+ (rule.prefix ? rule.prefix.replace(/"/g, '"') : '') +'\">\ |
||||
|
<input type="text" name="suffix" class="format_option" size="8" value=\"'+ (rule.suffix ? rule.suffix.replace(/"/g, '"') : '') +'\">\ |
||||
|
<input type="text" name="key" class="format_option" size="2" maxlength="1" value=\"'+ rule.key +'\">\ |
||||
|
<input type="button" value="X" onclick="if(confirm(\'Do you wish to remove the '+ rule.text +' formatting rule?\'))$(this).parent().remove();">\ |
||||
|
'); |
||||
|
|
||||
|
if ($('.format_rule').length > 0) { |
||||
|
$('.format_rule').last().after(html); |
||||
|
} else { |
||||
|
Options.extend_tab('formatting', html); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
self.save_rules = function(){ |
||||
|
var rule, newrules = {}, rules = $('.format_rule'); |
||||
|
for (var index=0;rules[index];index++) { |
||||
|
rule = $(rules[index]); |
||||
|
newrules[rule.attr('name')] = { |
||||
|
text: rule.find('[name="text"]').val(), |
||||
|
key: rule.find('[name="key"]').val(), |
||||
|
prefix: rule.find('[name="prefix"]').val(), |
||||
|
suffix: rule.find('[name="suffix"]').val(), |
||||
|
multiline: rule.find('[name="multiline"]').is(':checked'), |
||||
|
exclusiveline: rule.find('[name="exclusiveline"]').is(':checked') |
||||
|
}; |
||||
|
} |
||||
|
localStorage.formatText_rules = JSON.stringify(newrules); |
||||
|
self.build_toolbars(); |
||||
|
}; |
||||
|
|
||||
|
self.reset_rules = function(to_default) { |
||||
|
$('.format_rule').remove(); |
||||
|
var rules; |
||||
|
if (to_default) rules = self.rules; |
||||
|
else rules = JSON.parse(localStorage.formatText_rules); |
||||
|
for (var index in rules){ |
||||
|
if (!rules.hasOwnProperty(index)) continue; |
||||
|
self.add_rule(rules[index], index); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// setup default rules for customizing
|
||||
|
if (!localStorage.formatText_rules) localStorage.formatText_rules = JSON.stringify(self.rules); |
||||
|
|
||||
|
// setup code to be ran when page is ready (work around for main.js compilation).
|
||||
|
$(document).ready(function(){ |
||||
|
// Add settings to Options panel general tab
|
||||
|
if (window.Options && Options.get_tab('general')) { |
||||
|
var s1 = '#formatText_keybinds>input', s2 = '#formatText_toolbar>input', e = 'change'; |
||||
|
Options.extend_tab('general', '\ |
||||
|
<fieldset>\ |
||||
|
<legend>Formatting Options</legend>\ |
||||
|
<label id="formatText_keybinds"><input type="checkbox">' + _('Enable formatting keybinds') + '</label>\ |
||||
|
<label id="formatText_toolbar"><input type="checkbox">' + _('Show formatting toolbar') + '</label>\ |
||||
|
</fieldset>\ |
||||
|
'); |
||||
|
} else { |
||||
|
var s1 = '#formatText_keybinds', s2 = '#formatText_toolbar', e = 'click'; |
||||
|
$('hr:first').before('<div id="formatText_keybinds" style="text-align:right"><a class="unimportant" href="javascript:void(0)">'+ _('Enable formatting keybinds') +'</a></div>'); |
||||
|
$('hr:first').before('<div id="formatText_toolbar" style="text-align:right"><a class="unimportant" href="javascript:void(0)">'+ _('Show formatting toolbar') +'</a></div>'); |
||||
|
} |
||||
|
|
||||
|
// add the tab for customizing the format settings
|
||||
|
if (window.Options && !Options.get_tab('formatting')) { |
||||
|
Options.add_tab('formatting', 'angle-right', _('Customize Formatting')); |
||||
|
Options.extend_tab('formatting', '\ |
||||
|
<style>\ |
||||
|
.format_option{\ |
||||
|
margin-right:5px;\ |
||||
|
overflow:initial;\ |
||||
|
font-size:15px;\ |
||||
|
}\ |
||||
|
.format_option[type="text"]{\ |
||||
|
text-align:center;\ |
||||
|
padding-bottom: 2px;\ |
||||
|
padding-top: 2px;\ |
||||
|
}\ |
||||
|
.format_option:last-child{\ |
||||
|
margin-right:0;\ |
||||
|
}\ |
||||
|
fieldset{\ |
||||
|
margin-top:5px;\ |
||||
|
}\ |
||||
|
</style>\ |
||||
|
'); |
||||
|
|
||||
|
// Data control row
|
||||
|
Options.extend_tab('formatting', '\ |
||||
|
<button onclick="formatText.add_rule();">'+_('Add Rule')+'</button>\ |
||||
|
<button onclick="formatText.save_rules();">'+_('Save Rules')+'</button>\ |
||||
|
<button onclick="formatText.reset_rules(false);">'+_('Revert')+'</button>\ |
||||
|
<button onclick="formatText.reset_rules(true);">'+_('Reset to Default')+'</button>\ |
||||
|
'); |
||||
|
|
||||
|
// Descriptor row
|
||||
|
Options.extend_tab('formatting', '\ |
||||
|
<span class="format_option" style="margin-left:25px;">Name</span>\ |
||||
|
<span class="format_option" style="margin-left:45px;" title="Multi-line: Allow formatted area to contain linebreaks.">ML</span>\ |
||||
|
<span class="format_option" style="margin-left:0px;" title="Exclusive-line: Require formatted area to start after and end before a linebreak.">EL</span>\ |
||||
|
<span class="format_option" style="margin-left:25px;" title="Text injected at the start of a format area.">Prefix</span>\ |
||||
|
<span class="format_option" style="margin-left:60px;" title="Text injected at the end of a format area.">Suffix</span>\ |
||||
|
<span class="format_option" style="margin-left:40px;" title="Optional keybind value to allow keyboard shortcut access.">Key</span>\ |
||||
|
'); |
||||
|
|
||||
|
// Rule rows
|
||||
|
var rules = JSON.parse(localStorage.formatText_rules); |
||||
|
for (var index in rules){ |
||||
|
if (!rules.hasOwnProperty(index)) continue; |
||||
|
self.add_rule(rules[index], index); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// setting for enabling formatting keybinds
|
||||
|
$(s1).on(e, function(e) { |
||||
|
console.log('Keybind'); |
||||
|
if (!localStorage.formatText_keybinds || localStorage.formatText_keybinds == 'false') { |
||||
|
localStorage.formatText_keybinds = 'true'; |
||||
|
if (window.Options && Options.get_tab('general')) e.target.checked = true; |
||||
|
} else { |
||||
|
localStorage.formatText_keybinds = 'false'; |
||||
|
if (window.Options && Options.get_tab('general')) e.target.checked = false; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// setting for toolbar injection
|
||||
|
$(s2).on(e, function(e) { |
||||
|
console.log('Toolbar'); |
||||
|
if (!localStorage.formatText_toolbar || localStorage.formatText_toolbar == 'false') { |
||||
|
localStorage.formatText_toolbar = 'true'; |
||||
|
if (window.Options && Options.get_tab('general')) e.target.checked = true; |
||||
|
formatText.build_toolbars(); |
||||
|
} else { |
||||
|
localStorage.formatText_toolbar = 'false'; |
||||
|
if (window.Options && Options.get_tab('general')) e.target.checked = false; |
||||
|
$('.format-text').remove(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// make sure the tab settings are switch properly at loadup
|
||||
|
if (window.Options && Options.get_tab('general')) { |
||||
|
if (localStorage.formatText_keybinds == 'true') $(s1)[0].checked = true; |
||||
|
else $(s1)[0].checked = false; |
||||
|
if (localStorage.formatText_toolbar == 'true') $(s2)[0].checked = true; |
||||
|
else $(s2)[0].checked = false; |
||||
|
} |
||||
|
|
||||
|
// Initial toolbar injection
|
||||
|
formatText.build_toolbars(); |
||||
|
|
||||
|
//attach listener to <body> so it also works on quick-reply box
|
||||
|
$('body').on('keydown', '[name="body"]', function(e) { |
||||
|
if (!localStorage.formatText_keybinds || localStorage.formatText_keybinds == 'false') return; |
||||
|
var key = String.fromCharCode(e.which).toLowerCase(); |
||||
|
var rules = JSON.parse(localStorage.formatText_rules); |
||||
|
for (var index in rules) { |
||||
|
if (!rules.hasOwnProperty(index)) continue; |
||||
|
if (key === rules[index].key && e.ctrlKey) { |
||||
|
e.preventDefault(); |
||||
|
if (e.shiftKey) { |
||||
|
formatText.wrap(e.target, 'textarea[name="body"]', index, true); |
||||
|
} else { |
||||
|
formatText.wrap(e.target, 'textarea[name="body"]', index, false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// Signal that comment-toolbar loading has completed.
|
||||
|
$(document).trigger('formatText'); |
||||
|
}); |
||||
|
|
||||
|
return self; |
||||
|
})(jQuery); |
||||
|
} |
@ -1,26 +1,69 @@ |
|||||
/* |
/* |
||||
* fix-report-delete-submit.js |
* fix-report-delete-submit.js |
||||
* https://github.com/savetheinternet/Tinyboard/blob/master/js/fix-report-delete-submit.js
|
|
||||
* |
|
||||
* Fixes a known bug regarding the delete/report submit buttons. |
|
||||
* |
|
||||
* Released under the MIT license |
|
||||
* Copyright (c) 2012 Michael Save <savetheinternet@tinyboard.org> |
|
||||
* |
* |
||||
* Usage: |
* Usage: |
||||
* $config['additional_javascript'][] = 'js/jquery.min.js'; |
* $config['additional_javascript'][] = 'js/jquery.min.js'; |
||||
|
* $config['additional_javascript'][] = 'js/post-menu.js'; |
||||
* $config['additional_javascript'][] = 'js/fix-report-delete-submit.js'; |
* $config['additional_javascript'][] = 'js/fix-report-delete-submit.js'; |
||||
* |
* |
||||
*/ |
*/ |
||||
|
|
||||
$(document).ready(function(){ |
if (active_page == 'thread' || active_page == 'index' || active_page == 'ukko') { |
||||
$('form[name="postcontrols"] div.delete input:not([type="checkbox"]):not([type="submit"]):not([type="hidden"])').keypress(function(e) { |
$(document).on('menu_ready', function(){ |
||||
if(e.which == 13) { |
var Menu = window.Menu; |
||||
|
|
||||
|
if ($('#delete-fields #password').length) { |
||||
|
Menu.add_item("delete_post_menu", _("Delete post")); |
||||
|
Menu.add_item("delete_file_menu", _("Delete file")); |
||||
|
Menu.onclick(function(e, $buf) { |
||||
|
var ele = e.target.parentElement.parentElement; |
||||
|
var $ele = $(ele); |
||||
|
var threadId = $ele.parent().attr('id').replace('thread_', ''); |
||||
|
var postId = $ele.find('.post_no').not('[id]').text(); |
||||
|
var board_name = $ele.parent().data('board'); |
||||
|
|
||||
|
$buf.find('#delete_post_menu,#delete_file_menu').click(function(e) { |
||||
e.preventDefault(); |
e.preventDefault(); |
||||
$(this).next().click(); |
$('#delete_'+postId).prop('checked', 'checked'); |
||||
return false; |
|
||||
|
if ($(this).attr('id') === 'delete_file_menu') { |
||||
|
$('#delete_file').prop('checked', 'checked'); |
||||
|
} else { |
||||
|
$('#delete_file').prop('checked', ''); |
||||
|
} |
||||
|
$('input[type="hidden"][name="board"]').val(board_name); |
||||
|
$('input[name=delete][type=submit]').click(); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
Menu.add_item("report_menu", _("Report")); |
||||
|
//Menu.add_item("global_report_menu", _("Global report"));
|
||||
|
Menu.onclick(function(e, $buf) { |
||||
|
var ele = e.target.parentElement.parentElement; |
||||
|
var $ele = $(ele); |
||||
|
var threadId = $ele.parent().attr('id').replace('thread_', ''); |
||||
|
var postId = $ele.find('.post_no').not('[id]').text(); |
||||
|
var board_name = $ele.parent().data('board'); |
||||
|
|
||||
|
$buf.find('#report_menu,#global_report_menu').click(function(e) { |
||||
|
if ($(this).attr('id') === "global_report_menu") { |
||||
|
var global = '&global'; |
||||
|
} else { |
||||
|
var global = ''; |
||||
} |
} |
||||
return true; |
window.open(configRoot+'report.php?board='+board_name+'&post=delete_'+postId+global, "", (global?"width=600, height=575":"width=500, height=275")); |
||||
}); |
}); |
||||
}); |
}); |
||||
|
|
||||
|
$(document).on('new_post', function(){ |
||||
|
$('input.delete').hide(); |
||||
|
}); |
||||
|
$('input.delete').hide(); |
||||
|
$('#post-moderation-fields').hide(); |
||||
|
}); |
||||
|
|
||||
|
if (typeof window.Menu !== "undefined") { |
||||
|
$(document).trigger('menu_ready'); |
||||
|
} |
||||
|
} |
||||
|
@ -1,43 +1,67 @@ |
|||||
/* |
/* |
||||
* MIXITUP - A CSS3 and JQuery Filter & Sort Plugin |
Copyright 2014 KunkaLabs Limited. |
||||
* Version: 1.5.5 |
@author KunkaLabs Limited. |
||||
* License: Creative Commons Attribution-NoDerivs 3.0 Unported - CC BY-ND 3.0 |
@link https://mixitup.kunkalabs.com
|
||||
* http://creativecommons.org/licenses/by-nd/3.0/
|
|
||||
* This software may be used freely on commercial and non-commercial projects with attribution to the author/copyright holder. |
@license Commercial use requires a commercial license. |
||||
* Author: Patrick Kunka |
https://mixitup.kunkalabs.com/licenses/
|
||||
* Copyright 2012-2013 Patrick Kunka, Barrel LLC, All Rights Reserved |
|
||||
* |
|
||||
* http://mixitup.io
|
|
||||
*/ |
|
||||
|
|
||||
(function(d){function r(e,c,l,b,a){function f(){n.unbind("webkitTransitionEnd transitionend otransitionend oTransitionEnd");c&&x(c,l,b,a);a.startOrder=[];a.newOrder=[];a.origSort=[];a.checkSort=[];v.removeStyle(a.prefix+"filter, filter, "+a.prefix+"transform, transform, opacity, display").css(a.clean).removeAttr("data-checksum");window.atob||v.css({display:"none",opacity:"0"});n.removeStyle(a.prefix+"transition, transition, "+a.prefix+"perspective, perspective, "+a.prefix+"perspective-origin, perspective-origin, "+ |
Non-commercial use permitted under terms of CC-BY-NC license. |
||||
(a.resizeContainer?"height":""));"list"==a.layoutMode?(p.css({display:a.targetDisplayList,opacity:"1"}),a.origDisplay=a.targetDisplayList):(p.css({display:a.targetDisplayGrid,opacity:"1"}),a.origDisplay=a.targetDisplayGrid);a.origLayout=a.layoutMode;setTimeout(function(){v.removeStyle(a.prefix+"transition, transition");a.mixing=!1;if("function"==typeof a.onMixEnd){var b=a.onMixEnd.call(this,a);a=b?b:a}})}clearInterval(a.failsafe);a.mixing=!0;a.filter=e;if("function"==typeof a.onMixStart){var g=a.onMixStart.call(this, |
http://creativecommons.org/licenses/by-nc/3.0/
|
||||
a);a=g?g:a}for(var k=a.transitionSpeed,g=0;2>g;g++){var h=0==g?h=a.prefix:"";a.transition[h+"transition"]="all "+k+"ms linear";a.transition[h+"transform"]=h+"translate3d(0,0,0)";a.perspective[h+"perspective"]=a.perspectiveDistance+"px";a.perspective[h+"perspective-origin"]=a.perspectiveOrigin}var w=a.targetSelector,v=b.find(w);v.each(function(){this.data={}});var n=v.parent();n.css(a.perspective);a.easingFallback="ease-in-out";"smooth"==a.easing&&(a.easing="cubic-bezier(0.25, 0.46, 0.45, 0.94)"); |
*/ |
||||
"snap"==a.easing&&(a.easing="cubic-bezier(0.77, 0, 0.175, 1)");"windback"==a.easing&&(a.easing="cubic-bezier(0.175, 0.885, 0.320, 1.275)",a.easingFallback="cubic-bezier(0.175, 0.885, 0.320, 1)");"windup"==a.easing&&(a.easing="cubic-bezier(0.6, -0.28, 0.735, 0.045)",a.easingFallback="cubic-bezier(0.6, 0.28, 0.735, 0.045)");g="list"==a.layoutMode&&null!=a.listEffects?a.listEffects:a.effects;Array.prototype.indexOf&&(a.fade=-1<g.indexOf("fade")?"0":"",a.scale=-1<g.indexOf("scale")?"scale(.01)":"",a.rotateZ= |
(function(f,l){f.MixItUp=function(){this._execAction("_constructor",0);f.extend(this,{selectors:{target:".mix",filter:".filter",sort:".sort"},animation:{enable:!0,effects:"fade scale",duration:600,easing:"ease",perspectiveDistance:"3000",perspectiveOrigin:"50% 50%",queue:!0,queueLimit:1,animateChangeLayout:!1,animateResizeContainer:!0,animateResizeTargets:!1,staggerSequence:!1,reverseOut:!1},callbacks:{onMixLoad:!1,onMixStart:!1,onMixBusy:!1,onMixEnd:!1,onMixFail:!1,_user:!1},controls:{enable:!0, |
||||
-1<g.indexOf("rotateZ")?"rotate(180deg)":"",a.rotateY=-1<g.indexOf("rotateY")?"rotateY(90deg)":"",a.rotateX=-1<g.indexOf("rotateX")?"rotateX(90deg)":"",a.blur=-1<g.indexOf("blur")?"blur(8px)":"",a.grayscale=-1<g.indexOf("grayscale")?"grayscale(100%)":"");var p=d(),s=d(),t=[],r=!1;"string"===typeof e?t=z(e):(r=!0,d.each(e,function(a){t[a]=z(this)}));"or"==a.filterLogic?(""==t[0]&&t.shift(),1>t.length?s=s.add(b.find(w+":visible")):v.each(function(){var a=d(this);if(r){var b=0;d.each(t,function(d){this.length? |
live:!1,toggleFilterButtons:!1,toggleLogic:"or",activeClass:"active"},layout:{display:"inline-block",containerClass:"",containerClassFail:"fail"},load:{filter:"all",sort:!1},_$body:null,_$container:null,_$targets:null,_$parent:null,_$sortButtons:null,_$filterButtons:null,_suckMode:!1,_mixing:!1,_sorting:!1,_clicking:!1,_loading:!0,_changingLayout:!1,_changingClass:!1,_changingDisplay:!1,_origOrder:[],_startOrder:[],_newOrder:[],_activeFilter:null,_toggleArray:[],_toggleString:"",_activeSort:"default:asc", |
||||
a.is("."+this.join(", ."))&&b++:0<b&&b++});b==t.length?p=p.add(a):s=s.add(a)}else a.is("."+t.join(", ."))?p=p.add(a):s=s.add(a)})):(p=p.add(n.find(w+"."+t.join("."))),s=s.add(n.find(w+":not(."+t.join(".")+"):visible")));e=p.length;var u=d(),q=d(),m=d();s.each(function(){var a=d(this);"none"!=a.css("display")&&(u=u.add(a),m=m.add(a))});if(p.filter(":visible").length==e&&!u.length&&!c){if(a.origLayout==a.layoutMode)return f(),!1;if(1==p.length)return"list"==a.layoutMode?(b.addClass(a.listClass),b.removeClass(a.gridClass), |
_newSort:null,_startHeight:null,_newHeight:null,_incPadding:!0,_newDisplay:null,_newClass:null,_targetsBound:0,_targetsDone:0,_queue:[],_$show:f(),_$hide:f()});this._execAction("_constructor",1)};f.MixItUp.prototype={constructor:f.MixItUp,_instances:{},_handled:{_filter:{},_sort:{}},_bound:{_filter:{},_sort:{}},_actions:{},_filters:{},extend:function(a){for(var c in a)f.MixItUp.prototype[c]=a[c]},addAction:function(a,c,b,d){f.MixItUp.prototype._addHook("_actions",a,c,b,d)},addFilter:function(a,c, |
||||
m.css("display",a.targetDisplayList)):(b.addClass(a.gridClass),b.removeClass(a.listClass),m.css("display",a.targetDisplayGrid)),f(),!1}a.origHeight=n.height();if(p.length){b.removeClass(a.failClass);p.each(function(){var a=d(this);"none"==a.css("display")?q=q.add(a):m=m.add(a)});if(a.origLayout!=a.layoutMode&&!1==a.animateGridList)return"list"==a.layoutMode?(b.addClass(a.listClass),b.removeClass(a.gridClass),m.css("display",a.targetDisplayList)):(b.addClass(a.gridClass),b.removeClass(a.listClass), |
b,d){f.MixItUp.prototype._addHook("_filters",a,c,b,d)},_addHook:function(a,c,b,d,e){a=f.MixItUp.prototype[a];var g={};e=1===e||"post"===e?"post":"pre";g[c]={};g[c][e]={};g[c][e][b]=d;f.extend(!0,a,g)},_init:function(a,c){this._execAction("_init",0,arguments);c&&f.extend(!0,this,c);this._$body=f("body");this._domNode=a;this._$container=f(a);this._$container.addClass(this.layout.containerClass);this._id=a.id;this._platformDetect();this._brake=this._getPrefixedCSS("transition","none");this._refresh(!0); |
||||
m.css("display",a.targetDisplayGrid)),f(),!1;if(!window.atob)return f(),!1;v.css(a.clean);m.each(function(){this.data.origPos=d(this).offset()});"list"==a.layoutMode?(b.addClass(a.listClass),b.removeClass(a.gridClass),q.css("display",a.targetDisplayList)):(b.addClass(a.gridClass),b.removeClass(a.listClass),q.css("display",a.targetDisplayGrid));q.each(function(){this.data.showInterPos=d(this).offset()});u.each(function(){this.data.hideInterPos=d(this).offset()});m.each(function(){this.data.preInterPos= |
this._$parent=this._$targets.parent().length?this._$targets.parent():this._$container;this.load.sort&&(this._newSort=this._parseSort(this.load.sort),this._activeSort=this._newSortString=this.load.sort,this._sort(),this._printSort());this._activeFilter="all"===this.load.filter?this.selectors.target:"none"===this.load.filter?"":this.load.filter;this.controls.enable&&this._bindHandlers();if(this.controls.toggleFilterButtons){this._buildToggleArray();for(var b=0;b<this._toggleArray.length;b++)this._updateControls({filter:this._toggleArray[b], |
||||
d(this).offset()});"list"==a.layoutMode?m.css("display",a.targetDisplayList):m.css("display",a.targetDisplayGrid);c&&x(c,l,b,a);if(c&&A(a.origSort,a.checkSort))return f(),!1;u.hide();q.each(function(a){this.data.finalPos=d(this).offset()});m.each(function(){this.data.finalPrePos=d(this).offset()});a.newHeight=n.height();c&&x("reset",null,b,a);q.hide();m.css("display",a.origDisplay);"block"==a.origDisplay?(b.addClass(a.listClass),q.css("display",a.targetDisplayList)):(b.removeClass(a.listClass),q.css("display", |
sort:this._activeSort},!0)}else this.controls.enable&&this._updateControls({filter:this._activeFilter,sort:this._activeSort});this._filter();this._init=!0;this._$container.data("mixItUp",this);this._execAction("_init",1,arguments);this._buildState();this._$targets.css(this._brake);this._goMix(this.animation.enable)},_platformDetect:function(){var a=["Webkit","Moz","O","ms"],c=["webkit","moz"],b=window.navigator.appVersion.match(/Chrome\/(\d+)\./)||!1,d="undefined"!==typeof InstallTrigger,e=function(b){for(var c= |
||||
a.targetDisplayGrid));a.resizeContainer&&n.css("height",a.origHeight+"px");e={};for(g=0;2>g;g++)h=0==g?h=a.prefix:"",e[h+"transform"]=a.scale+" "+a.rotateX+" "+a.rotateY+" "+a.rotateZ,e[h+"filter"]=a.blur+" "+a.grayscale;q.css(e);m.each(function(){var b=this.data,c=d(this);c.hasClass("mix_tohide")?(b.preTX=b.origPos.left-b.hideInterPos.left,b.preTY=b.origPos.top-b.hideInterPos.top):(b.preTX=b.origPos.left-b.preInterPos.left,b.preTY=b.origPos.top-b.preInterPos.top);for(var e={},k=0;2>k;k++){var h= |
0;c<a.length;c++)if(a[c]+"Transition"in b.style)return{prefix:"-"+a[c].toLowerCase()+"-",vendor:a[c]};return"transition"in b.style?"":!1}(this._domNode);this._execAction("_platformDetect",0);this._chrome=b?parseInt(b[1],10):!1;this._ff=d?parseInt(window.navigator.userAgent.match(/rv:([^)]+)\)/)[1]):!1;this._prefix=e.prefix;this._vendor=e.vendor;(this._suckMode=window.atob&&this._prefix?!1:!0)&&(this.animation.enable=!1);this._ff&&4>=this._ff&&(this.animation.enable=!1);for(b=0;b<c.length&&!window.requestAnimationFrame;b++)window.requestAnimationFrame= |
||||
0==k?h=a.prefix:"";e[h+"transform"]="translate("+b.preTX+"px,"+b.preTY+"px)"}c.css(e)});"list"==a.layoutMode?(b.addClass(a.listClass),b.removeClass(a.gridClass)):(b.addClass(a.gridClass),b.removeClass(a.listClass));setTimeout(function(){if(a.resizeContainer){for(var b={},c=0;2>c;c++){var e=0==c?e=a.prefix:"";b[e+"transition"]="all "+k+"ms ease-in-out";b.height=a.newHeight+"px"}n.css(b)}u.css("opacity",a.fade);q.css("opacity",1);q.each(function(){var b=this.data;b.tX=b.finalPos.left-b.showInterPos.left; |
window[c[b]+"RequestAnimationFrame"];"function"!==typeof Object.getPrototypeOf&&(Object.getPrototypeOf="object"===typeof"test".__proto__?function(a){return a.__proto__}:function(a){return a.constructor.prototype});this._domNode.nextElementSibling===l&&Object.defineProperty(Element.prototype,"nextElementSibling",{get:function(){for(var a=this.nextSibling;a;){if(1===a.nodeType)return a;a=a.nextSibling}return null}});this._execAction("_platformDetect",1)},_refresh:function(a,c){this._execAction("_refresh", |
||||
b.tY=b.finalPos.top-b.showInterPos.top;for(var c={},e=0;2>e;e++){var h=0==e?h=a.prefix:"";c[h+"transition-property"]=h+"transform, "+h+"filter, opacity";c[h+"transition-timing-function"]=a.easing+", linear, linear";c[h+"transition-duration"]=k+"ms";c[h+"transition-delay"]="0";c[h+"transform"]="translate("+b.tX+"px,"+b.tY+"px)";c[h+"filter"]="none"}d(this).css("-webkit-transition","all "+k+"ms "+a.easingFallback).css(c)});m.each(function(){var b=this.data;b.tX=0!=b.finalPrePos.left?b.finalPrePos.left- |
0,arguments);this._$targets=this._$container.find(this.selectors.target);for(var b=0;b<this._$targets.length;b++){var d=this._$targets[b];if(d.dataset===l||c){d.dataset={};for(var e=0;e<d.attributes.length;e++){var g=d.attributes[e],k=g.name,g=g.value;-1<k.indexOf("data-")&&(k=this._helpers._camelCase(k.substring(5,k.length)),d.dataset[k]=g)}}d.mixParent===l&&(d.mixParent=this._id)}if(this._$targets.length&&a||!this._origOrder.length&&this._$targets.length)for(this._origOrder=[],b=0;b<this._$targets.length;b++)d= |
||||
b.preInterPos.left:0;b.tY=0!=b.finalPrePos.left?b.finalPrePos.top-b.preInterPos.top:0;for(var c={},e=0;2>e;e++){var h=0==e?h=a.prefix:"";c[h+"transition"]="all "+k+"ms "+a.easing;c[h+"transform"]="translate("+b.tX+"px,"+b.tY+"px)"}d(this).css("-webkit-transition","all "+k+"ms "+a.easingFallback).css(c)});b={};for(c=0;2>c;c++)e=0==c?e=a.prefix:"",b[e+"transition"]="all "+k+"ms "+a.easing+", "+e+"filter "+k+"ms linear, opacity "+k+"ms linear",b[e+"transform"]=a.scale+" "+a.rotateX+" "+a.rotateY+" "+ |
this._$targets[b],this._origOrder.push(d);this._execAction("_refresh",1,arguments)},_bindHandlers:function(){var a=this,c=f.MixItUp.prototype._bound._filter,b=f.MixItUp.prototype._bound._sort;a._execAction("_bindHandlers",0);if(a.controls.live)a._$body.on("click.mixItUp."+a._id,a.selectors.sort,function(){a._processClick(f(this),"sort")}).on("click.mixItUp."+a._id,a.selectors.filter,function(){a._processClick(f(this),"filter")});else a._$sortButtons=f(a.selectors.sort),a._$filterButtons=f(a.selectors.filter), |
||||
a.rotateZ,b[e+"filter"]=a.blur+" "+a.grayscale,b.opacity=a.fade;u.css(b);n.bind("webkitTransitionEnd transitionend otransitionend oTransitionEnd",function(a){if(-1<a.originalEvent.propertyName.indexOf("transform")||-1<a.originalEvent.propertyName.indexOf("opacity"))-1<w.indexOf(".")?d(a.target).hasClass(w.replace(".",""))&&f():d(a.target).is(w)&&f()})},10);a.failsafe=setTimeout(function(){a.mixing&&f()},k+400)}else{a.resizeContainer&&n.css("height",a.origHeight+"px");if(!window.atob)return f(),!1; |
a._$sortButtons.on("click.mixItUp."+a._id,function(){a._processClick(f(this),"sort")}),a._$filterButtons.on("click.mixItUp."+a._id,function(){a._processClick(f(this),"filter")});c[a.selectors.filter]=c[a.selectors.filter]===l?1:c[a.selectors.filter]+1;b[a.selectors.sort]=b[a.selectors.sort]===l?1:b[a.selectors.sort]+1;a._execAction("_bindHandlers",1)},_processClick:function(a,c){var b=this,d=function(a,c,d){var e=f.MixItUp.prototype;e._handled["_"+c][b.selectors[c]]=e._handled["_"+c][b.selectors[c]]=== |
||||
u=s;setTimeout(function(){n.css(a.perspective);if(a.resizeContainer){for(var c={},e=0;2>e;e++){var d=0==e?d=a.prefix:"";c[d+"transition"]="height "+k+"ms ease-in-out";c.height=a.minHeight+"px"}n.css(c)}v.css(a.transition);if(s.length){c={};for(e=0;2>e;e++)d=0==e?d=a.prefix:"",c[d+"transform"]=a.scale+" "+a.rotateX+" "+a.rotateY+" "+a.rotateZ,c[d+"filter"]=a.blur+" "+a.grayscale,c.opacity=a.fade;u.css(c);n.bind("webkitTransitionEnd transitionend otransitionend oTransitionEnd",function(c){if(-1<c.originalEvent.propertyName.indexOf("transform")|| |
l?1:e._handled["_"+c][b.selectors[c]]+1;e._handled["_"+c][b.selectors[c]]===e._bound["_"+c][b.selectors[c]]&&(a[(d?"remove":"add")+"Class"](b.controls.activeClass),delete e._handled["_"+c][b.selectors[c]])};b._execAction("_processClick",0,arguments);if(!b._mixing||b.animation.queue&&b._queue.length<b.animation.queueLimit){b._clicking=!0;if("sort"===c){var e=a.attr("data-sort");if(!a.hasClass(b.controls.activeClass)||-1<e.indexOf("random"))f(b.selectors.sort).removeClass(b.controls.activeClass),d(a, |
||||
-1<c.originalEvent.propertyName.indexOf("opacity"))b.addClass(a.failClass),f()})}else a.mixing=!1},10)}}function x(e,c,l,b){function a(a,b){var c=isNaN(1*a.attr(e))?a.attr(e).toLowerCase():1*a.attr(e),d=isNaN(1*b.attr(e))?b.attr(e).toLowerCase():1*b.attr(e);return c<d?-1:c>d?1:0}function f(a){"asc"==c?k.prepend(a).prepend(" "):k.append(a).append(" ")}function g(a){a=a.slice();for(var b=a.length,c=b;c--;){var e=parseInt(Math.random()*b),d=a[c];a[c]=a[e];a[e]=d}return a}l.find(b.targetSelector).wrapAll('<div class="mix_sorter"/>'); |
c),b.sort(e)}if("filter"===c){var g=a.attr("data-filter"),e="or"===b.controls.toggleLogic?",":"";b.controls.toggleFilterButtons?(b._buildToggleArray(),a.hasClass(b.controls.activeClass)?(d(a,c,!0),d=b._toggleArray.indexOf(g),b._toggleArray.splice(d,1)):(d(a,c),b._toggleArray.push(g)),b._toggleArray=f.grep(b._toggleArray,function(a){return a}),b._toggleString=b._toggleArray.join(e),b.filter(b._toggleString)):a.hasClass(b.controls.activeClass)||(f(b.selectors.filter).removeClass(b.controls.activeClass), |
||||
var k=l.find(".mix_sorter");b.origSort.length||k.find(b.targetSelector+":visible").each(function(){d(this).wrap("<s/>");b.origSort.push(d(this).parent().html().replace(/\s+/g,""));d(this).unwrap()});k.empty();if("reset"==e)d.each(b.startOrder,function(){k.append(this).append(" ")});else if("default"==e)d.each(b.origOrder,function(){f(this)});else if("random"==e)b.newOrder.length||(b.newOrder=g(b.startOrder)),d.each(b.newOrder,function(){k.append(this).append(" ")});else if("custom"==e)d.each(c,function(){f(this)}); |
d(a,c),b.filter(g))}b._execAction("_processClick",1,arguments)}else"function"===typeof b.callbacks.onMixBusy&&b.callbacks.onMixBusy.call(b._domNode,b._state,b),b._execAction("_processClickBusy",1,arguments)},_buildToggleArray:function(){var a=this._activeFilter.replace(/\s/g,"");this._execAction("_buildToggleArray",0,arguments);if("or"===this.controls.toggleLogic)this._toggleArray=a.split(",");else{this._toggleArray=a.split(".");!this._toggleArray[0]&&this._toggleArray.shift();for(var a=0,c;c=this._toggleArray[a];a++)this._toggleArray[a]= |
||||
else{if("undefined"===typeof b.origOrder[0].attr(e))return console.log("No such attribute found. Terminating"),!1;b.newOrder.length||(d.each(b.origOrder,function(){b.newOrder.push(d(this))}),b.newOrder.sort(a));d.each(b.newOrder,function(){f(this)})}b.checkSort=[];k.find(b.targetSelector+":visible").each(function(a){var c=d(this);0==a&&c.attr("data-checksum","1");c.wrap("<s/>");b.checkSort.push(c.parent().html().replace(/\s+/g,""));c.unwrap()});l.find(b.targetSelector).unwrap()}function B(e){for(var c= |
"."+c}this._execAction("_buildToggleArray",1,arguments)},_updateControls:function(a,c){var b={filter:a.filter,sort:a.sort},d="filter",e=null;this._execAction("_updateControls",0,arguments);a.filter===l&&(b.filter=this._activeFilter);a.sort===l&&(b.sort=this._activeSort);b.filter===this.selectors.target&&(b.filter="all");for(var g=0;2>g;g++){if(e=this.controls.live?f(this.selectors[d]):this["_$"+d+"Buttons"]){var k="[data-"+d+'="'+b[d]+'"]';c&&"filter"===d&&"none"!==b.filter&&""!==b.filter?e.filter(k).addClass(this.controls.activeClass): |
||||
["Webkit","Moz","O","ms"],d=0;d<c.length;d++)if(c[d]+"Transition"in e.style)return c[d];return"transition"in e.style?"":!1}function A(e,c){if(e.length!=c.length)return!1;for(var d=0;d<c.length;d++)if(e[d].compare&&!e[d].compare(c[d])||e[d]!==c[d])return!1;return!0}function z(e){e=e.replace(/\s{2,}/g," ");var c=e.split(" ");d.each(c,function(d){"all"==this&&(c[d]="mix_all")});""==c[0]&&c.shift();return c}var y={init:function(e){return this.each(function(){var c=window.navigator.appVersion.match(/Chrome\/(\d+)\./), |
e.removeClass(this.controls.activeClass).filter(k).addClass(this.controls.activeClass)}d="sort"}this._execAction("_updateControls",1,arguments)},_filter:function(){this._execAction("_filter",0);for(var a=0;a<this._$targets.length;a++){var c=f(this._$targets[a]);c.is(this._activeFilter)?this._$show=this._$show.add(c):this._$hide=this._$hide.add(c)}this._execAction("_filter",1)},_sort:function(){var a=this,c=function(a){a=a.slice();for(var b=a.length,c=b;c--;){var f=parseInt(Math.random()*b),h=a[c]; |
||||
c=c?parseInt(c[1],10):!1,l=function(a){a=document.getElementById(a);var b=a.parentElement,c=document.createElement("div"),d=document.createDocumentFragment();b.insertBefore(c,a);d.appendChild(a);b.replaceChild(a,c)};(c&&31==c||32==c)&&l(this.id);var b={targetSelector:".mix",filterSelector:".filter",sortSelector:".sort",buttonEvent:"click",effects:["fade","scale"],listEffects:null,easing:"smooth",layoutMode:"grid",targetDisplayGrid:"inline-block",targetDisplayList:"block",listClass:"",gridClass:"", |
a[c]=a[f];a[f]=h}return a};a._execAction("_sort",0);a._startOrder=[];for(var b=0;b<a._$targets.length;b++)a._startOrder.push(a._$targets[b]);switch(a._newSort[0].sortBy){case "default":a._newOrder=a._origOrder;break;case "random":a._newOrder=c(a._startOrder);break;case "custom":a._newOrder=a._newSort[0].order;break;default:a._newOrder=a._startOrder.concat().sort(function(b,c){return a._compare(b,c)})}a._execAction("_sort",1)},_compare:function(a,c,b){b=b?b:0;var d=this,e=d._newSort[b].order,g=function(a){return a.dataset[d._newSort[b].sortBy]|| |
||||
transitionSpeed:600,showOnLoad:"all",sortOnLoad:!1,multiFilter:!1,filterLogic:"or",resizeContainer:!0,minHeight:0,failClass:"fail",perspectiveDistance:"3000",perspectiveOrigin:"50% 50%",animateGridList:!0,onMixLoad:null,onMixStart:null,onMixEnd:null,container:null,origOrder:[],startOrder:[],newOrder:[],origSort:[],checkSort:[],filter:"",mixing:!1,origDisplay:"",origLayout:"",origHeight:0,newHeight:0,isTouch:!1,resetDelay:0,failsafe:null,prefix:"",easingFallback:"ease-in-out",transition:{},perspective:{}, |
0},f=isNaN(1*g(a))?g(a).toLowerCase():1*g(a),g=isNaN(1*g(c))?g(c).toLowerCase():1*g(c);return f<g?"asc"===e?-1:1:f>g?"asc"===e?1:-1:f===g&&d._newSort.length>b+1?d._compare(a,c,b+1):0},_printSort:function(a){var c=a?this._startOrder:this._newOrder,b=this._$parent[0].querySelectorAll(this.selectors.target),d=b.length?b[b.length-1].nextElementSibling:null,e=document.createDocumentFragment();this._execAction("_printSort",0,arguments);for(var g=0;g<b.length;g++){var f=b[g],h=f.nextSibling;"absolute"!== |
||||
clean:{},fade:"1",scale:"",rotateX:"",rotateY:"",rotateZ:"",blur:"",grayscale:""};e&&d.extend(b,e);this.config=b;d.support.touch="ontouchend"in document;d.support.touch&&(b.isTouch=!0,b.resetDelay=350);b.container=d(this);var a=b.container;b.prefix=B(a[0]);b.prefix=b.prefix?"-"+b.prefix.toLowerCase()+"-":"";a.find(b.targetSelector).each(function(){b.origOrder.push(d(this))});if(b.sortOnLoad){var f;d.isArray(b.sortOnLoad)?(c=b.sortOnLoad[0],f=b.sortOnLoad[1],d(b.sortSelector+"[data-sort="+b.sortOnLoad[0]+ |
f.style.position&&(h&&"#text"===h.nodeName&&this._$parent[0].removeChild(h),this._$parent[0].removeChild(f))}for(g=0;g<c.length;g++)b=c[g],"default"!==this._newSort[0].sortBy||"desc"!==this._newSort[0].order||a?(e.appendChild(b),e.appendChild(document.createTextNode(" "))):(e.insertBefore(b,e.firstChild),e.insertBefore(document.createTextNode(" "),b));d?this._$parent[0].insertBefore(e,d):this._$parent[0].appendChild(e);this._execAction("_printSort",1,arguments)},_parseSort:function(a){for(var c="string"=== |
||||
"][data-order="+b.sortOnLoad[1]+"]").addClass("active")):(d(b.sortSelector+"[data-sort="+b.sortOnLoad+"]").addClass("active"),c=b.sortOnLoad,b.sortOnLoad="desc");x(c,f,a,b)}for(f=0;2>f;f++)c=0==f?c=b.prefix:"",b.transition[c+"transition"]="all "+b.transitionSpeed+"ms ease-in-out",b.perspective[c+"perspective"]=b.perspectiveDistance+"px",b.perspective[c+"perspective-origin"]=b.perspectiveOrigin;for(f=0;2>f;f++)c=0==f?c=b.prefix:"",b.clean[c+"transition"]="none";"list"==b.layoutMode?(a.addClass(b.listClass), |
typeof a?a.split(" "):[a],b=[],d=0;d<c.length;d++){var e="string"===typeof a?c[d].split(":"):["custom",c[d]],e={sortBy:this._helpers._camelCase(e[0]),order:e[1]||"asc"};b.push(e);if("default"===e.sortBy||"random"===e.sortBy)break}return this._execFilter("_parseSort",b,arguments)},_parseEffects:function(){var a=this,c={opacity:"",transformIn:"",transformOut:"",filter:""},b=function(b,c,d){return-1<a.animation.effects.indexOf(b)?c&&(b=a.animation.effects.indexOf(b+"("),-1<b)?(b=a.animation.effects.substring(b), |
||||
b.origDisplay=b.targetDisplayList):(a.addClass(b.gridClass),b.origDisplay=b.targetDisplayGrid);b.origLayout=b.layoutMode;f=b.showOnLoad.split(" ");d.each(f,function(){d(b.filterSelector+'[data-filter="'+this+'"]').addClass("active")});a.find(b.targetSelector).addClass("mix_all");"all"==f[0]&&(f[0]="mix_all",b.showOnLoad="mix_all");var g=d();d.each(f,function(){g=g.add(d("."+this))});g.each(function(){var a=d(this);"list"==b.layoutMode?a.css("display",b.targetDisplayList):a.css("display",b.targetDisplayGrid); |
{val:/\(([^)]+)\)/.exec(b)[1]}):!0:!1},d=function(a,d){for(var f=[["scale",".01"],["translateX","20px"],["translateY","20px"],["translateZ","20px"],["rotateX","90deg"],["rotateY","90deg"],["rotateZ","180deg"]],h=0;h<f.length;h++){var m=f[h][0],l=f[h][1],p=d&&"scale"!==m,q=c[a],n;b(m)?(n=m+"(",m=b(m,!0).val||l,p=p?"-"===m.charAt(0)?m.substr(1,m.length):"-"+m:m,n=n+p+") "):n="";c[a]=q+n}};c.opacity=b("fade")?b("fade",!0).val||"0":"1";d("transformIn");a.animation.reverseOut?d("transformOut",!0):c.transformOut= |
||||
a.css(b.transition)});setTimeout(function(){b.mixing=!0;g.css("opacity","1");setTimeout(function(){"list"==b.layoutMode?g.removeStyle(b.prefix+"transition, transition").css({display:b.targetDisplayList,opacity:1}):g.removeStyle(b.prefix+"transition, transition").css({display:b.targetDisplayGrid,opacity:1});b.mixing=!1;if("function"==typeof b.onMixLoad){var a=b.onMixLoad.call(this,b);b=a?a:b}},b.transitionSpeed)},10);b.filter=b.showOnLoad;d(b.sortSelector).bind(b.buttonEvent,function(){if(!b.mixing){var c= |
c.transformIn;c.transition={};c.transition=a._getPrefixedCSS("transition","all "+a.animation.duration+"ms "+a.animation.easing+", opacity "+a.animation.duration+"ms linear");a.animation.stagger=b("stagger")?!0:!1;a.animation.staggerDuration=parseInt(b("stagger")?b("stagger",!0).val?b("stagger",!0).val:100:100);return a._execFilter("_parseEffects",c)},_buildState:function(a){var c={};this._execAction("_buildState",0);c={activeFilter:""===this._activeFilter?"none":this._activeFilter,activeSort:a&&this._newSortString? |
||||
d(this),e=c.attr("data-sort"),f=c.attr("data-order");if(!c.hasClass("active"))d(b.sortSelector).removeClass("active"),c.addClass("active");else if("random"!=e)return!1;a.find(b.targetSelector).each(function(){b.startOrder.push(d(this))});r(b.filter,e,f,a,b)}});d(b.filterSelector).bind(b.buttonEvent,function(){if(!b.mixing){var c=d(this);if(!1==b.multiFilter)d(b.filterSelector).removeClass("active"),c.addClass("active"),b.filter=c.attr("data-filter"),d(b.filterSelector+'[data-filter="'+b.filter+'"]').addClass("active"); |
this._newSortString:this._activeSort,fail:!this._$show.length&&""!==this._activeFilter,$targets:this._$targets,$show:this._$show,$hide:this._$hide,totalTargets:this._$targets.length,totalShow:this._$show.length,totalHide:this._$hide.length,display:a&&this._newDisplay?this._newDisplay:this.layout.display};if(a)return this._execFilter("_buildState",c);this._state=c;this._execAction("_buildState",1)},_goMix:function(a){var c=this,b=function(){if(c._chrome&&31===c._chrome){var a=c._$parent[0],b=a.parentElement, |
||||
else{var e=c.attr("data-filter");c.hasClass("active")?(c.removeClass("active"),b.filter=b.filter.replace(RegExp("(\\s|^)"+e),"")):(c.addClass("active"),b.filter=b.filter+" "+e)}r(b.filter,null,null,a,b)}})})},toGrid:function(){return this.each(function(){var e=this.config;"grid"!=e.layoutMode&&(e.layoutMode="grid",r(e.filter,null,null,d(this),e))})},toList:function(){return this.each(function(){var e=this.config;"list"!=e.layoutMode&&(e.layoutMode="list",r(e.filter,null,null,d(this),e))})},filter:function(e){return this.each(function(){var c= |
e=document.createElement("div"),f=document.createDocumentFragment();b.insertBefore(e,a);f.appendChild(a);b.replaceChild(a,e)}c._setInter();d()},d=function(){var a=window.pageYOffset,b=window.pageXOffset;c._getInterMixData();c._setFinal();c._getFinalMixData();window.pageYOffset!==a&&window.scrollTo(b,a);c._prepTargets();window.requestAnimationFrame?requestAnimationFrame(e):setTimeout(function(){e()},20)},e=function(){c._animateTargets();0===c._targetsBound&&c._cleanUp()},f=c._buildState(!0);c._execAction("_goMix", |
||||
this.config;c.mixing||(d(c.filterSelector).removeClass("active"),d(c.filterSelector+'[data-filter="'+e+'"]').addClass("active"),r(e,null,null,d(this),c))})},sort:function(e){return this.each(function(){var c=this.config,l=d(this);if(!c.mixing){d(c.sortSelector).removeClass("active");if(d.isArray(e)){var b=e[0],a=e[1];d(c.sortSelector+'[data-sort="'+e[0]+'"][data-order="'+e[1]+'"]').addClass("active")}else d(c.sortSelector+'[data-sort="'+e+'"]').addClass("active"),b=e,a="desc";l.find(c.targetSelector).each(function(){c.startOrder.push(d(this))}); |
0,arguments);!c.animation.duration&&(a=!1);c._mixing=!0;c._$container.removeClass(c.layout.containerClassFail);"function"===typeof c.callbacks.onMixStart&&c.callbacks.onMixStart.call(c._domNode,c._state,f,c);c._$container.trigger("mixStart",[c._state,f,c]);c._getOrigMixData();a&&!c._suckMode?window.requestAnimationFrame?requestAnimationFrame(b):b():c._cleanUp();c._execAction("_goMix",1,arguments)},_getTargetData:function(a,c){var b;a.dataset[c+"PosX"]=a.offsetLeft;a.dataset[c+"PosY"]=a.offsetTop; |
||||
r(c.filter,b,a,l,c)}})},multimix:function(e){return this.each(function(){var c=this.config,l=d(this);multiOut={filter:c.filter,sort:null,order:"desc",layoutMode:c.layoutMode};d.extend(multiOut,e);c.mixing||(d(c.filterSelector).add(c.sortSelector).removeClass("active"),d(c.filterSelector+'[data-filter="'+multiOut.filter+'"]').addClass("active"),"undefined"!==typeof multiOut.sort&&(d(c.sortSelector+'[data-sort="'+multiOut.sort+'"][data-order="'+multiOut.order+'"]').addClass("active"),l.find(c.targetSelector).each(function(){c.startOrder.push(d(this))})), |
this.animation.animateResizeTargets&&(b=window.getComputedStyle(a),a.dataset[c+"MarginBottom"]=parseInt(b.marginBottom),a.dataset[c+"MarginRight"]=parseInt(b.marginRight),a.dataset[c+"Width"]=a.offsetWidth,a.dataset[c+"Height"]=a.offsetHeight)},_getOrigMixData:function(){var a=this._suckMode?{boxSizing:""}:window.getComputedStyle(this._$parent[0]);this._incPadding="border-box"===(a.boxSizing||a[this._vendor+"BoxSizing"]);this._execAction("_getOrigMixData",0);!this._suckMode&&(this.effects=this._parseEffects()); |
||||
c.layoutMode=multiOut.layoutMode,r(multiOut.filter,multiOut.sort,multiOut.order,l,c))})},remix:function(e){return this.each(function(){var c=this.config,l=d(this);c.origOrder=[];l.find(c.targetSelector).each(function(){var b=d(this);b.addClass("mix_all");c.origOrder.push(b)});c.mixing||"undefined"===typeof e||(d(c.filterSelector).removeClass("active"),d(c.filterSelector+'[data-filter="'+e+'"]').addClass("active"),r(e,null,null,l,c))})}};d.fn.mixitup=function(d,c){if(y[d])return y[d].apply(this,Array.prototype.slice.call(arguments, |
this._$toHide=this._$hide.filter(":visible");this._$toShow=this._$show.filter(":hidden");this._$pre=this._$targets.filter(":visible");this._startHeight=this._incPadding?this._$parent.outerHeight():this._$parent.height();for(a=0;a<this._$pre.length;a++)this._getTargetData(this._$pre[a],"orig");this._execAction("_getOrigMixData",1)},_setInter:function(){this._execAction("_setInter",0);this._changingLayout&&this.animation.animateChangeLayout?(this._$toShow.css("display",this._newDisplay),this._changingClass&& |
||||
1));if("object"===typeof d||!d)return y.init.apply(this,arguments)};d.fn.removeStyle=function(e){return this.each(function(){var c=d(this);e=e.replace(/\s+/g,"");var l=e.split(",");d.each(l,function(){var b=RegExp(this.toString()+"[^;]+;?","g");c.attr("style",function(a,c){if(c)return c.replace(b,"")})})})}})(jQuery); |
this._$container.removeClass(this.layout.containerClass).addClass(this._newClass)):this._$toShow.css("display",this.layout.display);this._execAction("_setInter",1)},_getInterMixData:function(){this._execAction("_getInterMixData",0);for(var a=0;a<this._$toShow.length;a++){var c=this._$toShow[a];this._getTargetData(c,"inter")}for(a=0;a<this._$pre.length;a++)c=this._$pre[a],this._getTargetData(c,"inter");this._execAction("_getInterMixData",1)},_setFinal:function(){this._execAction("_setFinal",0);this._sorting&& |
||||
|
this._printSort();this._$toHide.removeStyle("display");this._changingLayout&&this.animation.animateChangeLayout&&this._$pre.css("display",this._newDisplay);this._execAction("_setFinal",1)},_getFinalMixData:function(){this._execAction("_getFinalMixData",0);for(var a=0;a<this._$toShow.length;a++){var c=this._$toShow[a];this._getTargetData(c,"final")}for(a=0;a<this._$pre.length;a++)c=this._$pre[a],this._getTargetData(c,"final");this._newHeight=this._incPadding?this._$parent.outerHeight():this._$parent.height(); |
||||
|
this._sorting&&this._printSort(!0);this._$toShow.removeStyle("display");this._$pre.css("display",this.layout.display);this._changingClass&&this.animation.animateChangeLayout&&this._$container.removeClass(this._newClass).addClass(this.layout.containerClass);this._execAction("_getFinalMixData",1)},_prepTargets:function(){var a={_in:this._getPrefixedCSS("transform",this.effects.transformIn),_out:this._getPrefixedCSS("transform",this.effects.transformOut)};this._execAction("_prepTargets",0);this.animation.animateResizeContainer&& |
||||
|
this._$parent.css("height",this._startHeight+"px");for(var c=0;c<this._$toShow.length;c++){var b=this._$toShow[c],d=f(b);b.style.opacity=this.effects.opacity;b.style.display=this._changingLayout&&this.animation.animateChangeLayout?this._newDisplay:this.layout.display;d.css(a._in);this.animation.animateResizeTargets&&(b.style.width=b.dataset.finalWidth+"px",b.style.height=b.dataset.finalHeight+"px",b.style.marginRight=-(b.dataset.finalWidth-b.dataset.interWidth)+1*b.dataset.finalMarginRight+"px",b.style.marginBottom= |
||||
|
-(b.dataset.finalHeight-b.dataset.interHeight)+1*b.dataset.finalMarginBottom+"px")}for(c=0;c<this._$pre.length;c++)b=this._$pre[c],d=f(b),a=this._getPrefixedCSS("transform","translate("+(b.dataset.origPosX-b.dataset.interPosX)+"px,"+(b.dataset.origPosY-b.dataset.interPosY)+"px)"),d.css(a),this.animation.animateResizeTargets&&(b.style.width=b.dataset.origWidth+"px",b.style.height=b.dataset.origHeight+"px",b.dataset.origWidth-b.dataset.finalWidth&&(b.style.marginRight=-(b.dataset.origWidth-b.dataset.interWidth)+ |
||||
|
1*b.dataset.origMarginRight+"px"),b.dataset.origHeight-b.dataset.finalHeight&&(b.style.marginBottom=-(b.dataset.origHeight-b.dataset.interHeight)+1*b.dataset.origMarginBottom+"px"));this._execAction("_prepTargets",1)},_animateTargets:function(){var a,c;this._execAction("_animateTargets",0);this._targetsBound=this._targetsDone=0;this._$parent.css(this._getPrefixedCSS("perspective",this.animation.perspectiveDistance+"px")).css(this._getPrefixedCSS("perspective-origin",this.animation.perspectiveOrigin)); |
||||
|
this.animation.animateResizeContainer&&this._$parent.css(this._getPrefixedCSS("transition","height "+this.animation.duration+"ms ease")).css("height",this._newHeight+"px");for(var b=0;b<this._$toShow.length;b++){var d=this._$toShow[b],e=f(d);a=d.dataset.finalPosX-d.dataset.interPosX;c=d.dataset.finalPosY-d.dataset.interPosY;var g=this._getDelay(b),k={};d.style.opacity="";for(d=0;2>d;d++){var h=0===d?h=this._prefix:"";this._ff&&20>=this._ff&&(k[h+"transition-property"]="all",k[h+"transition-timing-function"]= |
||||
|
this.animation.easing+"ms",k[h+"transition-duration"]=this.animation.duration+"ms");k[h+"transition-delay"]=g+"ms";k[h+"transform"]="translate("+a+"px,"+c+"px)"}(this.effects.transform||this.effects.opacity)&&this._bindTargetDone(e);this._ff&&20>=this._ff?e.css(k):e.css(this.effects.transition).css(k)}for(b=0;b<this._$pre.length;b++)d=this._$pre[b],e=f(d),a=d.dataset.finalPosX-d.dataset.interPosX,c=d.dataset.finalPosY-d.dataset.interPosY,g=this._getDelay(b),d.dataset.finalPosX===d.dataset.origPosX&& |
||||
|
d.dataset.finalPosY===d.dataset.origPosY||this._bindTargetDone(e),e.css(this._getPrefixedCSS("transition","all "+this.animation.duration+"ms "+this.animation.easing+" "+g+"ms")),e.css(this._getPrefixedCSS("transform","translate("+a+"px,"+c+"px)")),this.animation.animateResizeTargets&&(d.dataset.origWidth-d.dataset.finalWidth&&1*d.dataset.finalWidth&&(d.style.width=d.dataset.finalWidth+"px",d.style.marginRight=-(d.dataset.finalWidth-d.dataset.interWidth)+1*d.dataset.finalMarginRight+"px"),d.dataset.origHeight- |
||||
|
d.dataset.finalHeight&&1*d.dataset.finalHeight&&(d.style.height=d.dataset.finalHeight+"px",d.style.marginBottom=-(d.dataset.finalHeight-d.dataset.interHeight)+1*d.dataset.finalMarginBottom+"px"));this._changingClass&&this._$container.removeClass(this.layout.containerClass).addClass(this._newClass);for(b=0;b<this._$toHide.length;b++){d=this._$toHide[b];e=f(d);g=this._getDelay(b);a={};for(d=0;2>d;d++)h=0===d?h=this._prefix:"",a[h+"transition-delay"]=g+"ms",a[h+"transform"]=this.effects.transformOut, |
||||
|
a.opacity=this.effects.opacity;e.css(this.effects.transition).css(a);(this.effects.transform||this.effects.opacity)&&this._bindTargetDone(e)}this._execAction("_animateTargets",1)},_bindTargetDone:function(a){var c=this,b=a[0];c._execAction("_bindTargetDone",0,arguments);b.dataset.bound||(b.dataset.bound=!0,c._targetsBound++,a.on("webkitTransitionEnd.mixItUp transitionend.mixItUp",function(d){(-1<d.originalEvent.propertyName.indexOf("transform")||-1<d.originalEvent.propertyName.indexOf("opacity"))&& |
||||
|
f(d.originalEvent.target).is(c.selectors.target)&&(a.off(".mixItUp"),delete b.dataset.bound,c._targetDone())}));c._execAction("_bindTargetDone",1,arguments)},_targetDone:function(){this._execAction("_targetDone",0);this._targetsDone++;this._targetsDone===this._targetsBound&&this._cleanUp();this._execAction("_targetDone",1)},_cleanUp:function(){var a=this,c=a.animation.animateResizeTargets?"transform opacity width height margin-bottom margin-right":"transform opacity";unBrake=function(){a._$targets.removeStyle("transition", |
||||
|
a._prefix)};a._execAction("_cleanUp",0);a._changingLayout?a._$show.css("display",a._newDisplay):a._$show.css("display",a.layout.display);a._$targets.css(a._brake);a._$targets.removeStyle(c,a._prefix).removeAttr("data-inter-pos-x data-inter-pos-y data-final-pos-x data-final-pos-y data-orig-pos-x data-orig-pos-y data-orig-height data-orig-width data-final-height data-final-width data-inter-width data-inter-height data-orig-margin-right data-orig-margin-bottom data-inter-margin-right data-inter-margin-bottom data-final-margin-right data-final-margin-bottom"); |
||||
|
a._$hide.removeStyle("display");a._$parent.removeStyle("height transition perspective-distance perspective perspective-origin-x perspective-origin-y perspective-origin perspectiveOrigin",a._prefix);a._sorting&&(a._printSort(),a._activeSort=a._newSortString,a._sorting=!1);a._changingLayout&&(a._changingDisplay&&(a.layout.display=a._newDisplay,a._changingDisplay=!1),a._changingClass&&(a._$parent.removeClass(a.layout.containerClass).addClass(a._newClass),a.layout.containerClass=a._newClass,a._changingClass= |
||||
|
!1),a._changingLayout=!1);a._refresh();a._buildState();a._state.fail&&a._$container.addClass(a.layout.containerClassFail);a._$show=f();a._$hide=f();window.requestAnimationFrame&&requestAnimationFrame(unBrake);a._mixing=!1;"function"===typeof a.callbacks._user&&a.callbacks._user.call(a._domNode,a._state,a);"function"===typeof a.callbacks.onMixEnd&&a.callbacks.onMixEnd.call(a._domNode,a._state,a);a._$container.trigger("mixEnd",[a._state,a]);a._state.fail&&("function"===typeof a.callbacks.onMixFail&& |
||||
|
a.callbacks.onMixFail.call(a._domNode,a._state,a),a._$container.trigger("mixFail",[a._state,a]));a._loading&&("function"===typeof a.callbacks.onMixLoad&&a.callbacks.onMixLoad.call(a._domNode,a._state,a),a._$container.trigger("mixLoad",[a._state,a]));a._queue.length&&(a._execAction("_queue",0),a.multiMix(a._queue[0][0],a._queue[0][1],a._queue[0][2]),a._queue.splice(0,1));a._execAction("_cleanUp",1);a._loading=!1},_getPrefixedCSS:function(a,c,b){var d={};for(i=0;2>i;i++){var e=0===i?this._prefix:""; |
||||
|
b?d[e+a]=e+c:d[e+a]=c}return this._execFilter("_getPrefixedCSS",d,arguments)},_getDelay:function(a){var c="function"===typeof this.animation.staggerSequence?this.animation.staggerSequence.call(this._domNode,a,this._state):a;return this._execFilter("_getDelay",this.animation.stagger?c*this.animation.staggerDuration:0,arguments)},_parseMultiMixArgs:function(a){for(var c={command:null,animate:this.animation.enable,callback:null},b=0;b<a.length;b++){var d=a[b];null!==d&&("object"===typeof d||"string"=== |
||||
|
typeof d?c.command=d:"boolean"===typeof d?c.animate=d:"function"===typeof d&&(c.callback=d))}return this._execFilter("_parseMultiMixArgs",c,arguments)},_parseInsertArgs:function(a){for(var c={index:0,$object:f(),multiMix:{filter:this._state.activeFilter},callback:null},b=0;b<a.length;b++){var d=a[b];"number"===typeof d?c.index=d:"object"===typeof d&&d instanceof f?c.$object=d:"object"===typeof d&&this._helpers._isElement(d)?c.$object=f(d):"object"===typeof d&&null!==d?c.multiMix=d:"boolean"!==typeof d|| |
||||
|
d?"function"===typeof d&&(c.callback=d):c.multiMix=!1}return this._execFilter("_parseInsertArgs",c,arguments)},_execAction:function(a,c,b){c=c?"post":"pre";if(!this._actions.isEmptyObject&&this._actions.hasOwnProperty(a))for(var d in this._actions[a][c])this._actions[a][c][d].call(this,b)},_execFilter:function(a,c,b){if(!this._filters.isEmptyObject&&this._filters.hasOwnProperty(a))for(var d in this._filters[a])return this._filters[a][d].call(this,b);else return c},_helpers:{_camelCase:function(a){return a.replace(/-([a-z])/g, |
||||
|
function(a){return a[1].toUpperCase()})},_isElement:function(a){return window.HTMLElement?a instanceof HTMLElement:null!==a&&1===a.nodeType&&"string"===a.nodeName}},isMixing:function(){return this._execFilter("isMixing",this._mixing)},filter:function(){var a=this._parseMultiMixArgs(arguments);this._clicking&&(this._toggleString="");this.multiMix({filter:a.command},a.animate,a.callback)},sort:function(){var a=this._parseMultiMixArgs(arguments);this.multiMix({sort:a.command},a.animate,a.callback)}, |
||||
|
changeLayout:function(){var a=this._parseMultiMixArgs(arguments);this.multiMix({changeLayout:a.command},a.animate,a.callback)},multiMix:function(){var a=this._parseMultiMixArgs(arguments);this._execAction("multiMix",0,arguments);if(this._mixing)this.animation.queue&&this._queue.length<this.animation.queueLimit?(this._queue.push(arguments),this.controls.enable&&!this._clicking&&this._updateControls(a.command),this._execAction("multiMixQueue",1,arguments)):("function"===typeof this.callbacks.onMixBusy&& |
||||
|
this.callbacks.onMixBusy.call(this._domNode,this._state,this),this._$container.trigger("mixBusy",[this._state,this]),this._execAction("multiMixBusy",1,arguments));else{this.controls.enable&&!this._clicking&&(this.controls.toggleFilterButtons&&this._buildToggleArray(),this._updateControls(a.command,this.controls.toggleFilterButtons));2>this._queue.length&&(this._clicking=!1);delete this.callbacks._user;a.callback&&(this.callbacks._user=a.callback);var c=a.command.sort,b=a.command.filter,d=a.command.changeLayout; |
||||
|
this._refresh();c&&(this._newSort=this._parseSort(c),this._newSortString=c,this._sorting=!0,this._sort());b!==l&&(this._activeFilter=b="all"===b?this.selectors.target:b);this._filter();d&&(this._newDisplay="string"===typeof d?d:d.display||this.layout.display,this._newClass=d.containerClass||"",this._newDisplay!==this.layout.display||this._newClass!==this.layout.containerClass)&&(this._changingLayout=!0,this._changingClass=this._newClass!==this.layout.containerClass,this._changingDisplay=this._newDisplay!== |
||||
|
this.layout.display);this._$targets.css(this._brake);this._goMix(a.animate^this.animation.enable?a.animate:this.animation.enable);this._execAction("multiMix",1,arguments)}},insert:function(){var a=this._parseInsertArgs(arguments),c="function"===typeof a.callback?a.callback:null,b=document.createDocumentFragment(),d;this._refresh();d=this._$targets.length?a.index<this._$targets.length||!this._$targets.length?this._$targets[a.index]:this._$targets[this._$targets.length-1].nextElementSibling:this._$parent[0].children[0]; |
||||
|
this._execAction("insert",0,arguments);if(a.$object){for(var e=0;e<a.$object.length;e++)b.appendChild(a.$object[e]),b.appendChild(document.createTextNode(" "));this._$parent[0].insertBefore(b,d)}this._execAction("insert",1,arguments);"object"===typeof a.multiMix&&this.multiMix(a.multiMix,c)},prepend:function(){var a=this._parseInsertArgs(arguments);this.insert(0,a.$object,a.multiMix,a.callback)},append:function(){var a=this._parseInsertArgs(arguments);this.insert(this._state.totalTargets,a.$object, |
||||
|
a.multiMix,a.callback)},getOption:function(a){var c=function(a,c){for(var e=c.split("."),f=e.pop(),k=e.length,h=1,m=e[0]||c;(a=a[m])&&h<k;)m=e[h],h++;if(a!==l)return a[f]!==l?a[f]:a};return a?this._execFilter("getOption",c(this,a),arguments):this},setOptions:function(a){this._execAction("setOptions",0,arguments);"object"===typeof a&&f.extend(!0,this,a);this._execAction("setOptions",1,arguments)},getState:function(){return this._execFilter("getState",this._state,this)},forceRefresh:function(){this._refresh(!1, |
||||
|
!0)},destroy:function(a){this._execAction("destroy",0,arguments);this._$body.add(f(this.selectors.sort)).add(f(this.selectors.filter)).off(".mixItUp");for(var c=0;c<this._$targets.length;c++){var b=this._$targets[c];a&&(b.style.display="");delete b.mixParent}this._execAction("destroy",1,arguments);delete f.MixItUp.prototype._instances[this._id]}};f.fn.mixItUp=function(){var a=arguments,c=[],b,d=function(a,b){var c=new f.MixItUp;c._execAction("_instantiate",0,arguments);a.id=a.id?a.id:"MixItUp"+("00000"+ |
||||
|
(16777216*Math.random()<<0).toString(16)).substr(-6).toUpperCase();c._instances[a.id]||(c._instances[a.id]=c,c._init(a,b));c._execAction("_instantiate",1,arguments)};b=this.each(function(){if(a&&"string"===typeof a[0]){var b=f.MixItUp.prototype._instances[this.id];"isLoaded"===a[0]?c.push(b?!0:!1):(b=b[a[0]](a[1],a[2],a[3]),b!==l&&c.push(b))}else d(this,a[0])});return c.length?1<c.length?c:c[0]:b};f.fn.removeStyle=function(a,c){c=c?c:"";return this.each(function(){for(var b=a.split(" "),d=0;d<b.length;d++)for(var e= |
||||
|
0;4>e;e++){switch(e){case 0:var g=b[d];break;case 1:g=f.MixItUp.prototype._helpers._camelCase(g);break;case 2:g=c+b[d];break;case 3:g=f.MixItUp.prototype._helpers._camelCase(c+b[d])}this.style[g]!==l&&"unknown"!==typeof this.style[g]&&0<this.style[g].length&&(this.style[g]="");if(!c&&1===e)break}this.attributes&&this.attributes.style&&this.attributes.style!==l&&""===this.attributes.style.value&&this.attributes.removeNamedItem("style")})}})(jQuery); |
||||
|
@ -0,0 +1,72 @@ |
|||||
|
$(document).ready(function(){ |
||||
|
//Creating functions
|
||||
|
var generateList = function(){ |
||||
|
var favStor = []; |
||||
|
for(var i=1; i<favorites.length+1; i++){ |
||||
|
favStor.push($("#sortable > div:nth-child("+i+")").html()); |
||||
|
} |
||||
|
return favStor; |
||||
|
} //This will generate a list of boards based off of the list on the screen
|
||||
|
function removeBoard(boardNumber){ |
||||
|
favorites.splice(boardNumber, 1); |
||||
|
localStorage.favorites = JSON.stringify(favorites); |
||||
|
$("#sortable > div:nth-child("+(boardNumber+1)+")").remove(); |
||||
|
$("#minusList > div:nth-child("+(favorites.length+1)+")").remove(); |
||||
|
add_favorites(); |
||||
|
} //This removes a board from favorites, localStorage.favorites and the page
|
||||
|
function addBoard(){ |
||||
|
$("#sortable").append("<div>"+($("#plusBox").val())+"</div>"); |
||||
|
$("#minusList").append( $('<div data-board="'+favorites.length+'" style="cursor: pointer; margin-right: 5px">-</div>').on('click', function(e){removeBoard($(this).data('board'));}) ); |
||||
|
favorites.push($("#plusBox").val()); |
||||
|
localStorage.favorites = JSON.stringify(favorites); |
||||
|
$("#plusBox").val(""); //Removing text from textbox
|
||||
|
add_favorites(); |
||||
|
} //This adds the text inside the textbox to favorites, localStorage.favorites and the page
|
||||
|
|
||||
|
var favorites = JSON.parse(localStorage.favorites); |
||||
|
Options.add_tab('fav-tab','star',_("Favorites")); |
||||
|
|
||||
|
//Pregenerating list of boards
|
||||
|
var favList = $('<div id="sortable" style="cursor: pointer; display: inline-block">'); |
||||
|
for(var i=0; i<favorites.length; i++){ |
||||
|
favList.append( $('<div>'+favorites[i]+'</div>') ); |
||||
|
} |
||||
|
|
||||
|
//Creating list of minus symbols to remove unwanted boards
|
||||
|
var minusList = $('<div id="minusList" style="color: #0000FF; display: inline-block">'); |
||||
|
for(var i=0; i<favorites.length; i++){ |
||||
|
minusList.append( $('<div data-board="'+i+'" style="cursor: pointer; margin-right: 5px">-</div>').on('click', function(e){removeBoard($(this).data('board'));}) ); |
||||
|
} |
||||
|
|
||||
|
//Help message so people understand how sorting boards works
|
||||
|
$("<span>"+_("Drag the boards to sort them.")+"</span><br><br>").appendTo(Options.get_tab('fav-tab').content); |
||||
|
|
||||
|
//Adding list of boards and minus symbols to remove boards with
|
||||
|
$(minusList).appendTo(Options.get_tab('fav-tab').content); //Adding the list of minus symbols to the tab
|
||||
|
$(favList).appendTo(Options.get_tab('fav-tab').content); //Adding the list of favorite boards to the tab
|
||||
|
|
||||
|
//Adding spacing and text box to right boards into
|
||||
|
var addDiv = $("<div id='favs-add-board'>"); |
||||
|
|
||||
|
var plusBox = $("<input id=\"plusBox\" type=\"text\">").appendTo(addDiv); |
||||
|
plusBox.keydown(function( event ) { |
||||
|
if(event.keyCode == 13){ |
||||
|
$("#plus").click(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
//Adding plus symbol to use to add board
|
||||
|
$("<div id=\"plus\">+</div>").css({ |
||||
|
cursor: "pointer", |
||||
|
color: "#0000FF" |
||||
|
}).on('click', function(e){addBoard()}).appendTo(addDiv); |
||||
|
|
||||
|
addDiv.appendTo(Options.get_tab('fav-tab').content); //Adding the plus button
|
||||
|
|
||||
|
favList.sortable(); //Making boards with sortable id use the sortable jquery function
|
||||
|
favList.on('sortstop', function() { |
||||
|
favorites = generateList(); |
||||
|
localStorage.favorites = JSON.stringify(favorites); |
||||
|
add_favorites(); |
||||
|
}); |
||||
|
}); |
@ -0,0 +1,852 @@ |
|||||
|
if (active_page === 'thread' || active_page === 'index' || active_page === 'catalog' || active_page === 'ukko') { |
||||
|
$(document).on('menu_ready', function () { |
||||
|
'use strict'; |
||||
|
|
||||
|
// returns blacklist object from storage
|
||||
|
function getList() { |
||||
|
return JSON.parse(localStorage.postFilter); |
||||
|
} |
||||
|
|
||||
|
// stores blacklist into storage and reruns the filter
|
||||
|
function setList(blacklist) { |
||||
|
localStorage.postFilter = JSON.stringify(blacklist); |
||||
|
$(document).trigger('filter_page'); |
||||
|
} |
||||
|
|
||||
|
// unit: seconds
|
||||
|
function timestamp() { |
||||
|
return Math.floor((new Date()).getTime() / 1000); |
||||
|
} |
||||
|
|
||||
|
function initList(list, boardId, threadId) { |
||||
|
if (typeof list.postFilter[boardId] == 'undefined') { |
||||
|
list.postFilter[boardId] = {}; |
||||
|
list.nextPurge[boardId] = {}; |
||||
|
} |
||||
|
if (typeof list.postFilter[boardId][threadId] == 'undefined') { |
||||
|
list.postFilter[boardId][threadId] = []; |
||||
|
} |
||||
|
list.nextPurge[boardId][threadId] = {timestamp: timestamp(), interval: 86400}; // 86400 seconds == 1 day
|
||||
|
} |
||||
|
|
||||
|
function addFilter(type, value, useRegex) { |
||||
|
var list = getList(); |
||||
|
var filter = list.generalFilter; |
||||
|
var obj = { |
||||
|
type: type, |
||||
|
value: value, |
||||
|
regex: useRegex |
||||
|
}; |
||||
|
|
||||
|
for (var i=0; i<filter.length; i++) { |
||||
|
if (filter[i].type == type && filter[i].value == value && filter[i].regex == useRegex) |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
filter.push(obj); |
||||
|
setList(list); |
||||
|
drawFilterList(); |
||||
|
} |
||||
|
|
||||
|
function removeFilter(type, value, useRegex) { |
||||
|
var list = getList(); |
||||
|
var filter = list.generalFilter; |
||||
|
|
||||
|
for (var i=0; i<filter.length; i++) { |
||||
|
if (filter[i].type == type && filter[i].value == value && filter[i].regex == useRegex) { |
||||
|
filter.splice(i, 1); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
setList(list); |
||||
|
drawFilterList(); |
||||
|
} |
||||
|
|
||||
|
function nameSpanToString(el) { |
||||
|
var s = ''; |
||||
|
|
||||
|
$.each($(el).contents(), function(k,v) { |
||||
|
if (v.nodeName === 'IMG') |
||||
|
s=s+$(v).attr('alt') |
||||
|
|
||||
|
if (v.nodeName === '#text') |
||||
|
s=s+v.nodeValue |
||||
|
}); |
||||
|
return s.trim(); |
||||
|
} |
||||
|
|
||||
|
var blacklist = { |
||||
|
add: { |
||||
|
post: function (boardId, threadId, postId, hideReplies) { |
||||
|
var list = getList(); |
||||
|
var filter = list.postFilter; |
||||
|
|
||||
|
initList(list, boardId, threadId); |
||||
|
|
||||
|
for (var i in filter[boardId][threadId]) { |
||||
|
if (filter[boardId][threadId][i].post == postId) return; |
||||
|
} |
||||
|
filter[boardId][threadId].push({ |
||||
|
post: postId, |
||||
|
hideReplies: hideReplies |
||||
|
}); |
||||
|
setList(list); |
||||
|
}, |
||||
|
uid: function (boardId, threadId, uniqueId, hideReplies) { |
||||
|
var list = getList(); |
||||
|
var filter = list.postFilter; |
||||
|
|
||||
|
initList(list, boardId, threadId); |
||||
|
|
||||
|
for (var i in filter[boardId][threadId]) { |
||||
|
if (filter[boardId][threadId][i].uid == uniqueId) return; |
||||
|
} |
||||
|
filter[boardId][threadId].push({ |
||||
|
uid: uniqueId, |
||||
|
hideReplies: hideReplies |
||||
|
}); |
||||
|
setList(list); |
||||
|
} |
||||
|
}, |
||||
|
remove: { |
||||
|
post: function (boardId, threadId, postId) { |
||||
|
var list = getList(); |
||||
|
var filter = list.postFilter; |
||||
|
|
||||
|
// thread already pruned
|
||||
|
if (typeof filter[boardId] == 'undefined' || typeof filter[boardId][threadId] == 'undefined') |
||||
|
return; |
||||
|
|
||||
|
for (var i=0; i<filter[boardId][threadId].length; i++) { |
||||
|
if (filter[boardId][threadId][i].post == postId) { |
||||
|
filter[boardId][threadId].splice(i, 1); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if ($.isEmptyObject(filter[boardId][threadId])) { |
||||
|
delete filter[boardId][threadId]; |
||||
|
delete list.nextPurge[boardId][threadId]; |
||||
|
|
||||
|
if ($.isEmptyObject(filter[boardId])) { |
||||
|
delete filter[boardId]; |
||||
|
delete list.nextPurge[boardId]; |
||||
|
} |
||||
|
} |
||||
|
setList(list); |
||||
|
}, |
||||
|
uid: function (boardId, threadId, uniqueId) { |
||||
|
var list = getList(); |
||||
|
var filter = list.postFilter; |
||||
|
|
||||
|
// thread already pruned
|
||||
|
if (typeof filter[boardId] == 'undefined' || typeof filter[boardId][threadId] == 'undefined') |
||||
|
return; |
||||
|
|
||||
|
for (var i=0; i<filter[boardId][threadId].length; i++) { |
||||
|
if (filter[boardId][threadId][i].uid == uniqueId) { |
||||
|
filter[boardId][threadId].splice(i, 1); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if ($.isEmptyObject(filter[boardId][threadId])) { |
||||
|
delete filter[boardId][threadId]; |
||||
|
delete list.nextPurge[boardId][threadId]; |
||||
|
|
||||
|
if ($.isEmptyObject(filter[boardId])) { |
||||
|
delete filter[boardId]; |
||||
|
delete list.nextPurge[boardId]; |
||||
|
} |
||||
|
} |
||||
|
setList(list); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
/* |
||||
|
* hide/show the specified thread/post |
||||
|
*/ |
||||
|
function hide(ele) { |
||||
|
var $ele = $(ele); |
||||
|
|
||||
|
if ($(ele).data('hidden')) |
||||
|
return; |
||||
|
|
||||
|
$(ele).data('hidden', true); |
||||
|
if ($ele.hasClass('op')) { |
||||
|
$ele.parent().find('.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(); |
||||
|
} |
||||
|
} |
||||
|
function show(ele) { |
||||
|
var $ele = $(ele); |
||||
|
|
||||
|
$(ele).data('hidden', false); |
||||
|
if ($ele.hasClass('op')) { |
||||
|
$ele.parent().find('.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(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* create filter menu when the button is clicked |
||||
|
*/ |
||||
|
function initPostMenu(pageData) { |
||||
|
var Menu = window.Menu; |
||||
|
var submenu; |
||||
|
Menu.add_item('filter-menu-hide', _('Hide post')); |
||||
|
Menu.add_item('filter-menu-unhide', _('Unhide post')); |
||||
|
|
||||
|
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')); |
||||
|
submenu.add_item('filter-add-id-plus', _('ID +'), _('Hide ID and all replies')); |
||||
|
submenu.add_item('filter-add-name', _('Name')); |
||||
|
submenu.add_item('filter-add-trip', _('Tripcode')); |
||||
|
|
||||
|
submenu = Menu.add_submenu('filter-menu-remove', _('Remove filter')); |
||||
|
submenu.add_item('filter-remove-id', _('ID')); |
||||
|
submenu.add_item('filter-remove-name', _('Name')); |
||||
|
submenu.add_item('filter-remove-trip', _('Tripcode')); |
||||
|
|
||||
|
Menu.onclick(function (e, $buffer) { |
||||
|
var ele = e.target.parentElement.parentElement; |
||||
|
var $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(); |
||||
|
if (pageData.hasUID) { |
||||
|
var postUid = $ele.find('.poster_id').text(); |
||||
|
} |
||||
|
|
||||
|
var postName; |
||||
|
var postTrip = ''; |
||||
|
if (!pageData.forcedAnon) { |
||||
|
postName = (typeof $ele.find('.name').contents()[0] == 'undefined') ? '' : nameSpanToString($ele.find('.name')[0]); |
||||
|
postTrip = $ele.find('.trip').text(); |
||||
|
} |
||||
|
|
||||
|
/* display logic and bind click handlers |
||||
|
*/ |
||||
|
|
||||
|
// unhide button
|
||||
|
if ($ele.data('hidden')) { |
||||
|
$buffer.find('#filter-menu-unhide').click(function () { |
||||
|
// if hidden due to post id, remove it from blacklist
|
||||
|
// otherwise just show this post
|
||||
|
blacklist.remove.post(boardId, threadId, postId); |
||||
|
show(ele); |
||||
|
}); |
||||
|
$buffer.find('#filter-menu-hide').addClass('hidden'); |
||||
|
} else { |
||||
|
$buffer.find('#filter-menu-unhide').addClass('hidden'); |
||||
|
$buffer.find('#filter-menu-hide').click(function () { |
||||
|
blacklist.add.post(boardId, threadId, postId, false); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// post id
|
||||
|
if (!$ele.data('hiddenByPost')) { |
||||
|
$buffer.find('#filter-add-post-plus').click(function () { |
||||
|
blacklist.add.post(boardId, threadId, postId, true); |
||||
|
}); |
||||
|
} else { |
||||
|
$buffer.find('#filter-add-post-plus').addClass('hidden'); |
||||
|
} |
||||
|
|
||||
|
// UID
|
||||
|
if (pageData.hasUID && !$ele.data('hiddenByUid')) { |
||||
|
$buffer.find('#filter-add-id').click(function () { |
||||
|
blacklist.add.uid(boardId, threadId, postUid, false); |
||||
|
}); |
||||
|
$buffer.find('#filter-add-id-plus').click(function () { |
||||
|
blacklist.add.uid(boardId, threadId, postUid, true); |
||||
|
}); |
||||
|
|
||||
|
$buffer.find('#filter-remove-id').addClass('hidden'); |
||||
|
} else if (pageData.hasUID) { |
||||
|
$buffer.find('#filter-remove-id').click(function () { |
||||
|
blacklist.remove.uid(boardId, threadId, postUid); |
||||
|
}); |
||||
|
|
||||
|
$buffer.find('#filter-add-id').addClass('hidden'); |
||||
|
$buffer.find('#filter-add-id-plus').addClass('hidden'); |
||||
|
} else { |
||||
|
// board doesn't use UID
|
||||
|
$buffer.find('#filter-add-id').addClass('hidden'); |
||||
|
$buffer.find('#filter-add-id-plus').addClass('hidden'); |
||||
|
$buffer.find('#filter-remove-id').addClass('hidden'); |
||||
|
} |
||||
|
|
||||
|
// name
|
||||
|
if (!pageData.forcedAnon && !$ele.data('hiddenByName')) { |
||||
|
$buffer.find('#filter-add-name').click(function () { |
||||
|
addFilter('name', postName, false); |
||||
|
}); |
||||
|
|
||||
|
$buffer.find('#filter-remove-name').addClass('hidden'); |
||||
|
} else if (!pageData.forcedAnon) { |
||||
|
$buffer.find('#filter-remove-name').click(function () { |
||||
|
removeFilter('name', postName, false); |
||||
|
}); |
||||
|
|
||||
|
$buffer.find('#filter-add-name').addClass('hidden'); |
||||
|
} else { |
||||
|
// board has forced anon
|
||||
|
$buffer.find('#filter-remove-name').addClass('hidden'); |
||||
|
$buffer.find('#filter-add-name').addClass('hidden'); |
||||
|
} |
||||
|
|
||||
|
// tripcode
|
||||
|
if (!pageData.forcedAnon && !$ele.data('hiddenByTrip') && postTrip !== '') { |
||||
|
$buffer.find('#filter-add-trip').click(function () { |
||||
|
addFilter('trip', postTrip, false); |
||||
|
}); |
||||
|
|
||||
|
$buffer.find('#filter-remove-trip').addClass('hidden'); |
||||
|
} else if (!pageData.forcedAnon && postTrip !== '') { |
||||
|
$buffer.find('#filter-remove-trip').click(function () { |
||||
|
removeFilter('trip', postTrip, false); |
||||
|
}); |
||||
|
|
||||
|
$buffer.find('#filter-add-trip').addClass('hidden'); |
||||
|
} else { |
||||
|
// board has forced anon
|
||||
|
$buffer.find('#filter-remove-trip').addClass('hidden'); |
||||
|
$buffer.find('#filter-add-trip').addClass('hidden'); |
||||
|
} |
||||
|
|
||||
|
/* hide sub menus if all items are hidden |
||||
|
*/ |
||||
|
if (!$buffer.find('#filter-menu-remove > ul').children().not('.hidden').length) { |
||||
|
$buffer.find('#filter-menu-remove').addClass('hidden'); |
||||
|
} |
||||
|
if (!$buffer.find('#filter-menu-add > ul').children().not('.hidden').length) { |
||||
|
$buffer.find('#filter-menu-add').addClass('hidden'); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* hide/unhide thread on index view |
||||
|
*/ |
||||
|
function quickToggle(ele, threadId, pageData) { |
||||
|
/*if ($(ele).find('.hide-thread-link').length) |
||||
|
$('.hide-thread-link').remove();*/ |
||||
|
|
||||
|
if ($(ele).hasClass('op') && !$(ele).find('.hide-thread-link').length) { |
||||
|
$('<a class="hide-thread-link" style="float:left;margin-right:5px" href="javascript:void(0)">[' + ($(ele).data('hidden') ? '+' : '–') + ']</a>') |
||||
|
.insertBefore($(ele).find(':not(h2,h2 *):first')) |
||||
|
.click(function() { |
||||
|
var postId = $(ele).find('.post_no').not('[id]').text(); |
||||
|
var hidden = $(ele).data('hidden'); |
||||
|
var boardId = $(ele).parents('.thread').data('board'); |
||||
|
|
||||
|
if (hidden) { |
||||
|
blacklist.remove.post(boardId, threadId, postId, false); |
||||
|
$(this).html('[–]'); |
||||
|
} else { |
||||
|
blacklist.add.post(boardId, threadId, postId, false); |
||||
|
$(this).text('[+]'); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* determine whether the reply post should be hidden |
||||
|
* - applies to all posts on page load or filtering rule change |
||||
|
* - apply to new posts on thread updates |
||||
|
* - must explicitly set the state of each attributes because filter will reapply to all posts after filtering rule change |
||||
|
*/ |
||||
|
function filter(post, threadId, pageData) { |
||||
|
var $post = $(post); |
||||
|
|
||||
|
var list = getList(); |
||||
|
var postId = $post.find('.post_no').not('[id]').text(); |
||||
|
var name, trip, uid, subject, comment; |
||||
|
var i, length, array, rule, pattern; // temp variables
|
||||
|
|
||||
|
var boardId = $post.data('board'); |
||||
|
if (!boardId) boardId = $post.parents('.thread').data('board'); |
||||
|
|
||||
|
var localList = pageData.localList; |
||||
|
var noReplyList = pageData.noReplyList; |
||||
|
var hasUID = pageData.hasUID; |
||||
|
var forcedAnon = pageData.forcedAnon; |
||||
|
|
||||
|
var hasTrip = ($post.find('.trip').length > 0); |
||||
|
var hasSub = ($post.find('.subject').length > 0); |
||||
|
|
||||
|
$post.data('hidden', false); |
||||
|
$post.data('hiddenByUid', false); |
||||
|
$post.data('hiddenByPost', false); |
||||
|
$post.data('hiddenByName', false); |
||||
|
$post.data('hiddenByTrip', false); |
||||
|
$post.data('hiddenBySubject', false); |
||||
|
$post.data('hiddenByComment', false); |
||||
|
|
||||
|
// add post with matched UID to localList
|
||||
|
if (hasUID && |
||||
|
typeof list.postFilter[boardId] != 'undefined' && |
||||
|
typeof list.postFilter[boardId][threadId] != 'undefined') { |
||||
|
uid = $post.find('.poster_id').text(); |
||||
|
array = list.postFilter[boardId][threadId]; |
||||
|
|
||||
|
for (i=0; i<array.length; i++) { |
||||
|
if (array[i].uid == uid) { |
||||
|
$post.data('hiddenByUid', true); |
||||
|
localList.push(postId); |
||||
|
if (array[i].hideReplies) noReplyList.push(postId); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// match localList
|
||||
|
if (localList.length) { |
||||
|
if ($.inArray(postId, localList) != -1) { |
||||
|
if ($post.data('hiddenByUid') !== true) $post.data('hiddenByPost', true); |
||||
|
hide(post); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// matches generalFilter
|
||||
|
if (!forcedAnon) |
||||
|
name = (typeof $post.find('.name').contents()[0] == 'undefined') ? '' : nameSpanToString($post.find('.name')[0]); |
||||
|
if (!forcedAnon && hasTrip) |
||||
|
trip = $post.find('.trip').text(); |
||||
|
if (hasSub) |
||||
|
subject = $post.find('.subject').text(); |
||||
|
|
||||
|
array = $post.find('.body').contents().filter(function () {if ($(this).text() !== '') return true;}).toArray(); |
||||
|
array = $.map(array, function (ele) { |
||||
|
return $(ele).text().trim(); |
||||
|
}); |
||||
|
comment = array.join(' '); |
||||
|
|
||||
|
|
||||
|
for (i = 0, length = list.generalFilter.length; i < length; i++) { |
||||
|
rule = list.generalFilter[i]; |
||||
|
|
||||
|
if (rule.regex) { |
||||
|
pattern = new RegExp(rule.value); |
||||
|
switch (rule.type) { |
||||
|
case 'name': |
||||
|
if (!forcedAnon && pattern.test(name)) { |
||||
|
$post.data('hiddenByName', true); |
||||
|
hide(post); |
||||
|
} |
||||
|
break; |
||||
|
case 'trip': |
||||
|
if (!forcedAnon && hasTrip && pattern.test(trip)) { |
||||
|
$post.data('hiddenByTrip', true); |
||||
|
hide(post); |
||||
|
} |
||||
|
break; |
||||
|
case 'sub': |
||||
|
if (hasSub && pattern.test(subject)) { |
||||
|
$post.data('hiddenBySubject', true); |
||||
|
hide(post); |
||||
|
} |
||||
|
break; |
||||
|
case 'com': |
||||
|
if (pattern.test(comment)) { |
||||
|
$post.data('hiddenByComment', true); |
||||
|
hide(post); |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
} else { |
||||
|
switch (rule.type) { |
||||
|
case 'name': |
||||
|
if (!forcedAnon && rule.value == name) { |
||||
|
$post.data('hiddenByName', true); |
||||
|
hide(post); |
||||
|
} |
||||
|
break; |
||||
|
case 'trip': |
||||
|
if (!forcedAnon && hasTrip && rule.value == trip) { |
||||
|
$post.data('hiddenByTrip', true); |
||||
|
hide(post); |
||||
|
} |
||||
|
break; |
||||
|
case 'sub': |
||||
|
pattern = new RegExp('\\b'+ rule.value+ '\\b'); |
||||
|
if (hasSub && pattern.test(subject)) { |
||||
|
$post.data('hiddenBySubject', true); |
||||
|
hide(post); |
||||
|
} |
||||
|
break; |
||||
|
case 'com': |
||||
|
pattern = new RegExp('\\b'+ rule.value+ '\\b'); |
||||
|
if (pattern.test(comment)) { |
||||
|
$post.data('hiddenByComment', true); |
||||
|
hide(post); |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// check for link to filtered posts
|
||||
|
$post.find('.body a').not('[rel="nofollow"]').each(function () { |
||||
|
var replyId = $(this).text().match(/^>>(\d+)$/); |
||||
|
|
||||
|
if (!replyId) |
||||
|
return; |
||||
|
|
||||
|
replyId = replyId[1]; |
||||
|
if ($.inArray(replyId, noReplyList) != -1) { |
||||
|
hide(post); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// post didn't match any filters
|
||||
|
if (!$post.data('hidden')) { |
||||
|
show(post); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* (re)runs the filter on the entire page |
||||
|
*/ |
||||
|
function filterPage(pageData) { |
||||
|
var list = getList(); |
||||
|
|
||||
|
if (active_page != 'catalog') { |
||||
|
|
||||
|
// empty the local and no-reply list
|
||||
|
pageData.localList = []; |
||||
|
pageData.noReplyList = []; |
||||
|
|
||||
|
$('.thread').each(function () { |
||||
|
var $thread = $(this); |
||||
|
// disregard the hidden threads constructed by post-hover.js
|
||||
|
if ($thread.css('display') == 'none') |
||||
|
return; |
||||
|
|
||||
|
var threadId = $thread.attr('id').replace('thread_', ''); |
||||
|
var boardId = $thread.data('board'); |
||||
|
var op = $thread.children('.op')[0]; |
||||
|
var i, array; // temp variables
|
||||
|
|
||||
|
// add posts to localList and noReplyList
|
||||
|
if (typeof list.postFilter[boardId] != 'undefined' && typeof list.postFilter[boardId][threadId] != 'undefined') { |
||||
|
array = list.postFilter[boardId][threadId]; |
||||
|
for (i=0; i<array.length; i++) { |
||||
|
if ( typeof array[i].post == 'undefined') |
||||
|
continue; |
||||
|
|
||||
|
pageData.localList.push(array[i].post); |
||||
|
if (array[i].hideReplies) pageData.noReplyList.push(array[i].post); |
||||
|
} |
||||
|
} |
||||
|
// run filter on OP
|
||||
|
filter(op, threadId, pageData); |
||||
|
quickToggle(op, threadId, pageData); |
||||
|
|
||||
|
// iterate filter over each post
|
||||
|
if (!$(op).data('hidden') || active_page == 'thread') { |
||||
|
$thread.find('.reply').not('.hidden').each(function () { |
||||
|
filter(this, threadId, pageData); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
} else { |
||||
|
var postFilter = list.postFilter[pageData.boardId]; |
||||
|
var $collection = $('.mix'); |
||||
|
|
||||
|
if ($.isEmptyObject(postFilter)) |
||||
|
return; |
||||
|
|
||||
|
// for each thread that has filtering rules
|
||||
|
// check if filter contains thread OP and remove the thread from catalog
|
||||
|
$.each(postFilter, function (key, thread) { |
||||
|
var threadId = key; |
||||
|
$.each(thread, function () { |
||||
|
if (this.post == threadId) { |
||||
|
$collection.filter('[data-id='+ threadId +']').remove(); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function initStyle() { |
||||
|
var $ele, cssStyle, cssString; |
||||
|
|
||||
|
$ele = $('<div>').addClass('post reply').hide().appendTo('body'); |
||||
|
cssStyle = $ele.css(['background-color', 'border-color']); |
||||
|
cssStyle.hoverBg = $('body').css('background-color'); |
||||
|
$ele.remove(); |
||||
|
|
||||
|
cssString = '\n/*** Generated by post-filter ***/\n' + |
||||
|
'#filter-control input[type=text] {width: 130px;}' + |
||||
|
'#filter-control input[type=checkbox] {vertical-align: middle;}' + |
||||
|
'#filter-control #clear {float: right;}\n' + |
||||
|
'#filter-container {margin-top: 20px; border: 1px solid; height: 270px; overflow: auto;}\n' + |
||||
|
'#filter-list {width: 100%; border-collapse: collapse;}\n' + |
||||
|
'#filter-list th {text-align: center; height: 20px; font-size: 14px; border-bottom: 1px solid;}\n' + |
||||
|
'#filter-list th:nth-child(1) {text-align: center; width: 70px;}\n' + |
||||
|
'#filter-list th:nth-child(2) {text-align: left;}\n' + |
||||
|
'#filter-list th:nth-child(3) {text-align: center; width: 58px;}\n' + |
||||
|
'#filter-list tr:not(#header) {height: 22px;}\n' + |
||||
|
'#filter-list tr:nth-child(even) {background-color:rgba(255, 255, 255, 0.5);}\n' + |
||||
|
'#filter-list td:nth-child(1) {text-align: center; width: 70px;}\n' + |
||||
|
'#filter-list td:nth-child(3) {text-align: center; width: 58px;}\n' + |
||||
|
'#confirm {text-align: right; margin-bottom: -18px; padding-top: 2px; font-size: 14px; color: #FF0000;}'; |
||||
|
|
||||
|
if (!$('style.generated-css').length) $('<style class="generated-css">').appendTo('head'); |
||||
|
$('style.generated-css').html($('style.generated-css').html() + cssString); |
||||
|
} |
||||
|
|
||||
|
function drawFilterList() { |
||||
|
var list = getList().generalFilter; |
||||
|
var $ele = $('#filter-list'); |
||||
|
var $row, i, length, obj, val; |
||||
|
|
||||
|
var typeName = { |
||||
|
name: 'name', |
||||
|
trip: 'tripcode', |
||||
|
sub: 'subject', |
||||
|
com: 'comment' |
||||
|
}; |
||||
|
|
||||
|
$ele.empty(); |
||||
|
|
||||
|
$ele.append('<tr id="header"><th>Type</th><th>Content</th><th>Remove</th></tr>'); |
||||
|
for (i = 0, length = list.length; i < length; i++) { |
||||
|
obj = list[i]; |
||||
|
|
||||
|
// display formatting
|
||||
|
val = (obj.regex) ? '/'+ obj.value +'/' : obj.value; |
||||
|
|
||||
|
$row = $('<tr>'); |
||||
|
$row.append( |
||||
|
'<td>'+ typeName[obj.type] +'</td>', |
||||
|
'<td>'+ val +'</td>', |
||||
|
$('<td>').append( |
||||
|
$('<a>').html('X') |
||||
|
.addClass('del-btn') |
||||
|
.attr('href', '#') |
||||
|
.data('type', obj.type) |
||||
|
.data('val', obj.value) |
||||
|
.data('useRegex', obj.regex) |
||||
|
) |
||||
|
); |
||||
|
$ele.append($row); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function initOptionsPanel() { |
||||
|
if (window.Options && !Options.get_tab('filter')) { |
||||
|
Options.add_tab('filter', 'list', _('Filters')); |
||||
|
Options.extend_tab('filter', |
||||
|
'<div id="filter-control">' + |
||||
|
'<select>' + |
||||
|
'<option value="name">'+_('Name')+'</option>' + |
||||
|
'<option value="trip">'+_('Tripcode')+'</option>' + |
||||
|
'<option value="sub">'+_('Subject')+'</option>' + |
||||
|
'<option value="com">'+_('Comment')+'</option>' + |
||||
|
'</select>' + |
||||
|
'<input type="text">' + |
||||
|
'<input type="checkbox">' + |
||||
|
'regex ' + |
||||
|
'<button id="set-filter">'+_('Add')+'</button>' + |
||||
|
'<button id="clear">'+_('Clear all filters')+'</button>' + |
||||
|
'<div id="confirm" class="hidden">' + |
||||
|
_('This will clear all filtering rules including hidden posts.')+' <a id="confirm-y" href="#">'+_('yes')+'</a> | <a id="confirm-n" href="#">'+_('no')+'</a>' + |
||||
|
'</div>' + |
||||
|
'</div>' + |
||||
|
'<div id="filter-container"><table id="filter-list"></table></div>' |
||||
|
); |
||||
|
drawFilterList(); |
||||
|
|
||||
|
// control buttons
|
||||
|
$('#filter-control').on('click', '#set-filter', function () { |
||||
|
var type = $('#filter-control select option:selected').val(); |
||||
|
var value = $('#filter-control input[type=text]').val(); |
||||
|
var useRegex = $('#filter-control input[type=checkbox]').prop('checked'); |
||||
|
|
||||
|
//clear the input form
|
||||
|
$('#filter-control input[type=text]').val(''); |
||||
|
|
||||
|
addFilter(type, value, useRegex); |
||||
|
drawFilterList(); |
||||
|
}); |
||||
|
$('#filter-control').on('click', '#clear', function () { |
||||
|
$('#filter-control #clear').addClass('hidden'); |
||||
|
$('#filter-control #confirm').removeClass('hidden'); |
||||
|
}); |
||||
|
$('#filter-control').on('click', '#confirm-y', function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
$('#filter-control #clear').removeClass('hidden'); |
||||
|
$('#filter-control #confirm').addClass('hidden'); |
||||
|
setList({ |
||||
|
generalFilter: [], |
||||
|
postFilter: {}, |
||||
|
nextPurge: {}, |
||||
|
lastPurge: timestamp() |
||||
|
}); |
||||
|
drawFilterList(); |
||||
|
}); |
||||
|
$('#filter-control').on('click', '#confirm-n', function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
$('#filter-control #clear').removeClass('hidden'); |
||||
|
$('#filter-control #confirm').addClass('hidden'); |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
// remove button
|
||||
|
$('#filter-list').on('click', '.del-btn', function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
var $ele = $(e.target); |
||||
|
var type = $ele.data('type'); |
||||
|
var val = $ele.data('val'); |
||||
|
var useRegex = $ele.data('useRegex'); |
||||
|
|
||||
|
removeFilter(type, val, useRegex); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* clear out pruned threads |
||||
|
*/ |
||||
|
function purge() { |
||||
|
var list = getList(); |
||||
|
var board, thread, boardId, threadId; |
||||
|
var deferred; |
||||
|
var requestArray = []; |
||||
|
|
||||
|
var successHandler = function (boardId, threadId) { |
||||
|
return function () { |
||||
|
// thread still alive, keep it in the list and increase the time between checks.
|
||||
|
var list = getList(); |
||||
|
var thread = list.nextPurge[boardId][threadId]; |
||||
|
|
||||
|
thread.timestamp = timestamp(); |
||||
|
thread.interval = Math.floor(thread.interval * 1.5); |
||||
|
setList(list); |
||||
|
}; |
||||
|
}; |
||||
|
var errorHandler = function (boardId, threadId) { |
||||
|
return function (xhr) { |
||||
|
if (xhr.status == 404) { |
||||
|
var list = getList(); |
||||
|
|
||||
|
delete list.nextPurge[boardId][threadId]; |
||||
|
delete list.postFilter[boardId][threadId]; |
||||
|
if ($.isEmptyObject(list.nextPurge[boardId])) delete list.nextPurge[boardId]; |
||||
|
if ($.isEmptyObject(list.postFilter[boardId])) delete list.postFilter[boardId]; |
||||
|
setList(list); |
||||
|
} |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
if ((timestamp() - list.lastPurge) < 86400) // less than 1 day
|
||||
|
return; |
||||
|
|
||||
|
for (boardId in list.nextPurge) { |
||||
|
board = list.nextPurge[boardId]; |
||||
|
for (threadId in board) { |
||||
|
thread = board[threadId]; |
||||
|
if (timestamp() > (thread.timestamp + thread.interval)) { |
||||
|
// check if thread is pruned
|
||||
|
deferred = $.ajax({ |
||||
|
cache: false, |
||||
|
url: '/'+ boardId +'/res/'+ threadId +'.json', |
||||
|
success: successHandler(boardId, threadId), |
||||
|
error: errorHandler(boardId, threadId) |
||||
|
}); |
||||
|
requestArray.push(deferred); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// when all requests complete
|
||||
|
$.when.apply($, requestArray).always(function () { |
||||
|
var list = getList(); |
||||
|
list.lastPurge = timestamp(); |
||||
|
setList(list); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function init() { |
||||
|
if (typeof localStorage.postFilter === 'undefined') { |
||||
|
localStorage.postFilter = JSON.stringify({ |
||||
|
generalFilter: [], |
||||
|
postFilter: {}, |
||||
|
nextPurge: {}, |
||||
|
lastPurge: timestamp() |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
var pageData = { |
||||
|
boardId: board_name, // get the id from the global variable
|
||||
|
localList: [], // all the blacklisted post IDs or UIDs that apply to the current page
|
||||
|
noReplyList: [], // any posts that replies to the contents of this list shall be hidden
|
||||
|
hasUID: (document.getElementsByClassName('poster_id').length > 0), |
||||
|
forcedAnon: ($('th:contains(Name)').length === 0) // tests by looking for the Name label on the reply form
|
||||
|
}; |
||||
|
|
||||
|
initStyle(); |
||||
|
initOptionsPanel(); |
||||
|
initPostMenu(pageData); |
||||
|
filterPage(pageData); |
||||
|
|
||||
|
// on new posts
|
||||
|
$(document).on('new_post', function (e, post) { |
||||
|
var threadId; |
||||
|
|
||||
|
if ($(post).hasClass('reply')) { |
||||
|
threadId = $(post).parents('.thread').attr('id').replace('thread_', ''); |
||||
|
} else { |
||||
|
threadId = $(post).attr('id').replace('thread_', ''); |
||||
|
post = $(post).children('.op')[0]; |
||||
|
} |
||||
|
|
||||
|
filter(post, threadId, pageData); |
||||
|
quickToggle(post, threadId, pageData); |
||||
|
}); |
||||
|
|
||||
|
$(document).on('filter_page', function () { |
||||
|
filterPage(pageData); |
||||
|
}); |
||||
|
|
||||
|
// shift+click on catalog to hide thread
|
||||
|
if (active_page == 'catalog') { |
||||
|
$(document).on('click', '.mix', function(e) { |
||||
|
if (e.shiftKey) { |
||||
|
var threadId = $(this).data('id').toString(); |
||||
|
var postId = threadId; |
||||
|
blacklist.add.post(pageData.boardId, threadId, postId, false); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// clear out the old threads
|
||||
|
purge(); |
||||
|
} |
||||
|
init(); |
||||
|
}); |
||||
|
|
||||
|
if (typeof window.Menu !== "undefined") { |
||||
|
$(document).trigger('menu_ready'); |
||||
|
} |
||||
|
} |
@ -0,0 +1,211 @@ |
|||||
|
/* |
||||
|
* post-menu.js - adds dropdown menu to posts |
||||
|
* |
||||
|
* Creates a global Menu object with four public methods: |
||||
|
* |
||||
|
* Menu.onclick(fnc) |
||||
|
* registers a function to be executed after button click, before the menu is displayed |
||||
|
* Menu.add_item(id, text[, title]) |
||||
|
* adds an item to the top level of menu |
||||
|
* Menu.add_submenu(id, text) |
||||
|
* creates and returns a List object through which to manipulate the content of the submenu |
||||
|
* Menu.get_submenu(id) |
||||
|
* returns the submenu with the specified id from the top level menu |
||||
|
* |
||||
|
* The List object contains all the methods from Menu except onclick() |
||||
|
* |
||||
|
* Example usage: |
||||
|
* Menu.add_item('filter-menu-hide', 'Hide post'); |
||||
|
* Menu.add_item('filter-menu-unhide', 'Unhide post'); |
||||
|
* |
||||
|
* 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'; |
||||
|
*/ |
||||
|
$(document).ready(function () { |
||||
|
|
||||
|
var List = function (menuId, text) { |
||||
|
this.id = menuId; |
||||
|
this.text = text; |
||||
|
this.items = []; |
||||
|
|
||||
|
this.add_item = function (itemId, text, title) { |
||||
|
this.items.push(new Item(itemId, text, title)); |
||||
|
}; |
||||
|
this.list_items = function () { |
||||
|
var array = []; |
||||
|
var i, length, obj, $ele; |
||||
|
|
||||
|
if ($.isEmptyObject(this.items)) |
||||
|
return; |
||||
|
|
||||
|
length = this.items.length; |
||||
|
for (i = 0; i < length; i++) { |
||||
|
obj = this.items[i]; |
||||
|
|
||||
|
$ele = $('<li>', {id: obj.id}).text(obj.text); |
||||
|
if ('title' in obj) $ele.attr('title', obj.title); |
||||
|
|
||||
|
if (obj instanceof Item) { |
||||
|
$ele.addClass('post-item'); |
||||
|
} else { |
||||
|
$ele.addClass('post-submenu'); |
||||
|
|
||||
|
$ele.prepend(obj.list_items()); |
||||
|
$ele.append($('<span>', {class: 'post-menu-arrow'}).text('»')); |
||||
|
} |
||||
|
|
||||
|
array.push($ele); |
||||
|
} |
||||
|
|
||||
|
return $('<ul>').append(array); |
||||
|
}; |
||||
|
this.add_submenu = function (menuId, text) { |
||||
|
var ele = new List(menuId, text); |
||||
|
this.items.push(ele); |
||||
|
return ele; |
||||
|
}; |
||||
|
this.get_submenu = function (menuId) { |
||||
|
for (var i = 0; i < this.items.length; i++) { |
||||
|
if ((this.items[i] instanceof Item) || this.items[i].id != menuId) continue; |
||||
|
return this.items[i]; |
||||
|
} |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
var Item = function (itemId, text, title) { |
||||
|
this.id = itemId; |
||||
|
this.text = text; |
||||
|
|
||||
|
// optional
|
||||
|
if (typeof title != 'undefined') this.title = title; |
||||
|
}; |
||||
|
|
||||
|
function buildMenu(e) { |
||||
|
var pos = $(e.target).offset(); |
||||
|
var i, length; |
||||
|
|
||||
|
var $menu = $('<div class="post-menu"></div>').append(mainMenu.list_items()); |
||||
|
|
||||
|
// execute registered click handlers
|
||||
|
length = onclick_callbacks.length; |
||||
|
for (i = 0; i < length; i++) { |
||||
|
onclick_callbacks[i](e, $menu); |
||||
|
} |
||||
|
|
||||
|
// set menu position and append to page
|
||||
|
$menu.css({top: pos.top, left: pos.left + 20}); |
||||
|
$('body').append($menu); |
||||
|
} |
||||
|
|
||||
|
function addButton(post) { |
||||
|
var $ele = $(post); |
||||
|
$ele.find('input.delete').after( |
||||
|
$('<a>', {href: '#', class: 'post-btn', title: 'Post menu'}).text('▶') |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* * * * * * * * * * |
||||
|
Public methods |
||||
|
* * * * * * * * * */ |
||||
|
var Menu = {}; |
||||
|
var mainMenu = new List(); |
||||
|
var onclick_callbacks = []; |
||||
|
|
||||
|
Menu.onclick = function (fnc) { |
||||
|
onclick_callbacks.push(fnc); |
||||
|
}; |
||||
|
|
||||
|
Menu.add_item = function (itemId, text, title) { |
||||
|
mainMenu.add_item(itemId, text, title); |
||||
|
}; |
||||
|
|
||||
|
Menu.add_submenu = function (menuId, text) { |
||||
|
return mainMenu.add_submenu(menuId, text); |
||||
|
}; |
||||
|
|
||||
|
Menu.get_submenu = function (id) { |
||||
|
return mainMenu.get_submenu(id); |
||||
|
}; |
||||
|
|
||||
|
window.Menu = Menu; |
||||
|
|
||||
|
|
||||
|
/* * * * * * * * |
||||
|
Initialize |
||||
|
* * * * * * * */ |
||||
|
|
||||
|
/* Styling |
||||
|
*/ |
||||
|
var $ele, cssStyle, cssString; |
||||
|
|
||||
|
$ele = $('<div>').addClass('post reply').hide().appendTo('body'); |
||||
|
cssStyle = $ele.css(['border-top-color']); |
||||
|
cssStyle.hoverBg = $('body').css('background-color'); |
||||
|
$ele.remove(); |
||||
|
|
||||
|
cssString = |
||||
|
'\n/*** Generated by post-menu ***/\n' + |
||||
|
'.post-menu {position: absolute; font-size: 12px; line-height: 1.3em;}\n' + |
||||
|
'.post-menu ul {\n' + |
||||
|
' background-color: '+ cssStyle['border-top-color'] +'; border: 1px solid #666;\n' + |
||||
|
' list-style: none; padding: 0; margin: 0; white-space: nowrap;\n}\n' + |
||||
|
'.post-menu .post-submenu{white-space: normal; width: 90px;}' + |
||||
|
'.post-menu .post-submenu>ul{white-space: nowrap; width: auto;}' + |
||||
|
'.post-menu li {cursor: pointer; position: relative; padding: 4px 4px; vertical-align: middle;}\n' + |
||||
|
'.post-menu li:hover {background-color: '+ cssStyle.hoverBg +';}\n' + |
||||
|
'.post-menu ul ul {display: none; position: absolute;}\n' + |
||||
|
'.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:hover {opacity: 1;}\n' + |
||||
|
'.post-btn-open {transform: rotate(90deg);}\n'; |
||||
|
|
||||
|
if (!$('style.generated-css').length) $('<style class="generated-css">').appendTo('head'); |
||||
|
$('style.generated-css').html($('style.generated-css').html() + cssString); |
||||
|
|
||||
|
/* Add buttons |
||||
|
*/ |
||||
|
$('.reply:not(.hidden), .thread>.op').each(function () { |
||||
|
addButton(this); |
||||
|
}); |
||||
|
|
||||
|
/* event handlers |
||||
|
*/ |
||||
|
$('form[name=postcontrols]').on('click', '.post-btn', function (e) { |
||||
|
e.preventDefault(); |
||||
|
var post = e.target.parentElement.parentElement; |
||||
|
$('.post-menu').remove(); |
||||
|
|
||||
|
if ($(e.target).hasClass('post-btn-open')) { |
||||
|
$('.post-btn-open').removeClass('post-btn-open'); |
||||
|
} else { |
||||
|
// close previous button
|
||||
|
$('.post-btn-open').removeClass('post-btn-open'); |
||||
|
$(post).find('.post-btn').addClass('post-btn-open'); |
||||
|
|
||||
|
buildMenu(e); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
$(document).on('click', function (e){ |
||||
|
if ($(e.target).hasClass('post-btn') || $(e.target).hasClass('post-submenu')) |
||||
|
return; |
||||
|
|
||||
|
$('.post-menu').remove(); |
||||
|
$('.post-btn-open').removeClass('post-btn-open'); |
||||
|
}); |
||||
|
|
||||
|
// on new posts
|
||||
|
$(document).on('new_post', function (e, post) { |
||||
|
addButton(post); |
||||
|
}); |
||||
|
|
||||
|
$(document).trigger('menu_ready'); |
||||
|
}); |
@ -0,0 +1,24 @@ |
|||||
|
<?php |
||||
|
include 'inc/functions.php'; |
||||
|
include 'inc/mod/pages.php'; |
||||
|
|
||||
|
if (!isset($_GET['board']) || !preg_match("/{$config['board_regex']}/u", $_GET['board'])) { |
||||
|
http_response_code(400); |
||||
|
error('Bad board.'); |
||||
|
} |
||||
|
if (!openBoard($_GET['board'])) { |
||||
|
http_response_code(404); |
||||
|
error('No board.'); |
||||
|
} |
||||
|
|
||||
|
if ($config['public_logs'] == 0) error('This board has public logs disabled. Ask the board owner to enable it.'); |
||||
|
if ($config['public_logs'] == 1) $hide_names = false; |
||||
|
if ($config['public_logs'] == 2) $hide_names = true; |
||||
|
|
||||
|
if (!isset($_GET['page'])) { |
||||
|
$page = 1; |
||||
|
} else { |
||||
|
$page = (int)$_GET['page']; |
||||
|
}; |
||||
|
|
||||
|
mod_board_log($board['uri'], $page, $hide_names, true); |
@ -0,0 +1,19 @@ |
|||||
|
<?php |
||||
|
include 'inc/functions.php'; |
||||
|
$global = isset($_GET['global']); |
||||
|
$post = (isset($_GET['post']) ? $_GET['post'] : false); |
||||
|
$board = (isset($_GET['board']) ? $_GET['board'] : false); |
||||
|
|
||||
|
if (!$post || !preg_match('/^delete_\d+$/', $post) || !$board || !openBoard($board)) { |
||||
|
header('HTTP/1.1 400 Bad Request'); |
||||
|
error(_('Bad request.')); |
||||
|
} |
||||
|
|
||||
|
if ($config['report_captcha']) { |
||||
|
$captcha = generate_captcha($config['captcha']['extra']); |
||||
|
} else { |
||||
|
$captcha = null; |
||||
|
} |
||||
|
|
||||
|
$body = Element('report.html', ['global' => $global, 'post' => $post, 'board' => $board, 'captcha' => $captcha, 'config' => $config]); |
||||
|
echo Element('page.html', ['config' => $config, 'body' => $body]); |
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 348 KiB After Width: | Height: | Size: 377 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,5 @@ |
|||||
|
// Screen Readers |
||||
|
// ------------------------- |
||||
|
|
||||
|
.sr-only { .sr-only(); } |
||||
|
.sr-only-focusable { .sr-only-focusable(); } |
@ -0,0 +1,5 @@ |
|||||
|
// Screen Readers |
||||
|
// ------------------------- |
||||
|
|
||||
|
.sr-only { @include sr-only(); } |
||||
|
.sr-only-focusable { @include sr-only-focusable(); } |
@ -0,0 +1,249 @@ |
|||||
|
/** |
||||
|
* northboard.css |
||||
|
* for circleboard by kotiakrobaatti |
||||
|
*/ |
||||
|
|
||||
|
body { |
||||
|
background: #191919; |
||||
|
color: #d4d4d4; |
||||
|
font-size: 13px; |
||||
|
font: 12px/1.5em Verdana,"DejaVu Sans",Sans-serif; |
||||
|
} |
||||
|
|
||||
|
a:link, a:visited, .intro a.email { |
||||
|
color: #60a0dc !important; |
||||
|
text-decoration: none; |
||||
|
} |
||||
|
|
||||
|
a:link:hover { |
||||
|
outline: 0; |
||||
|
color: #82c2fe !important; |
||||
|
} |
||||
|
|
||||
|
a.post_no, a.watchThread { |
||||
|
color: #60a0dc; |
||||
|
} |
||||
|
|
||||
|
div.post.reply { |
||||
|
background: #343439; |
||||
|
border-color: #3070A9; |
||||
|
border-top: 1px solid #3070A9; |
||||
|
border-left: 1px solid #3070A9; |
||||
|
border-radius: 3px; |
||||
|
padding: 0px; |
||||
|
} |
||||
|
|
||||
|
div.post.reply.highlighted { |
||||
|
background: #44444f; |
||||
|
border: 3px dashed #3070a9; |
||||
|
} |
||||
|
|
||||
|
div.post.reply div.body a, .mentioned { |
||||
|
color: 60a0dc; |
||||
|
text-decoration: underline; |
||||
|
} |
||||
|
|
||||
|
div.post.reply div.body a:hover { |
||||
|
color: #82c2fe !important; |
||||
|
text-decoration: underline !important; |
||||
|
} |
||||
|
|
||||
|
div.body a:hover, a.watchThread:hover, a.email span.name:hover { |
||||
|
color: #82c2fe !important; |
||||
|
} |
||||
|
|
||||
|
.intro span.subject { |
||||
|
color: #60a0dc !important; |
||||
|
font-weight: 700; |
||||
|
font-size: 1.4em; |
||||
|
line-height: 35px; |
||||
|
height: 35px; |
||||
|
padding: 0 5px; |
||||
|
} |
||||
|
|
||||
|
form table tr th { |
||||
|
background: #333; |
||||
|
border: 1px solid #444; |
||||
|
color: #60a0dc; |
||||
|
} |
||||
|
|
||||
|
div.ban h2 { |
||||
|
background: #333; |
||||
|
color: inherit; |
||||
|
} |
||||
|
|
||||
|
div.ban { |
||||
|
border-color: #800; |
||||
|
} |
||||
|
|
||||
|
div.ban p { |
||||
|
color: black; |
||||
|
} |
||||
|
|
||||
|
div.pages { |
||||
|
background: #343439; |
||||
|
border: 1px solid #3070a9; |
||||
|
border-radius: 5px; |
||||
|
} |
||||
|
|
||||
|
div.pages a.selected { |
||||
|
color: #ccc; |
||||
|
} |
||||
|
|
||||
|
div.boardlist { |
||||
|
color: #aaa; |
||||
|
} |
||||
|
|
||||
|
div.boardlist a { |
||||
|
color: #ccc; |
||||
|
} |
||||
|
|
||||
|
table.modlog tr th { |
||||
|
background: #333; |
||||
|
} |
||||
|
|
||||
|
/* options.js */ |
||||
|
|
||||
|
#options_div, #alert_div { |
||||
|
background: #44444f; |
||||
|
} |
||||
|
|
||||
|
.desktop-style div.boardlist:nth-child(1) { |
||||
|
background-color: #bbb; |
||||
|
} |
||||
|
|
||||
|
span.name { |
||||
|
color: #93e3ff !important; |
||||
|
} |
||||
|
|
||||
|
span.trip { |
||||
|
color: #ffffff; |
||||
|
} |
||||
|
|
||||
|
span.quote { |
||||
|
color: green; |
||||
|
} |
||||
|
|
||||
|
[id^=thread] { |
||||
|
background: #1C1C1C; |
||||
|
margin-bottom: 1em ; |
||||
|
padding: 1em 1em 0 1em ; |
||||
|
border: 1px solid #333333; |
||||
|
} |
||||
|
|
||||
|
[id^=thread] hr { |
||||
|
display: none ; |
||||
|
} |
||||
|
|
||||
|
html body hr { |
||||
|
border-color: #9B9B9B; |
||||
|
border-width: 1px; |
||||
|
} |
||||
|
|
||||
|
p.intro { |
||||
|
background-color: #44444F; |
||||
|
padding-top: 5px; |
||||
|
padding-left: 5px; |
||||
|
padding-right: 5px; |
||||
|
margin-top: 0px!important; |
||||
|
display: box; |
||||
|
margin: intial; |
||||
|
border-bottom: 1px solid #1c1c1c; |
||||
|
box-shadow: 0 5px 5px -5px #1c1c1c; |
||||
|
} |
||||
|
|
||||
|
div.post.op p.intro { |
||||
|
background-color: #252525; |
||||
|
min-height: 30px; |
||||
|
} |
||||
|
|
||||
|
span.omitted { |
||||
|
color: #707070; |
||||
|
font-size: .9em; |
||||
|
margin: 5 5px 0px; |
||||
|
} |
||||
|
|
||||
|
h1 { |
||||
|
font-size: 3em; |
||||
|
font-weight: 300; |
||||
|
margin: .3em 0; |
||||
|
color: #60a0dc; |
||||
|
} |
||||
|
|
||||
|
div.subtitle { |
||||
|
font-style: oblique; |
||||
|
font-size: 1.25em!important; |
||||
|
font-weight: 400!important; |
||||
|
color: #ccc!important; |
||||
|
} |
||||
|
|
||||
|
tr td input, #body { |
||||
|
background-color: #AAA; |
||||
|
border-color: #888; |
||||
|
border-width: 1px; |
||||
|
padding-top: 3px; |
||||
|
padding-right: 2px; |
||||
|
padding-bottom: 3px; |
||||
|
padding-left: 2px; |
||||
|
} |
||||
|
|
||||
|
#upload_file { |
||||
|
color: #ccc; |
||||
|
background-color: transparent; |
||||
|
} |
||||
|
|
||||
|
div.blotter { |
||||
|
color: #ccc!important; |
||||
|
} |
||||
|
|
||||
|
div.banner, a.unimportant { |
||||
|
background-color: #60a0dc; |
||||
|
color: #000!important; |
||||
|
border-radius: 3px; |
||||
|
min-height: 25px; |
||||
|
padding-top: 5px; |
||||
|
} |
||||
|
|
||||
|
div.thread:hover { |
||||
|
background: #44444f; |
||||
|
border-color: #1c1c1c; |
||||
|
} |
||||
|
|
||||
|
span.heading { |
||||
|
color: red; |
||||
|
text-shadow: 0 0 3px #000, 0 0 3px #000; |
||||
|
} |
||||
|
|
||||
|
#expand-all-images, |
||||
|
#shrink-all-images, |
||||
|
#treeview{ |
||||
|
right: 1em !important; |
||||
|
position: absolute !important; |
||||
|
} |
||||
|
|
||||
|
#expand-all-images{ |
||||
|
margin-top: 4em !important; |
||||
|
} |
||||
|
|
||||
|
#treeview{ |
||||
|
margin-top: 5em !important; |
||||
|
} |
||||
|
|
||||
|
#shrink-all-images{ |
||||
|
margin-top: 6em !important; |
||||
|
} |
||||
|
|
||||
|
#expand-all-images + hr, |
||||
|
#shrink-all-images + hr{ |
||||
|
opacity: 0 !important; |
||||
|
margin: 0 !important; |
||||
|
} |
||||
|
|
||||
|
#treeview + hr{ |
||||
|
opacity: 0 !important; |
||||
|
clear: both !important; |
||||
|
} |
||||
|
|
||||
|
#options_handler{ |
||||
|
margin-top: 3em !important; |
||||
|
} |
@ -0,0 +1,29 @@ |
|||||
|
<div style="text-align:center"> |
||||
|
<form method="POST"> |
||||
|
<input name="token" value="{{ token }}" type="hidden"> |
||||
|
<table> |
||||
|
<tr> |
||||
|
<th>{% trans %}Markup method{% endtrans %} |
||||
|
{% set allowed_html = config.allowed_html %} |
||||
|
{% trans %}<p class="unimportant">"markdown" is provided by <a href="http://parsedown.org/">parsedown</a>. Note: images disabled.</p> |
||||
|
<p class="unimportant">"html" allows the following tags:<br/>{{ allowed_html }}</p> |
||||
|
<p class="unimportant">"infinity" is the same as what is used in posts.</p> |
||||
|
<p class="unimportant">This page will not convert between formats,<br/>choose it once or do the conversion yourself!</p>{% endtrans %} |
||||
|
</th> |
||||
|
<td> |
||||
|
<select name="method"> |
||||
|
{% for markup in ['markdown', 'html', 'infinity'] %} |
||||
|
<option value="{{ markup }}" {% if page.type == markup %}selected{% endif %}>{{ markup }}</option> |
||||
|
{% endfor %} |
||||
|
</select> |
||||
|
</td></tr> |
||||
|
<tr><th>{% trans %}Page content{% endtrans %} |
||||
|
<br/> |
||||
|
<span class="unimportant">{% trans %}Page will appear at:{% endtrans %} |
||||
|
{% if board %} <a href="/{{ board.uri }}/{{ page.name }}.html">{{ config.domain }}/{{ board.uri }}/{{ page.name }}.html</a> |
||||
|
{% else %} <a href="/{{ page.name }}.html">{{ config.site }}/{{ page.name }}.html</a> |
||||
|
{% endif %}</span></th><td><textarea name="content" style="height:500px;width:500px">{{content}}</textarea></td><tr> |
||||
|
</table> |
||||
|
<input type="submit" value="Save page"> |
||||
|
</form> |
||||
|
</div> |
@ -0,0 +1,34 @@ |
|||||
|
<script type="text/javascript" src="js/jquery.min.js"></script> |
||||
|
<div style="text-align:center"> |
||||
|
<p class="unimportant"> |
||||
|
{% if board %} |
||||
|
{% set page_max = config.pages_max %} |
||||
|
{% trans %}This page allows you to create static pages for your board. The limit is {{ page_max }} pages per board. You will still have to link to your pages somewhere in your board, for example in a sticky or in the board's announcement. To make links in the board's announcement, use <a> HTML tags.{% endtrans %} |
||||
|
{% else %} |
||||
|
{% trans %}This page allows you to create static pages for your imageboard.{% endtrans %} |
||||
|
{% endif %} |
||||
|
<h2>{% trans %}Existing pages{% endtrans %}</h2> |
||||
|
{% if pages %} |
||||
|
<form> |
||||
|
<table style="margin:auto"> |
||||
|
<tr><th>{% trans %}URL{% endtrans %}</th><th>{% trans %}Title{% endtrans %}</th><th>{% trans %}Edit{% endtrans %}</th><th>{% trans %}Delete{% endtrans %}</tr> |
||||
|
{% for page in pages %} |
||||
|
<tr><td>{{ page.name }}</td><td>{{ page.title }}</td><td><a href="?/edit_page/{{ page.id }}">{% trans %}Edit{% endtrans %}</a></td><td><a href="?/edit_pages/delete/{{ page.name }}{% if board %}/{{ board }}{% endif %}/{{ page.delete_token }}">{% trans %}Delete{% endtrans %}</a></td> |
||||
|
{% endfor %} |
||||
|
{% else %} |
||||
|
<em>No pages yet!</em> |
||||
|
{% endif %} |
||||
|
</table> |
||||
|
</form> |
||||
|
<hr/> |
||||
|
<h2>{% trans %}Create a new page{% endtrans %}</h2> |
||||
|
<form method="POST"> |
||||
|
<input type="hidden" name="token" value="{{ token }}"> |
||||
|
<table> |
||||
|
<tr><th>{% trans %}URL{% endtrans %}</th><th>{% trans %}Title{% endtrans %}</th></tr> |
||||
|
<tr><td><input type="text" name="page"></td><td><input type="text" name="title"></td> |
||||
|
</table> |
||||
|
<input type="submit" value="{% trans %}Create{% endtrans %}"> |
||||
|
</form> |
||||
|
|
||||
|
</div> |
@ -1,12 +1,12 @@ |
|||||
<div class="ban"> |
<div class="ban"> |
||||
<h2>{% trans 'Rebuilt' %}</h2> |
<h2>{% trans 'Rebuilt' %}</h2> |
||||
|
<p> |
||||
|
<a href="?/rebuild">{% trans 'Go back and rebuild again' %}</a>. |
||||
|
</p> |
||||
<ul> |
<ul> |
||||
{% for log in logs %} |
{% for log in logs %} |
||||
<li>{{ log }}</li> |
<li>{{ log }}</li> |
||||
{% endfor %} |
{% endfor %} |
||||
</ul> |
</ul> |
||||
<p> |
|
||||
<a href="?/rebuild">{% trans 'Go back and rebuild again' %}</a>. |
|
||||
</p> |
|
||||
</div> |
</div> |
||||
|
|
||||
|
@ -1,7 +1,7 @@ |
|||||
{% if config.poster_ids %} |
{% if config.poster_ids %} |
||||
{% if post.thread %} |
{% if post.thread %} |
||||
ID: <span class="poster_id">{{ post.ip|poster_id(post.thread) }}</span> |
<span class="poster_id">{{ post.ip|poster_id(post.thread) }}</span> |
||||
{% else %} |
{% else %} |
||||
ID: <span class="poster_id">{{ post.ip|poster_id(post.id) }}</span> |
<span class="poster_id">{{ post.ip|poster_id(post.id) }}</span> |
||||
{% endif %} |
{% endif %} |
||||
{% endif %} |
{% endif %} |
||||
|
@ -0,0 +1,22 @@ |
|||||
|
<form action="{{ config.post_url }}" method="post" id="report_form"> |
||||
|
{% if error %} |
||||
|
<div class="error"> |
||||
|
<strong>{{ error|e }}</strong> |
||||
|
</div> |
||||
|
{% endif %} |
||||
|
<input type="hidden" name="board" value="{{ board.uri }}"> |
||||
|
<input type="hidden" name="{{ post|e }}" value="1"> |
||||
|
{% if global %} |
||||
|
<input type="hidden" name="global" value="1"> |
||||
|
<div><h1>Attention!</h1><p>This form is only for reporting <strong>child pornography</strong>, <strong>bot spam</strong> and <strong>credit card numbers, social security numbers or banking information</strong>. DMCA requests and all other deletion requests <em>MUST</em> be sent via email to [email protected].</p><p>8chan is unmoderated and allows posts without collecting <em>ANY</em> information from the poster less the details of their post. Furthermore, all boards on 8chan are user created and not actively monitored by anyone but the board creator.</p><p>8chan has a small volunteer staff to handle this queue, please do not waste their time by filling it with nonsense! <em>If you made a report with this tool and the post was not deleted, <strong>do not make the report again!</strong> Email [email protected] instead.</em> Abuse of the global report system could lead to address blocks against your IP from 8chan.</p><p>Again, 8chan's global volunteers <em>do not</em> handle board specific issues. You most likely want to click "Report" instead to reach the creator and volunteers he assigned to this board.</p> |
||||
|
{% endif %} |
||||
|
<p>{% trans %}Enter reason below...{% endtrans %}</p> |
||||
|
<input type="text" id="reason" name="reason" value="{{ reason_prefill|e|addslashes }}"> |
||||
|
{% if config.report_captcha %} |
||||
|
<p>{% trans %}To submit your report, please fill out the CAPTCHA below.{% endtrans %}</p> |
||||
|
{{ captcha['html'] }}<br/> |
||||
|
<input class="captcha_text" name="captcha_text" size="25" maxlength="6" autocomplete="off" type="text" value=""> |
||||
|
<input class="captcha_cookie" name="captcha_cookie" type="hidden" autocomplete="off" value="{{ captcha['cookie']|e }}"><br/> |
||||
|
{% endif %} |
||||
|
<input name="report" value="{% trans %}Submit{% endtrans %}" type="submit"> |
||||
|
</form> |
@ -1,13 +1,16 @@ |
|||||
{% if config.allow_delete %} |
<div id="post-moderation-fields"> |
||||
<div class="delete"> |
{% if config.allow_delete %} |
||||
{% trans %}Delete Post{% endtrans %} [<input title="Delete file only" type="checkbox" name="file" id="delete_file" /> |
<div id="delete-fields"> |
||||
<label for="delete_file">{% trans %}File{% endtrans %}</label>] <label for="password">{% trans %}Password{% endtrans %}</label> |
{% trans %}Delete Post{% endtrans %} [<input title="Delete file only" type="checkbox" name="file" id="delete_file" /> |
||||
|
<label for="delete_file">{% trans %}File{% endtrans %}</label>] <label for="password">{% trans %}Password{% endtrans %}</label> |
||||
<input id="password" type="password" name="password" size="12" maxlength="18" /> |
<input id="password" type="password" name="password" size="12" maxlength="18" /> |
||||
<input type="submit" name="delete" value="{% trans %}Delete{% endtrans %}" /> |
<input type="submit" name="delete" value="{% trans %}Delete{% endtrans %}" /> |
||||
</div> |
</div> |
||||
{% endif %} |
{% endif %} |
||||
<div class="delete" style="clear:both"> |
|
||||
<label for="reason">{% trans %}Reason{% endtrans %}</label> |
<div id="report-fields"> |
||||
|
<label for="reason">{% trans %}Reason{% endtrans %}</label> |
||||
<input id="reason" type="text" name="reason" size="20" maxlength="30" /> |
<input id="reason" type="text" name="reason" size="20" maxlength="30" /> |
||||
<input type="submit" name="report" value="{% trans %}Report{% endtrans %}" /> |
<input type="submit" name="report" value="{% trans %}Report{% endtrans %}" /> |
||||
</div> |
</div> |
||||
|
</div> |
@ -0,0 +1,19 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"> |
||||
|
<channel> |
||||
|
<title>/{{ board.uri }}/ - {{ board.title|e }}</title> |
||||
|
<link>{{ config.root }}{{ board.uri }}/</link> |
||||
|
<description>Live feed of new threads on the board /{{ board.uri }}/ - {{ board.title|e }}.</description> |
||||
|
<atom:link href="{{ config.root }}{{ board.uri }}/index.rss" rel="self" type="application/rss+xml"/> |
||||
|
{% for post in recent_posts %} |
||||
|
<item> |
||||
|
<title>{% if post.subject %}{{ post.subject|e }}{% else %}{{ post.body_nomarkup[:256]|remove_modifiers|e }}{% endif %}</title> |
||||
|
<link>{{ config.root }}{{ board.uri }}/res/{{ post.id }}.html</link> |
||||
|
<guid>{{ config.root }}{{ board.uri }}/res/{{ post.id }}.html</guid> |
||||
|
<comments>{{ config.root }}{{ board.uri }}/res/{{ post.id }}.html</comments> |
||||
|
<pubDate>{{ post.pubdate }}</pubDate> |
||||
|
<description><![CDATA[ <a href='{{ config.root }}{{ board.uri }}/res/{{ post.id }}.html' target=_blank><img style='float:left;margin:8px' border=0 src='{% if not config.uri_thumb %}{{ config.root }}{% endif %}{{ post.file }}'></a> {{ post.body }} ]]></description> |
||||
|
</item> |
||||
|
{% endfor %} |
||||
|
</channel> |
||||
|
</rss> |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue