Browse Source

Add staff application theme, calendar theme and ukko4 theme

pull/40/head
Benjamin Southall 7 years ago
parent
commit
7f8c54249d
  1. 10
      js/fullcalendar.min.js
  2. 7
      js/moment.min.js
  3. 9
      js/scheduler.min.js
  4. 5
      stylesheets/fullcalendar.min.css
  5. 5
      stylesheets/scheduler.min.css
  6. 191
      templates/themes/calendar/calendar.html
  7. 53
      templates/themes/calendar/calendarpost.php
  8. 36
      templates/themes/calendar/info.php
  9. 40
      templates/themes/calendar/theme.php
  10. BIN
      templates/themes/calendar/thumb.png
  11. 36
      templates/themes/staffapplication/info.php
  12. 80
      templates/themes/staffapplication/staffapplication.html
  13. 54
      templates/themes/staffapplication/staffapplicationpost.php
  14. 40
      templates/themes/staffapplication/theme.php
  15. BIN
      templates/themes/staffapplication/thumb.png
  16. 55
      templates/themes/ukko4/info.php
  17. 162
      templates/themes/ukko4/theme.php
  18. BIN
      templates/themes/ukko4/thumb.png
  19. 116
      templates/themes/ukko4/ukko.js

10
js/fullcalendar.min.js

File diff suppressed because one or more lines are too long

7
js/moment.min.js

File diff suppressed because one or more lines are too long

9
js/scheduler.min.js

File diff suppressed because one or more lines are too long

5
stylesheets/fullcalendar.min.css

File diff suppressed because one or more lines are too long

5
stylesheets/scheduler.min.css

File diff suppressed because one or more lines are too long

191
templates/themes/calendar/calendar.html

