r20151101

Signed-off-by: Flashwave <me@flash.moe>
This commit is contained in:
flash 2015-11-01 17:32:47 +01:00
parent 82ba292600
commit d4063a994f
32 changed files with 225 additions and 253 deletions

View file

@ -20,18 +20,12 @@ class Template
private $template;
private $templateName;
private $templateOptions;
private $fallback;
private $fallbackName;
private $fallbackOptions;
// Initialise templating engine and data
public function __construct()
{
// Set template to default
$this->setTemplate(Configuration::getConfig('site_style'));
// Set a fallback
$this->setFallback(Configuration::getConfig('site_style'));
}
// Set a template name
@ -81,53 +75,6 @@ class Template
$this->template->addExtension(new Twig_Extension_StringLoader());
}
// Set a fallback
private function setFallback($name)
{
// Assign config path to a variable so we don't have to type it out twice
$confPath = ROOT . '_sakura/templates/' . $name . '/template.ini';
// Check if the configuration file exists
if (!file_exists($confPath)) {
trigger_error('Template configuration does not exist', E_USER_ERROR);
}
// Parse and store the configuration
$this->fallbackOptions = parse_ini_file($confPath, true);
// Make sure we're not using a manage template for the main site or the other way around
if (defined('SAKURA_MANAGE') && (bool) $this->fallbackOptions['manage']['mode'] != (bool) SAKURA_MANAGE) {
trigger_error('Incorrect template type', E_USER_ERROR);
}
// Set variables
$this->fallbackName = $name;
// Reinitialise
$this->initFallback();
}
// Initialise main fallback engine
public function initFallback()
{
// Initialise Twig Filesystem Loader
$twigLoader = new Twig_Loader_Filesystem(ROOT . '_sakura/templates/' . $this->fallbackName);
// Environment variable
$twigEnv = [];
// Enable caching
if (Configuration::getConfig('enable_tpl_cache')) {
$twigEnv['cache'] = ROOT . 'cache';
}
// And now actually initialise the templating engine
$this->fallback = new Twig_Environment($twigLoader, $twigEnv);
// Load String template loader
$this->fallback->addExtension(new Twig_Extension_StringLoader());
}
// Set variables
public function setVariables($vars)
{
@ -140,11 +87,7 @@ class Template
try {
return $this->template->render($file, $this->vars);
} catch (\Exception $e) {
try {
return $this->fallback->render($file, $this->vars);
} catch (\Exception $e) {
trigger_error($e->getMessage(), E_USER_ERROR);
}
trigger_error($e->getMessage(), E_USER_ERROR);
}
}
}

View file

@ -8,7 +8,7 @@
namespace Sakura;
// Define Sakura version
define('SAKURA_VERSION', '20151031');
define('SAKURA_VERSION', '20151101');
define('SAKURA_VLABEL', 'Eminence');
define('SAKURA_COLOUR', '#6C3082');
define('SAKURA_STABLE', false);

View file

@ -0,0 +1,5 @@
<div class="forumListing">
{% for category in board.forums %}
{% include 'forum/forumEntry.tpl' %}
{% endfor %}
</div>

View file