@ -0,0 +1,191 @@
<!doctype html>
<html>
<head>
<link rel="stylesheet" media="screen" href="/stylesheets/style.css">
<meta charset="utf-8">
{% if config.meta_keywords %}<meta name="keywords" content="{{ config.meta_keywords }}">{% endif %}
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes">
<link rel='stylesheet' href='/stylesheets/fullcalendar.min.css' />
<script type='text/javascript'>
var active_page = "news";
</script>
<title>{{ settings.title }}</title>
{% include 'header.html' %}
<script src='/js/moment.min.js'></script>
<script src='/js/fullcalendar.min.js'></script>
</head>
<body class="8chan vichan {% if mod %}is-moderator{% else %}is-not-moderator{% endif %}" data-stylesheet="{% if config.default_stylesheet.1 != '' %}{{ config.default_stylesheet.1 }}{% else %}default{% endif %}">
<div class="bar top">
{{ boardlist.top }}
</div>
<header>
<h1 class="glitch" data-text="{{ settings.title }}"> {{ settings.title }}</h1>
<div class="subtitle">{{ settings.subtitle }}</div>
</header>
<div class="ban">
<div id='calendar'></div>
</div>
<hr/>
<footer>
<p class="unimportant" style="margin-top:20px;text-align:center;">- <a href="http://tinyboard.org/">Tinyboard</a> +
<a href='https://int.vichan.net/devel/'>vichan</a> +
<a href='https://github.com/lainchan/lainchan'>lainchan</a> {{ config.version }} -
<br><a href="http://tinyboard.org/">Tinyboard</a> Copyright &copy; 2010-2014 Tinyboard Development Group
<br><a href="https://engine.vichan.net/">vichan</a> Copyright &copy; 2012-2016 vichan-devel
<br><a href="https://github.com/lainchan/lainchan">lainchan</a> Copyright &copy; 2014-2017 lainchan Administration</p>
</footer>
<div class="pages"></div>
<script type='text/javascript'>
$(document).ready(function() {
var calendar = $('#calendar').fullCalendar({
editable: true,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
events: "calendarpost.php",
eventRender: function(event, element, view) {
if (event.allDay === 'true') {
event.allDay = true;
} else {
event.allDay = false;
}
element.find('.fc-title').append("<br/>" + event.description);
element.css('background-color',event.color);
},
selectable: true,
selectHelper: true,
select: function(start, end, allDay) {
var title = prompt('Event Title:');
var description = prompt('Event Description:');
var url = prompt("Event URL");
var color = prompt("Event Color");
var starttime = prompt("Event Start Time");
var endtime = prompt("Event End Time");
if (title) {
var startmoment = moment(start);
var endmoment = moment(end);
var start = startmoment.format('YYYY-MM-DD HH:mm:ss');
var end = endmoment.format('YYYY-MM-DD HH:mm:ss');
if (starttime && endtime){
var starttimemoment = moment(starttime,'HH:mm');
var endtimemoment = moment(endtime,'HH:mm');
startmoment.hour(starttimemoment.hour());
startmoment.minute(starttimemoment.minute());
endmoment.hour(endtimemoment.hour());
endmoment.minute(endtimemoment.minute());
endmoment.subtract(1, "days");
allday = false;
start = startmoment.format('YYYY-MM-DD HH:mm:ss');
end = endmoment.format('YYYY-MM-DD HH:mm:ss');
}
$.ajax({
url: 'calendarpost.php',
data: 'type=add&title='+ title+'&description='+ description +'&start='+ start +'&end='+ end + '&url='+url+'&color='+color,
type: "POST",
success: function(json) {
alert('Added Successfully');
}
});
calendar.fullCalendar('renderEvent',
{
title: title,
description: description,
start: start,
end: end,
allDay: allDay,
url: url,
color:color,
},
true
);
}
calendar.fullCalendar('unselect');
},
editable: true,
eventDrop: function(event, delta) {
var startmoment = moment(start);
var endmoment = moment(end);
var start = startmoment.format('YYYY-MM-DD HH:mm:ss');
var end = endmoment.format('YYYY-MM-DD HH:mm:ss');
var starttime = prompt("Event Start Time");
var endtime = prompt("Event End Time");
if (starttime && endtime){
var starttimemoment = moment(starttime,'HH:mm');
var endtimemoment = moment(endtime,'HH:mm');
startmoment.hour(starttimemoment.hour());
startmoment.minute(starttimemoment.minute());
endmoment.hour(endtimemoment.hour());
endmoment.minute(endtimemoment.minute());
allday = false;
endmoment.subtract(1, "days");
start = startmoment.format('YYYY-MM-DD HH:mm:ss');
end = endmoment.format('YYYY-MM-DD HH:mm:ss');
}
$.ajax({
url: 'calendarpost.php',
data: 'type=update&title='+ event.title+'&description='+ event.description + '&start='+ start +'&end='+ end +'&id='+ event.id ,
type: "POST",
success: function(json) {
alert("Updated Successfully");
}
});
},
eventClick: function(event) {
var decision = confirm("Do you really want to do that?");
if (decision) {
$.ajax({
type: "POST",
url: 'calendarpost.php',
data: "type=delete&id=" + event.id,
success: function(json) {
$('#calendar').fullCalendar('removeEvents', event.id);
alert("Updated Successfully");}
});
}
},
eventResize: function(event) {
var startmoment = moment(start);
var endmoment = moment(end);
var start = moment(start).format('YYYY-MM-DD HH:mm:ss');
var end = moment(end).format('YYYY-MM-DD HH:mm:ss');
var starttime = prompt("Event Start Time");
var endtime = prompt("Event End Time");
if (starttime && endtime){
var starttimemoment = moment(starttime,'HH:mm');
var endtimemoment = moment(endtime,'HH:mm');
startmoment.hour(starttimemoment.hour());
startmoment.minute(starttimemoment.minute());
endmoment.hour(endtimemoment.hour());
endmoment.minute(endtimemoment.minute());
allday = false;
endmoment.subtract(1, "days");
start = startmoment.format('YYYY-MM-DD HH:mm:ss');
end = endmoment.format('YYYY-MM-DD HH:mm:ss');
}
$.ajax({
url: 'calendarpost.php',
data: 'type=update&title='+ event.title+ '&description='+ event.description + '&start='+ start +'&end='+ end +'&id='+ event.id ,
type: "POST",
success: function(json) {
alert("Updated Successfully");
}
});
}
});
});
</script>
<script type="text/javascript">{% raw %}
ready();
{% endraw %}</script>
</body>
</html>

53
templates/themes/calendar/calendarpost.php

@ -0,0 +1,53 @@
<?php
require '/var/www/html/inc/functions.php';
$method = $_SERVER['REQUEST_METHOD'];
if ($method == 'POST') {
// Method is POST
$type = $_POST['type'];
switch ($type) {
case "add":
$title = $_POST['title'];
$description = $_POST['description'];
$start = $_POST['start'];
$end = $_POST['end'];
$url = $_POST['url'];
$color = $_POST['color'];
$query = prepare("INSERT INTO calendar_events (title, description, start, end,url,color) VALUES (:title,:description, :start, :end,:url, :color )");
$query->bindValue(':title', $title);
$query->bindValue(':description', $description);
$query->bindValue(':start', $start);
$query->bindValue(':end', $end);
$query->bindValue(':url', $url);
$query->bindValue(':color', $color);
$query->execute() or error(db_error($query));
break;
case "delete":
$id = $_POST['id'];
$query = query("DELETE from calendar_events WHERE id = :id") or error(db_error());
break;
case "update":
$id = $_POST['id'];
$title = $_POST['title'];
$description = $_POST['description'];
$start = $_POST['start'];
$end = $_POST['end'];
$query = prepare(" UPDATE calendar_events SET title = :title, description = :description, start = :start, end = :end, url = :url, color =:color WHERE id = :id");
$query->bindValue(':id', $id);
$query->bindValue(':title', $title);
$query->bindValue(':description', $description);
$query->bindValue(':start', $start);
$query->bindValue(':end', $end);
$query->bindValue(':url', $url);
$query->bindValue(':color', $color);
$query->execute() or error(db_error($query));
break;
default:
}
} elseif ($method == 'GET') {
// Method is GET
$query = query("SELECT * FROM calendar_events ORDER BY id") or error(db_error());
echo json_encode($query->fetchAll(PDO::FETCH_ASSOC));
}
?>

36
templates/themes/calendar/info.php

@ -0,0 +1,36 @@
<?php
$theme = Array();
// Theme name
$theme['name'] = 'Calendar';
// Description (you can use Tinyboard markup here)
$theme['description'] = 'Calendar theme.';
$theme['version'] = 'v0.0.1';
// Theme configuration
$theme['config'] = Array();
$theme['config'][] = Array(
'title' => 'Site title',
'name' => 'title',
'type' => 'text'
);
$theme['config'][] = Array(
'title' => 'Slogan',
'name' => 'subtitle',
'type' => 'text',
'comment' => '(optional)'
);
$theme['config'][] = Array(
'title' => 'File',
'name' => 'file',
'type' => 'text',
'default' => $config['file_index'],
'comment' => '(eg. "index.html")'
);
// Unique function name for building everything
$theme['build_function'] = 'calendar_build';

40
templates/themes/calendar/theme.php

@ -0,0 +1,40 @@
<?php
require 'info.php';
function calendar_build($action, $settings, $board) {
// Possible values for $action:
// - all (rebuild everything, initialization)
// - news (news has been updated)
// - boards (board list changed)
Calendar::build($action, $settings);
}
// Wrap functions in a class so they don't interfere with normal Tinyboard operations
class Calendar {
public static function build($action, $settings) {
global $config;
if ($action == 'all' || $action == 'news')
file_write($config['dir']['home'] . $settings['file'], Calendar::htmlpage($settings));
file_write($config['dir']['home'] . "calendarpost.php", Calendar::phppage($settings));
}
// Build staff application page
public static function htmlpage($settings) {
global $config;
return Element('themes/calendar/calendar.html', Array(
'settings' => $settings,
'config' => $config,
'boardlist' => createBoardlist()
));
}
public static function phppage($settings) {
global $config;
$page = file_get_contents('templates/themes/calendar/calendarpost.php');
return $page;
}
};
?>