@ -0,0 +1,45 @@
{% if category.forums|length and category.forum|length %}
<div class="forumCategory">
<div class="forumCategoryHead">
<div class="forumCategoryTitle">{% if category.forum.forum_type != 1 %}Subforums{% else %}<a href="{{ urls.format('FORUM_SUB', [category.forum.forum_id]) }}">{{ category.forum.forum_name }}</a>{% endif %}</div>
<div class="forumCategoryDescription">{{ category.forum.forum_desc }}</div>
</div>
{% for forum in category.forums %}
<div class="forumSubEntry">
<a href="{% if forum.forum_type == 2 %}{{ forum.forum_link }}{% else %}{{ urls.format('FORUM_SUB', [forum.forum_id]) }}{% endif %}" class="forumSubIcon">
<div class="forumIcon fa fa-3x {% if forum.forum_icon %}{{ forum.forum_icon }}{% else %}{% if forum.forum_type == 2 %}fa-chevron-circle-right{% elseif forum.forum_type == 1 %}fa-folder{% else %}fa-comments{% endif %}{% endif %}"></div>
</a>
<div class="forumSubTitle">
<a href="{% if forum.forum_type == 2 %}{{ forum.forum_link }}{% else %}{{ urls.format('FORUM_SUB', [forum.forum_id]) }}{% endif %}" class="forumSubName">{{ forum.forum_name }}</a>
<div class="forumSubDesc">
{{ forum.forum_desc }}
{% if board.forums[forum.forum_id]|length %}
<ul class="forumSubSubforums">
{% for forum in board.forums[forum.forum_id].forums %}
<li><a href="{% if forum.forum_type == 2 %}{{ forum.forum_link }}{% else %}{{ urls.format('FORUM_SUB', [forum.forum_id]) }}{% endif %}" class="default">{{ forum.forum_name }}</a></li>
{% endfor %}
</ul>
{% endif %}
</div>
</div>
{% if forum.forum_type != 2 %}
<div class="forumSubStats">
<div class="forumSubTopics" title="Amount of topics in this forum.">{{ forum.topic_count }}</div>
<div class="forumSubStatsSeperator">/</div>
<div class="forumSubPosts" title="Amount of posts in this forum.">{{ forum.post_count }}</div>
</div>
<div class="forumSubReplies">
<div>
{% if forum.last_post.post_id %}
<a href="{{ urls.format('FORUM_THREAD', [forum.last_post.topic_id]) }}" class="default">{{ forum.last_post.post_subject }}</a><br />
<span title="{{ forum.last_post.post_time|date(sakura.dateFormat) }}">{{ forum.last_post.elapsed }}</span> by {% if forum.last_poster.data.user_id %}<a href="{{ urls.format('USER_PROFILE', [forum.last_poster.data.user_id]) }}" class="default" style="color: {{ forum.last_poster.colour }}; text-shadow: 0 0 5px {% if forum.last_poster.colour != 'inherit' %}{{ forum.last_poster.colour }}{% else %}#222{% endif %};">{{ forum.last_poster.data.username }}</a>{% else %}[deleted user]{% endif %} <a href="{{ urls.format('FORUM_POST', [forum.last_post.post_id]) }}#p{{ forum.last_post.post_id }}" class="default fa fa-tag"></a>
{% else %}
There are no posts in this forum.
{% endif %}
</div>
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}

View file