BIN
templates/themes/calendar/thumb.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

36
templates/themes/staffapplication/info.php

@ -0,0 +1,36 @@
<?php
$theme = Array();
// Theme name
$theme['name'] = 'StaffApplication';
// Description (you can use Tinyboard markup here)
$theme['description'] = 'Staff Application theme.';
$theme['version'] = 'v0.0.1';
// Theme configuration
$theme['config'] = Array();
$theme['config'][] = Array(
'title' => 'Site title',
'name' => 'title',
'type' => 'text'
);
$theme['config'][] = Array(
'title' => 'Slogan',
'name' => 'subtitle',
'type' => 'text',
'comment' => '(optional)'
);
$theme['config'][] = Array(
'title' => 'File',
'name' => 'file',
'type' => 'text',
'default' => $config['file_index'],
'comment' => '(eg. "index.html")'
);
// Unique function name for building everything
$theme['build_function'] = 'staffapplication_build';

80
templates/themes/staffapplication/staffapplication.html

@ -0,0 +1,80 @@
{% filter remove_whitespace %}
<!doctype html>
<html>
<head>
<link rel="stylesheet" media="screen" href="/stylesheets/style.css">
<meta charset="utf-8">
{% if config.meta_keywords %}<meta name="keywords" content="{{ config.meta_keywords }}">{% endif %}
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes">
<script type='text/javascript'>
var active_page = "news";
</script>
<title>{{ settings.title }}</title>
{% include 'header.html' %}
</head>
<body class="8chan vichan {% if mod %}is-moderator{% else %}is-not-moderator{% endif %}" data-stylesheet="{% if config.default_stylesheet.1 != '' %}{{ config.default_stylesheet.1 }}{% else %}default{% endif %}">
<div class="bar top">
{{ boardlist.top }}
</div>
<header>
<h1 class="glitch" data-text="{{ settings.title }}"> {{ settings.title }}</h1>
<div class="subtitle">{{ settings.subtitle }}</div>
</header>
<center>
<img src="static/lain_is_cute_datass_small_teal.png" alt="mascot"/>
</center>
<div class="ban">
<p>
Please use to the form below to apply to be staff.</br>
If you don't want to use this form you can also email [email protected] or ask in #questions on the Lainchan IRC channel.
In the rest of your application section, please specify the following information: </br>
Do you have to specify all the requested information below ? </br>
No of course not, but the more you specify the more likely your application will be approved, because applications
that demostrate that you can put effort in things, tell us that you can be bothered putting effort into things.</br>
What position you wanted to apply for ? E.g. Chan staff ? IRC staff ? Sysadmin ? Developer ? All of the above ?
None of the above ? Special snowflake role invented just for you ?</br>
Your reasons for applying ? </br>
Your existing qualifications for the position </br>
A summary of your strengths, weaknesses and interesting points / quirks </br>
If chan staff , then please specify which boards you are interested in and your experience with their subject matter.
</br>
Things to not include on your application. </br>
1. NSFW pictures </br>
2. Anything that is against the rules on the Rules page.</br>
3. Short stories about ducks and ribbons and that guy Jimmy and other off topic things.</br>
4. Your entire life story. </br>
5. Your passport number or SSN and / or other identifying information. </br>
6. Your rant about XYZ and how much all ABC need to suffer DEF because of it. </br>
</p>
<form action="staffapplication.php" method="post">
<p><label for="name">Name: </label><input type="text" name="name" size="50"></p>
<p><label for="contactmethod">Preferred Contact Method: </label><select name="contactmethod">
<option value="email" selected>Email</option>
<option value="irc">IRC</option>
<option value="chan">Lainchan</option>
</select></p>
<p><label for="email">Email: </label><input type="email" name="email" size="50"></p>
<p>
<label for="application">The rest of your application.</label><textarea name="application" rows="30" cols="50"></textarea>
</p>
<p><label for="anitspam">Antispam: (What is Cyberpunk , answer in all CAPS, single word, no spaces) </label><input type="text" name="antispam" size="50"></p>
<input type="submit" value="Send">
</form>
</div>
<hr/>
<footer>
<p class="unimportant" style="margin-top:20px;text-align:center;">- <a href="http://tinyboard.org/">Tinyboard</a> +
<a href='https://int.vichan.net/devel/'>vichan</a> +
<a href='https://github.com/lainchan/lainchan'>lainchan</a> {{ config.version }} -
<br><a href="http://tinyboard.org/">Tinyboard</a> Copyright &copy; 2010-2014 Tinyboard Development Group
<br><a href="https://engine.vichan.net/">vichan</a> Copyright &copy; 2012-2016 vichan-devel
<br><a href="https://github.com/lainchan/lainchan">lainchan</a> Copyright &copy; 2014-2017 lainchan Administration</p>
</footer>
<div class="pages"></div>
<script type="text/javascript">{% raw %}
ready();
{% endraw %}</script>
</body>
</html>
{% endfilter %}

54
templates/themes/staffapplication/staffapplicationpost.php

@ -0,0 +1,54 @@
<?php
$name = $contactmethod = $email = $application = $antispam = $displaymessage = "";
require '/var/www/html/inc/functions.php';
if (isset ($_POST["antispam"])){
if ($_POST["antispam"] == "DUCK"){
$namecheck = ! empty($_POST["name"]);
$contactmethodcheck = $_POST["contactmethod"] == "email";
$emailcheck = ! empty($_POST["email"]);
$emailischecked = $contactmethodcheck ? $emailcheck : true;
if ($emailischecked && $namecheck){
$name = $_POST["name"];
$contactmethod = $_POST["contactmethod"];
$email = $_POST["email"];
$application = $_POST["application"];
$antispam = $_POST["antispam"];
$to = "[email protected]";
$subject = "Lainchan.org Staff Application for " . $name;
$message = "Name: " . $name . "\r\n";
$message .= "Contact method: " . $contactmethod . "\r\n";
$message .= $application;
$message = wordwrap($message, 70, "\r\n");
$source = $emailcheck ? $email : $to;
$headers = 'From: ' . $source . "\r\n" .
'Reply-To: ' . $source . "\r\n" .
'X-Mailer: PHP/' . phpversion();
$sent = mail($to, $subject, $message, $headers);
$sentmessage = $sent ? "was submitted successfully.</p>\r\n" : "was unable to be submitted.</p>\r\n";
$displaymessage = "<p style=\"text-align:center;\"> Your staff application " . $sentmessage;
}
}
else
{
$displaymessage = "<p style=\"text-align:center;\">ANTISPAM VALUE INCORRECT</p>\r\n";
}
}
else {
$displaymessage = "<p style=\"text-align:center;\">ANTISPAM NOT SET</p>\r\n";
}
$displaymessage .= '<span style="text-align:center; display: block;" >[ <a href="https://lainchan.org/"> Return Home </a> ]</span>';
echo Element('page.html', array(
'index' => $config['root'],
'title' => _('Staff Application'),
'config' => $config,
'boardlist' => createBoardlist(isset($mod) ? $mod : false),
'body' => $displaymessage,
)
);
?>

40
templates/themes/staffapplication/theme.php