@ -0,0 +1,10 @@
{% extends 'global/master.tpl' %}
{% block title %}Forum Listing{% endblock %}
{% block content %}
<div class="homepage forums">
{% include 'elements/statsHeader.tpl' %}
{% include 'forum/forum.tpl' %}
</div>
{% endblock %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -85,8 +85,6 @@
<li><a target="_blank" title="Flashii on Twitter" class="fa fa-twitter" href="https://twitter.com/_flashii"></a></li>
<li><a target="_blank" title="Flashii on YouTube" class="fa fa-youtube-play" href="https://youtube.com/user/flashiinet"></a></li>
<li><a target="_blank" title="Flashii on Steam" class="fa fa-steam" href="https://steamcommunity.com/groups/flashiinet"></a></li>
<li><a target="_blank" title="Circlestorm on BitBucket" class="fa fa-bitbucket" href="https://bitbucket.org/circlestorm"></a></li>
<li><a target="_blank" title="Flashii on osu!" class="fa fa-dot-circle-o" href="https://osu.ppy.sh/#"></a></li>
<li><a title="Subscribe to the news page feed" class="fa fa-rss" href="/news.xml"></a></li>
</ul>
<div class="clear"></div>
@ -126,7 +124,7 @@
</ul>
</div>
{% block content %}
<h1>{{ php.self }} is now printing!</h1>
<div style="text-align: center; font-family: 'Exo2-0-LightItalic', sans-serif; font-size: 3em; line-height: 1.5em; margin: 10px auto">This template doesn't exist (yet)!<br />Switch back to Yuuno via the User Settings to view this page!</div>
{% endblock %}
</div>
</div>
@ -135,7 +133,7 @@
<div class="ft-logo"></div>
<div class="ft-text">
<div>Copyright &copy; 2013-2015 <a href="http://flash.moe/" target="_blank">Flashwave</a>, <a href="http://circlestorm.net/" target="_blank">et al</a>.</div>
<div><a href="{{ urls.format('INFO_PAGE', ['terms']) }}">Terms of Service</a> | <a href="{{ urls.format('INFO_PAGE', ['contact']) }}">Contact</a> | <a href="{{ urls.format('SITE_FAQ') }}">FAQ</a> | <a href="{{ urls.format('INFO_PAGE', ['rules']) }}">Rules</a> | <a href="{{ urls.format('CHANGELOG') }}">Changelog</a> | <a href="https://fiistat.us/">Status</a></div>
<div><a href="{{ urls.format('INFO_PAGE', ['terms']) }}">Terms of Service</a> | <a href="{{ urls.format('INFO_PAGE', ['contact']) }}">Contact</a> | <a href="{{ urls.format('SITE_FAQ') }}">FAQ</a> | <a href="{{ urls.format('INFO_PAGE', ['rules']) }}">Rules</a> | <a href="https://sakura.flash.moe/">Changelog</a> | <a href="https://fiistat.us/">Status</a></div>
</div>
</div>
</div>

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -0,0 +1 @@
{% extends 'global/master.tpl' %}

View file

@ -29,7 +29,7 @@
</tr>
</tfoot>
<tbody>
{% for topic in board.topics %}
{% for topic in board.topics[currentPage] %}
{% include 'forum/topicEntry.tpl' %}
{% endfor %}
</tbody>

View file

@ -8,7 +8,7 @@
<div class="head">{{ forum.forum.forum_name }} / {{ topic.topic_title }}</div>
{% include 'forum/forumBtns.tpl' %}
<table class="posts">
{% for post in posts %}
{% for post in posts[currentPage] %}
<tr class="post" id="p{{ post.post_id }}">
<td class="userpanel">
{% if not post.user.checkPermission('SITE', 'DEACTIVATED') or post.user.checkPermission('SITE', 'RESTRICTED') %}<a href="{{ urls.format('USER_PROFILE', [post.user.data.user_id]) }}" class="default username" style="color: {{ post.user.colour }}; text-shadow: 0 0 5px {% if post.user.colour != 'inherit' %}{{ post.user.colour }}{% else %}#222{% endif %};" title="Go to {{ post.user.data.username }}'s profile">{{ post.user.data.username }}</a>

View file

@ -189,6 +189,10 @@ a:active {
text-align: right;
}
#footer > .inner a {
color: inherit;
}
/*
* Site header
*/
@ -660,7 +664,7 @@ a:active {
flex-shrink: 1;
background: rgba(148, 117, 178, .2);
box-shadow: 0 2px 6px rgba(0, 0, 0, .75);
margin: 5px;
margin: 0 10px;
}
.homepage .frontStats > div > div {
@ -711,3 +715,126 @@ a:active {
.news-post > .news-content > .news-text {
padding: 3px 4px;
}
/*
* Forums
*/
.forums .forumListing .forumCategory {
margin: 10px;
padding: 5px;
background: #3A2E44;
box-shadow: 0 2px 6px rgba(0, 0, 0, .75);
}
.forums .forumListing .forumCategory .forumCategoryHead {
color: #FFF;
padding: 5px;
text-shadow: 1px 1px 2px rgba(0, 0, 0, .75);
}
.forums .forumListing .forumCategory .forumCategoryHead .forumCategoryTitle {
font-size: 2em;
line-height: .8em;
padding-bottom: 5px;
font-family: "Exo2-0-LightItalic", sans-serif;
}
.forums .forumListing .forumCategory .forumCategoryHead .forumCategoryDescription {
font-size: .8em;
line-height: 1.2em;
}
.forums .forumListing .forumCategory .forumCategoryHead a {
color: inherit !important;
}
.forums .forumListing .forumCategory .forumSubEntry {
border-top: 1px solid #231C29;
padding: 5px;
display: flex;
transition: .2s;
}
.forums .forumListing .forumCategory .forumSubEntry:hover {
background: #231C29;
}
.forums .forumListing .forumCategory .forumSubEntry .forumSubIcon {
display: inline-flex;
align-items: center;
justify-content: center;
text-align: center;
flex-shrink: 0;
flex-grow: 0;
width: 50px;
}
.forums .forumListing .forumCategory .forumSubEntry .forumSubIcon .forumIcon {
transition: .1s;
}
.forums .forumListing .forumCategory .forumSubEntry:hover .forumSubIcon .forumIcon {
font-size: 3.5em;
}
.forums .forumListing .forumCategory .forumSubEntry a {
color: inherit;
text-decoration: none;
}
.forums .forumListing .forumCategory .forumSubTitle {
flex-grow: 2;
border-right: 1px solid #231C29;
text-shadow: 1px 1px 2px rgba(0, 0, 0, .75);
}
.forums .forumListing .forumCategory .forumSubEntry:hover .forumSubTitle {
border-right: 1px solid #3A2E44;
}
.forums .forumListing .forumCategory .forumSubTitle .forumSubName {
font-size: 1.5em;
}
.forums .forumListing .forumCategory .forumSubStats {
flex-shrink: 0;
font-family: "Exo2-0-LightItalic", sans-serif;
padding: 0 10px;
min-width: 70px;
text-shadow: 1px 1px 2px rgba(0, 0, 0, .75);
line-height: .5em;
border-right: 1px solid #231C29;
display: inline-flex;
justify-content: center;
align-items: center;
}
.forums .forumListing .forumCategory .forumSubEntry:hover .forumSubStats {
border-right: 1px solid #3A2E44;
}
.forums .forumListing .forumCategory .forumSubStats div {
display: inline-block;
}
.forums .forumListing .forumCategory .forumSubStats .forumSubTopics {
font-size: 1.5em;
margin-bottom: 10px;
}
.forums .forumListing .forumCategory .forumSubStats .forumSubStatsSeperator {
font-size: 1.2em;
}
.forums .forumListing .forumCategory .forumSubStats .forumSubPosts {
font-size: .8em;
margin-top: 14px;
}
.forums .forumListing .forumCategory .forumSubReplies {
padding: 0 5px;
display: inline-flex;
align-items: center;
line-height: 1.2em;
min-width: 200px;
}

View file

@ -4,9 +4,7 @@
// Get or set cookies
function cookieData(action, name, data) {
switch(action) {
case 'get':
return (result = new RegExp('(^|; )' + encodeURIComponent(name) + '=([^;]*)').exec(document.cookie)) ? result[2] : '';
@ -16,21 +14,16 @@ function cookieData(action, name, data) {
default:
return null;
}
}
// Get the current unix/epoch timestamp
function epochTime() {
return Math.floor(Date.now() / 1000);
}
// Create a notification box
function notifyUI(content) {
// Grab the container and create an ID
var container = document.getElementById('notifications');
var identifier = 'sakura-notification-' + Date.now();
@ -100,7 +93,6 @@ function notifyUI(content) {
// Play sound if requested
if(content.sound > 0) {
// Create sound element and mp3 and ogg sources
var sound = document.createElement('audio');
var soundMP3 = document.createElement('source');
@ -118,27 +110,20 @@ function notifyUI(content) {
// Play the sound
sound.play();
}
// If keepalive is 0 keep the notification open "forever" (until the user closes it or changes the page)
if(content.timeout > 0) {
// Set set a timeout and execute notifyClose() after amount of milliseconds specified
setTimeout(function() {
// Use the later defined notifyClose function
notifyClose(identifier);
}, content.timeout);
}
}
// Closing a notification box
function notifyClose(id) {
// Get the element and assign it to a variable
var element = document.getElementById(id);
@ -147,35 +132,25 @@ function notifyClose(id) {
// Remove the element after 500 milliseconds (animation takes 400)
setTimeout(function() {
// Use the later defined removeId function
removeId(id);
}, 410);
}
// Opening a link to a notifcated thing (what even)
function notifyOpen(id) {
var sakuraHref = document.getElementById(id).getAttribute('sakurahref');
if(typeof sakuraHref !== 'undefined') {
window.location = sakuraHref;
}
}
// Request notifications
function notifyRequest(session) {
// Check if the document isn't hidden
if(document.hidden) {
return;
}
// Create XMLHttpRequest and notifyURL
@ -184,19 +159,15 @@ function notifyRequest(session) {
// Wait for the ready state to change
notificationWatcher.onreadystatechange = function() {
// Wait for it to reach the "complete" stage
if(notificationWatcher.readyState === 4) {
// Continue if the HTTP return was 200
if(notificationWatcher.status === 200) {
// Assign the JSON parsed content to a variable
var notifyGet = JSON.parse(notificationWatcher.responseText);
// If nothing was set stop
if(typeof notifyGet == 'undefined') {
// Tell the user something went wrong...
notifyUI({
"title": "An error occurred!",
@ -208,18 +179,13 @@ function notifyRequest(session) {
// ...then prevent the function from contiuing
return;
}
// Go over every return notification and pass the object to it
for(var notifyID in notifyGet) {
notifyUI(notifyGet[notifyID]);
}
} else if((notificationWatcher.status + '').substring(0, 1) == '5') {
// ELse tell the user there was an internal server error...
notifyUI({
"title": "An internal server error occurred!",
@ -228,52 +194,39 @@ function notifyRequest(session) {
"timeout": 60000,
"sound": false
});
}
}
};
// Make the request
notificationWatcher.open('GET', notifyURL, true);
notificationWatcher.send();
}
// Removing all elements with a certain class
function removeClass(className) {
// Get the elements
var objectCont = document.getElementsByClassName(className);
// Use a while loop instead of a for loop (Array keys change) to remove each element
while(objectCont.length > 0) {
objectCont[0].parentNode.removeChild(objectCont[0]);
}
}
// Removing an element by ID
function removeId(id) {
// Get the element
var objectCont = document.getElementById(id);
// If the element exists use the parent node to remove it
if(typeof(objectCont) != "undefined" && objectCont !== null) {
objectCont.parentNode.removeChild(objectCont);
}
}
// Show the full-page busy window
function ajaxBusyView(show, message, type) {
// Get elements
var busyCont = document.getElementById('ajaxBusy');
var busyStat = document.getElementById('ajaxStatus');
@ -283,7 +236,6 @@ function ajaxBusyView(show, message, type) {
// Select the proper icon
switch(type) {
case 'ok':
busyAnimIco = 'fa fa-check fa-4x';
break;
@ -294,15 +246,12 @@ function ajaxBusyView(show, message, type) {
default:
busyAnimIco = 'fa fa-refresh fa-spin fa-4x';
break;
}
// If requested to show the window build it
if(show) {
// Make sure it doesn't exist already
if(busyCont === null) {
// Container
var createBusyCont = document.createElement('div');
createBusyCont.className = 'ajax-busy';
@ -330,7 +279,6 @@ function ajaxBusyView(show, message, type) {
busyCont = document.getElementById('ajaxBusy');
busyStat = document.getElementById('ajaxStatus');
busyAnim = document.getElementById('ajaxAnimate');
} // If the container already exists just continue and update the elements
// Alter the icon
@ -338,51 +286,34 @@ function ajaxBusyView(show, message, type) {
// Change the message
busyStat.innerHTML = (message === null ? 'Unknown' : message);
} else { // If show is false remove the element...
// ...but just do nothing if the container doesn't exist
if(busyCont !== null) {
// Create the fadeout with a 10ms interval
var fadeOut = setInterval(function() {
// Set an opacity if it doesn't exist yet
if(busyCont.style.opacity === null || busyCont.style.opacity === "") {
busyCont.style.opacity = 1;
}
// If the value isn't 0 yet start subtract .1 from the opacity
if(busyCont.style.opacity > 0) {
busyCont.style.opacity = busyCont.style.opacity - 0.1;
} else { // When we've reached 0 remove the container element and clear the fadeout interval
removeId('ajaxBusy');
clearInterval(fadeOut);
}
}, 10);
}
}
}
// Making a post request using AJAX
function ajaxPost(url, data, callback) {
// Combine name and value with an = inbetween
var query = [];
for(var i in data) {
query.push(encodeURIComponent(i) +"="+ encodeURIComponent(data[i]));
}
// Join the array
@ -396,16 +327,11 @@ function ajaxPost(url, data, callback) {
// Wait for the readiness to change
request.onreadystatechange = function() {
// Wait for completion
if(request.readyState === 4) {
if(request.status === 200) {
callback.call(request.responseText);
} else {
ajaxBusyView(false);
notifyUI({
@ -417,11 +343,8 @@ function ajaxPost(url, data, callback) {
});
return null;
}
}
};
// Set headers
@ -429,20 +352,16 @@ function ajaxPost(url, data, callback) {
// Submit the request
request.send(query);
}
// Convert href attribute to an object
function prepareAjaxLink(linkId, callback, attrs) {
// Get the elements
var link = typeof linkId === 'object' ? linkId : document.getElementById(linkId);
// Catch null
if(link == null) {
return;
}
// Get the href value
@ -459,13 +378,11 @@ function prepareAjaxLink(linkId, callback, attrs) {
// Split the name and values of the variables
for(var key in variablesNotSplit) {
// Split name and value
var newVar = variablesNotSplit[key].split('=');
// Push it into the object
variables[newVar[0]] = newVar[1];
}
// Add ajax=true
@ -474,11 +391,9 @@ function prepareAjaxLink(linkId, callback, attrs) {
// Update link attributes
link.setAttribute('href', 'javascript:void(0);');
link.setAttribute('onclick', callback +'(\''+ action +'\', JSON.parse(\''+ JSON.stringify(variables) +'\')'+ (typeof attrs != 'undefined' ? attrs : '') +');');
}
function prepareAjaxForm(formId, message, resetCaptchaOnFailure) {
// Get the form
var form = document.getElementById(formId);
@ -494,12 +409,10 @@ function prepareAjaxForm(formId, message, resetCaptchaOnFailure) {
// Update form
form.setAttribute('onsubmit', 'submitPost(\''+ form.action +'\', formToObject(\''+ formId +'\'), true, \''+ (message ? message : 'Please wait...') +'\', '+ (resetCaptchaOnFailure ? 'true' : 'false') +');');
form.setAttribute('action', 'javascript:void(0);');
}
// Convert form to an object
function formToObject(formId) {
// Get form data
var form = document.getElementById(formId);
@ -511,23 +424,17 @@ function formToObject(formId) {
// Sort children and make them ready for submission
for(var i in children) {
if(typeof children[i] == 'object') {
requestParts[children[i].name] = ((typeof children[i].type !== "undefined" && children[i].type.toLowerCase() == "checkbox") ? (children[i].checked ? 1 : 0) : children[i].value);
}
}
// Return the object
return requestParts;
}
// Quickly building a form for god knows what reason
function generateForm(formId, formAttr, formData, appendTo) {
// Create form elements and assign ID
var i;
var form = document.createElement('form');
@ -535,53 +442,39 @@ function generateForm(formId, formAttr, formData, appendTo) {
// Set additional attributes
if(formAttr !== null) {
for(i in formAttr) {
form.setAttribute(i, formAttr[i]);
}
}
// Generate input elements
for(i in formData) {
var disposableVar = document.createElement('input');
disposableVar.setAttribute('type', 'hidden');
disposableVar.setAttribute('name', i);
disposableVar.setAttribute('value', formData[i]);
form.appendChild(disposableVar);
}
// Append to another element if requested
if(appendTo !== null) {
document.getElementById(appendTo).appendChild(form);
}
// Return the completed form
return form;
}
// Submitting a form using an AJAX POST request
function submitPost(action, requestParts, busyView, msg, resetCaptchaOnFailure) {
// If requested display the busy thing
if(busyView) {
ajaxBusyView(true, msg, 'busy');
}
// Submit the AJAX request
var request = ajaxPost(action, requestParts, function() {
submitPostHandler(this, busyView, resetCaptchaOnFailure);
});
}
@ -594,144 +487,114 @@ function submitPostHandler(result, busyView, resetCaptchaOnFailure) {
// If using the busy view thing update the text displayed to the return of the request
if(busyView) {
ajaxBusyView(true, result[0], (result[1] == '1' ? 'ok' : 'fail'));
}
// If request reset the recaptcha on failure
if(resetCaptchaOnFailure && result[1] != '1' && sakuraVars.recaptchaEnabled != '0') {
grecaptcha.reset();
}
setTimeout(function(){
if(busyView) {
ajaxBusyView(false);
}
if(result[1] == '1') {
window.location = result[2];
}
}, 2000);
}
// Encode UTF-8
function utf8_encode(str) {
return unescape(encodeURIComponent(str));
}
// Decode UTF-8
function utf8_decode(str) {
return decodeURIComponent(escape(str));
}
// Calculate the amount of unique characters in a string
function uniqueChars(str) {
// Create storage array and count var
var usedChars = [];
var count = 0;
// Count the amount of unique characters
for(var i = 0; i < str.length; i++) {
// Check if we already counted this character
if(usedChars.indexOf(str[i]) == -1) {
// Push the character into the used array
usedChars.push(str[i]);
// Up the count
count++;
}
}
// Return the count
return count;
}
// Alternative for Math.log2() since it's still experimental
function log2(num) {
return Math.log(num) / Math.log(2);
}
// Calculate password entropy
function pwdEntropy(pwd) {
// Decode utf-8 chars
pwd = utf8_decode(pwd);
// Count the amount of unique characters in the password and calculate the entropy
return uniqueChars(pwd) * log2(256);
}
// Check if password is within the minimum entropy value
function checkPwdEntropy(pwd) {
return (pwdEntropy(pwd) >= sakuraVars.minPwdEntropy);
}
// Check the length of a string
function checkStringLength(str, min, max) {
// Get length of string
var len = str.length;
// Check if it meets the minimum
if(len < min)
if(len < min) {
return false;
}
// Check if it meets the maximum
if(len > max)
if(len > max) {
return false;
}
// If it passes both return true
return true;
}
// Validate email address formats
function validateEmail(email) {
// The regex
var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,48})+$/;
// is of fix
// Test it (which returns true or false)
return re.test(email);
}
// Check registration variables
function registerVarCheck(id, mode, option) {
// Get the element we're working with
var input = document.getElementById(id);
var check = null;
// Use the proper mode
switch(mode) {
case 'confirmpw':
option = document.getElementById(option);
check = input.value === option.value;
@ -749,26 +612,19 @@ function registerVarCheck(id, mode, option) {
default:
check = checkStringLength(input.value, sakuraVars.minUserLen, sakuraVars.maxUserLen);
break;
}
if(input.className.indexOf(check ? 'green' : 'red') < 0) {
input.className = input.className + ' ' + (check ? 'green' : 'red');
}
if(input.className.indexOf(check ? 'red' : 'green') > 0) {
input.className = input.className.replace(check ? 'red' : 'green', '');
}
}
// Initialising the element parallax functionality
function initialiseParallax(id) {
// Assign the element to a variable
var parallax = document.getElementById(id);
@ -788,12 +644,10 @@ function initialiseParallax(id) {
parallax.style.right = convertParallaxPositionValue(e.clientX, false, true) + 'px';
});
}
// Converting the position value of the mouseover to a pixel value
function convertParallaxPositionValue(pos, dir, neg) {
// Get the body element
var body = document.getElementsByTagName('body')[0];
@ -802,9 +656,7 @@ function convertParallaxPositionValue(pos, dir, neg) {
// If someone decided to fuck with the inputs reset it to 0%
if(position < 0 || position > 100) {
position = 0;
}
// Do the first maths
@ -812,9 +664,7 @@ function convertParallaxPositionValue(pos, dir, neg) {
// If the negative flag is set inverse the number
if(neg) {
position = -position;
}
// Subtract another 2.5 to make the element not go all over the place
@ -822,12 +672,10 @@ function convertParallaxPositionValue(pos, dir, neg) {
// Return the proper position value
return position;
}
// Smooth scrolling
function scrollToTop() {
// Get the current position
var windowY = window.pageYOffset - 100;
@ -836,11 +684,8 @@ function scrollToTop() {
// Keep executing this function till we're at the top
if(windowY + 1 > 0) {
setTimeout(function(){scrollToTop();}, 10);
}
}
function replaceTag(tag) {
@ -852,7 +697,6 @@ function safeTagsReplace(str) {
}
function commentReply(id, session, category, action, avatar) {
// Find subject post
var replyingTo = document.getElementById('comment-' + id);
@ -952,20 +796,17 @@ function commentReply(id, session, category, action, avatar) {
// Prepare AJAX submission
prepareAjaxForm(replyForm.id, 'Replying...');
}
// Formatting money
Number.prototype.formatMoney = function(c, d, t) {
var n = this,
c = isNaN(c = Math.abs(c)) ? 2 : c,
d = d == undefined ? "." : d,
t = t == undefined ? "," : t,
s = n < 0 ? "-" : "",
i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
j = (j = i.length) > 3 ? j % 3 : 0;
return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
Number.prototype.formatMoney = function(u, c, k) {
var f = this,
u = isNaN(u = Math.abs(u)) ? 2 : u,
c = c == undefined ? "." : c,
k = k == undefined ? "," : k,
i = f < 0 ? "-" : "",
n = parseInt(f = Math.abs(+f || 0).toFixed(u)) + "",
g = (g = n.length) > 3 ? g % 3 : 0;
return i + (g ? n.substr(0, g) + k : "") + n.substr(g).replace(/(\c{3})(?=\c)/g, "$1" + k) + (u ? c + Math.abs(f - n).toFixed(u).slice(2) : "");
};

View file

@ -16,10 +16,8 @@ $forum = Forum::getForum(isset($_GET['f']) ? $_GET['f'] : 0);
if (!$forum) {
// Set render data
$renderData['page'] = [
'title' => 'Information',
'message' => 'The subforum you tried to access does not exist.',
];
// Print template
@ -31,11 +29,9 @@ if (!$forum) {
if ($forum['forum']['forum_type'] === 2) {
// Set render data
$renderData['page'] = [
'title' => 'Information',
'message' => 'The forum you tried to access is a link. You\'re being redirected.',
'redirect' => $forum['forum']['forum_link'],
];
// Print template
@ -44,17 +40,14 @@ if ($forum['forum']['forum_type'] === 2) {
}
$renderData['board'] = [
'forums' => [
$forum,
],
'topics' => Forum::getTopics($forum['forum']['forum_id']),
'topics' => array_chunk($forum['topics'], 25, true),
'viewforum' => true,
'viewtopic' => false,
];
$renderData['currentPage'] = isset($_GET['page']) && ($_GET['page'] - 1) >= 0 ? $_GET['page'] - 1 : 0;
// Print page contents
print Templates::render('forum/viewforum.tpl', $renderData);

View file

@ -20,9 +20,7 @@ $topic = Forum::getTopic(
if (!$topic) {
// Set render data
$renderData['page'] = [
'message' => 'The topic you tried to access does not exist.',
];
// Print template
@ -32,14 +30,12 @@ if (!$topic) {
// Set additional render data
$renderData = array_merge($renderData, $topic, [
'board' => [
'viewforum' => false,
'viewtopic' => true,
],
'posts' => array_chunk($topic['posts'], 10, true),
'currentPage' => isset($_GET['page']) && ($_GET['page'] - 1) >= 0 ? $_GET['page'] - 1 : 0,
]);
// Print page contents