@ -0,0 +1,40 @@
<?php
require 'info.php';
function staffapplication_build($action, $settings, $board) {
// Possible values for $action:
// - all (rebuild everything, initialization)
// - news (news has been updated)
// - boards (board list changed)
StaffApplication::build($action, $settings);
}
// Wrap functions in a class so they don't interfere with normal Tinyboard operations
class StaffApplication {
public static function build($action, $settings) {
global $config;
if ($action == 'all' || $action == 'news')
file_write($config['dir']['home'] . $settings['file'], StaffApplication::htmlpage($settings));
file_write($config['dir']['home'] . "staffapplication.php", StaffApplication::phppage($settings));
}
// Build staff application page
public static function htmlpage($settings) {
global $config;
return Element('themes/staffapplication/staffapplication.html', Array(
'settings' => $settings,
'config' => $config,
'boardlist' => createBoardlist()
));
}
public static function phppage($settings) {
global $config;
$page = file_get_contents('templates/themes/staffapplication/staffapplicationpost.php');
return $page;
}
};
?>

BIN
templates/themes/staffapplication/thumb.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

55
templates/themes/ukko4/info.php

@ -0,0 +1,55 @@
<?php
$theme = array();
// Theme name
$theme['name'] = 'Overboard (Ukko) 4';
// Description (you can use Tinyboard markup here)
$theme['description'] = 'Board with threads and messages from all boards';
$theme['version'] = 'v0.2';
// Theme configuration
$theme['config'] = array();
$theme['config'][] = array(
'title' => 'Board name',
'name' => 'title',
'type' => 'text',
'default' => 'Ukko'
);
$theme['config'][] = array(
'title' => 'Board URI',
'name' => 'uri',
'type' => 'text',
'default' => '*',
'comment' => '(ukko for example)'
);
$theme['config'][] = array(
'title' => 'Subtitle',
'name' => 'subtitle',
'type' => 'text',
'comment' => '(%s = thread limit. for example "%s freshly bumped threads")'
);
$theme['config'][] = array(
'title' => 'Excluded boards',
'name' => 'exclude',
'type' => 'text',
'comment' => '(space seperated)'
);
$theme['config'][] = array(
'title' => 'Number of threads',
'name' => 'thread_limit',
'type' => 'text',
'default' => '15',
);
// Unique function name for building everything
$theme['build_function'] = 'ukko4_build';
$theme['install_callback'] = 'ukko4_install';
if(!function_exists('ukko4_install')) {
function ukko4_install($settings) {
if (!file_exists($settings['uri']))
@mkdir($settings['uri'], 0777) or error("Couldn't create " . $settings['uri'] . ". Check permissions.", true);
file_write($settings['uri'] . '/ukko.js', Element('themes/ukko/ukko.js', array()));
}
}

162
templates/themes/ukko4/theme.php

@ -0,0 +1,162 @@
<?php
require 'info.php';
function ukko4_build($action, $settings) {
global $config;
$ukko = new ukko();
$ukko->settings = $settings;
if (! ($action == 'all' || $action == 'post' || $action == 'post-thread' || $action == 'post-delete')) {
return;
}
$action = generation_strategy('sb_ukko', array());
if ($action == 'delete') {
file_unlink($settings['uri'] . '/index.html');
if ($config['api']['enabled']) {
$jsonFilename = $settings['uri'] . '/0.json';
file_unlink($jsonFilename);
$jsonFilename = $settings['uri'] . '/catalog.json';
file_unlink($jsonFilename);
$jsonFilename = $settings['uri'] . '/threads.json';
file_unlink($jsonFilename);
}
}
elseif ($action == 'rebuild') {
file_write($settings['uri'] . '/index.html', $ukko->build());
}
}
class ukko4 {
public $settings;
public function build($mod = false) {
global $config;
$boards = listBoards();
$body = '';
$overflow = array();
$board = array(
'dir' => $this->settings['uri'] . "/",
'url' => $this->settings['uri'],
'uri' => $this->settings['uri'],
'name' => $this->settings['title'],
'title' => sprintf($this->settings['subtitle'], $this->settings['thread_limit'])
);
$boardsforukko = array();
$query = '';
foreach($boards as &$_board) {
if(in_array($_board['uri'], explode(' ', $this->settings['exclude'])))
continue;
$query .= sprintf("SELECT *, '%s' AS `board` FROM ``posts_%s`` WHERE `thread` IS NULL UNION ALL ", $_board['uri'], $_board['uri']);
array_push($boardsforukko,$_board);
}
$query = preg_replace('/UNION ALL $/', 'ORDER BY `bump` DESC', $query);
$query = query($query) or error(db_error());
$count = 0;
$threads = array();
if ($config['api']['enabled']) {
$apithreads = array();
}
while($post = $query->fetch()) {
if(!isset($threads[$post['board']])) {
$threads[$post['board']] = 1;
} else {
$threads[$post['board']] += 1;
}
if($count < $this->settings['thread_limit']) {
openBoard($post['board']);
$thread = new Thread($post, $mod ? '?/' : $config['root'], $mod);
$posts = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE `thread` = :id ORDER BY `sticky` DESC, `id` DESC LIMIT :limit", $post['board']));
$posts->bindValue(':id', $post['id']);
$posts->bindValue(':limit', ($post['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview']), PDO::PARAM_INT);
$posts->execute() or error(db_error($posts));
$num_images = 0;
while ($po = $posts->fetch()) {
if ($po['files'])
$num_images++;
$post2 = new Post($po, $mod ? '?/' : $config['root'], $mod);
$thread->add($post2);
}
if ($posts->rowCount() == ($post['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview'])) {
$ct = prepare(sprintf("SELECT COUNT(`id`) as `num` FROM ``posts_%s`` WHERE `thread` = :thread UNION ALL SELECT COUNT(`id`) FROM ``posts_%s`` WHERE `files` IS NOT NULL AND `thread` = :thread", $post['board'], $post['board']));
$ct->bindValue(':thread', $post['id'], PDO::PARAM_INT);
$ct->execute() or error(db_error($count));
$c = $ct->fetch();
$thread->omitted = $c['num'] - ($post['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview']);
$c = $ct->fetch();
$thread->omitted_images = $c['num'] - $num_images;
}
$thread->posts = array_reverse($thread->posts);
$body .= '<h2><a href="' . $config['root'] . $post['board'] . '">/' . $post['board'] . '/</a></h2>';
$body .= $thread->build(true);
if ($config['api']['enabled']) {
array_push($apithreads,$thread);
}
} else {
$page = 'index';
if(floor($threads[$post['board']] / $config['threads_per_page']) > 0) {
$page = floor($threads[$post['board']] / $config['threads_per_page']) + 1;
}
$overflow[] = array('id' => $post['id'], 'board' => $post['board'], 'page' => $page . '.html');
}
$count += 1;
}
$body .= '<script> var overflow = ' . json_encode($overflow) . '</script>';
$body .= '<script type="text/javascript" src="/'.$this->settings['uri'].'/ukko.js"></script>';
// json api
if ($config['api']['enabled']) {
require_once __DIR__. '/../../../inc/api.php';
$api = new Api();
$jsonFilename = $board['dir'] . '0.json';
$json = json_encode($api->translatePage($apithreads));
file_write($jsonFilename, $json);
$catalog = array();
$catalog[0] = $apithreads;
$json = json_encode($api->translateCatalog($catalog));
$jsonFilename = $board['dir'] . 'catalog.json';
file_write($jsonFilename, $json);
$json = json_encode($api->translateCatalog($catalog, true));
$jsonFilename = $board['dir'] . 'threads.json';
file_write($jsonFilename, $json);
}
$antibot = null;
if (!$antibot) {
$antibot = create_antibot($board['uri']);
}
$antibot->reset();
return Element('index.html', array(
'config' => $config,
'board' => $board,
'no_post_form' => $config['overboard_post_form'] ? false : true,
'body' => $body,
'mod' => $mod,
'boardlist' => createBoardlist($mod),
'boards' => $boardsforukko,
'antibot' => $antibot )
);
}
};
?>

BIN
templates/themes/ukko4/thumb.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

116
templates/themes/ukko4/ukko.js

@ -0,0 +1,116 @@
(function(){
var cache = new Array(),
thread = false,
loading = false,
ukkotimer = false;
if (localStorage.hiddenboards === undefined) {
localStorage.hiddenboards = "{}";
}
// Load data from HTML5 localStorage
var hiddenboards = JSON.parse(localStorage.hiddenboards);
var storeboards = function() {
localStorage.hiddenboards = JSON.stringify(hiddenboards);
};
$(document).ready(function() {
var addukkohide = function() {
var ukkohide = $('<a href="javascript:void(0);" class="unimportant ukkohide"></a>');
var board = $(this).next().data("board");
var hr = $("<hr />");
$(this).append(ukkohide);
$(this).append(hr);
if (hiddenboards[board] !== true) {
ukkohide.html(_("(hide threads from this board)"));
hr.hide();
}
else {
ukkohide.html(_("(show threads from this board)"));
$(this).next().hide();
}
ukkohide.click(function() {
hiddenboards[board] = (hiddenboards[board] !== true);
if (hiddenboards[board] !== true) {
$('[data-board="'+board+'"]:not([data-cached="yes"])').show().prev().
find('.ukkohide').html(_("(hide threads from this board)")).
parent().find('hr').hide();
}
else {
$('[data-board="'+board+'"]:not([data-cached="yes"])').hide().prev().
find('.ukkohide').html(_("(show threads from this board)"))
.parent().find('hr').show();
}
storeboards();
return false;
});
};
$("h2").each(addukkohide);
$('.pages').hide();
var loadnext = function() {
if (overflow.length == 0) {
$('.pages').show().html(_("No more threads to display"));
}
while($(window).scrollTop() + $(window).height() + 1000 > $(document).height() && !loading && overflow.length > 0) {
var page = modRoot + overflow[0].board + '/' + overflow[0].page;
thread = $('div#thread_' + overflow[0].id + '[data-board="' + overflow[0].board + '"]');
if (thread.length > 0 && thread.attr("data-cached") !== 'yes') { // already present
overflow.shift();
continue;
}
var boardheader = $('<h2><a href="/' + overflow[0].board + '/">/' + overflow[0].board + '/</a> </h2>');
if($.inArray(page, cache) != -1) {
if (thread.length > 0) {
$('div[id*="thread_"]').last().after(thread.attr('data-board', overflow[0].board).attr("data-cached", "no").css('display', 'block'));
boardheader.insertBefore(thread);
addukkohide.call(boardheader);
$(document).trigger('new_post', thread);
}
overflow.shift();
} else {
loading = true;
$('.pages').show().html(_("Loading..."));
$.get(page, function(data) {
cache.push(page);
$(data).find('div[id*="thread_"]').each(function() {
var checkout = $(this).attr('id').replace('thread_', '');
if ($('div#thread_' + checkout + '[data-board="' + overflow[0].board + '"]').length == 0) {
$('form[name="postcontrols"]').prepend($(this).css('display', 'none').attr("data-cached", "yes").attr('data-board', overflow[0].board));
}
});
thread = $('div#thread_' + overflow[0].id + '[data-board="' + overflow[0].board + '"][data-cached="yes"]');
if(thread.length > 0) {
$('div[id*="thread_"]').last().after(thread.attr('data-board', overflow[0].board).attr("data-cached", "no").css('display', 'block'));
boardheader.insertBefore(thread);
addukkohide.call(boardheader);
$(document).trigger('new_post', thread);
}
overflow.shift();
loading = false;
$('.pages').hide().html("");
});
break;
}
}
clearTimeout(ukkotimer);
ukkotimer = setTimeout(loadnext, 1000);
};
$(window).on('scroll', loadnext);
ukkotimer = setTimeout(loadnext, 1000);
});
})();
Loading…
Cancel
Save