r20151209

This commit is contained in:
flash 2015-12-09 21:21:08 +01:00
parent 3a48bfd912
commit 60b60ad30a
14 changed files with 341 additions and 1100 deletions

View file

@ -6,10 +6,10 @@
namespace Sakura; namespace Sakura;
/** /**
* Class Action * Class ActionCode
* @package Sakura * @package Sakura
*/ */
class Action class ActionCode
{ {
private $actions = []; // Contains the action methods private $actions = []; // Contains the action methods
private $code = null; // Contains the action code we're working with private $code = null; // Contains the action code we're working with

View file

@ -196,7 +196,7 @@ class Main
if (isset($errid)) { if (isset($errid)) {
$errorPage .= '<p>The error and surrounding data has been logged.</p> $errorPage .= '<p>The error and surrounding data has been logged.</p>
<h2>' . ($detailed ? 'Report the following text to a staff member' : 'Logged as') . '</h2> <h2>' . (!$detailed ? 'Report the following text to a staff member' : 'Logged as') . '</h2>
<pre class="error">' . $errid . '</pre>'; <pre class="error">' . $errid . '</pre>';
} else { } else {
$errorPage .= '<p>Sakura was not able to log this error which could mean that there was an error $errorPage .= '<p>Sakura was not able to log this error which could mean that there was an error
@ -205,7 +205,7 @@ class Main
know about this error if it occurs again.</p>'; know about this error if it occurs again.</p>';
} }
if (!$detailed) { if ($detailed) {
$errorPage .= ' <h2>Summary</h2> $errorPage .= ' <h2>Summary</h2>
<pre class="error">' . $error . '</pre> <pre class="error">' . $error . '</pre>
<h2>Backtraces</h2>'; <h2>Backtraces</h2>';

View file

@ -4,5 +4,6 @@
*/ */
.main { .main {
margin: -40px 10px 0; margin: -40px auto 0;
max-width: 1280px;
} }

View file

@ -1,618 +1,503 @@
/* /*
* Sakura Yuuno JavaScript * Sakura Yuuno
*/ */
// Spawns a notification
// Create a notification box
function notifyUI(content) { function notifyUI(content) {
// Grab the container and create an ID // Grab the container and create an ID
var container = document.getElementById('notifications'); var cont = document.getElementById('notifications');
var identifier = 'sakura-notification-' + Date.now(); var id = 'sakura-notification-' + Date.now();
// Create the elements
// Create the notification element and children var alert = document.createElement('div');
var notif = document.createElement('div'); var aIcon = document.createElement('div');
var notifIcon = document.createElement('div'); var aCont = document.createElement('div');
var notifContent = document.createElement('div'); var aTitle = document.createElement('div');
var notifTitle = document.createElement('div'); var aText = document.createElement('div');
var notifText = document.createElement('div'); var aClose = document.createElement('div');
var notifClose = document.createElement('div'); var aCIcon = document.createElement('div');
var notifCloseIcon = document.createElement('div'); var aClear = document.createElement('div');
var notifClear = document.createElement('div'); var aIconCont;
var iconCont; // Add attributes to the main element
alert.className = 'notification-enter';
// Add ID and class on notification container alert.id = id;
notif.className = 'notification-enter'; // Add the icon
notif.setAttribute('id', identifier); if ((typeof content.img).toLowerCase() === 'undefined' && content.img == null && !(content.img.length > 1)) {
aIconCont = document.createElement('div');
// Add icon aIconCont.className = 'font-icon fa fa-info fa-4x';
notifIcon .className = 'notification-icon';
if(content.img.substring(0, 5) == "FONT:") {
iconCont = document.createElement('div');
iconCont.className = 'font-icon fa ' + content.img.replace('FONT:', '') + ' fa-4x';
} else {
iconCont = document.createElement('img');
iconCont.setAttribute('alt', identifier);
iconCont.setAttribute('src', content.img);
} }
notifIcon .appendChild(iconCont); else if (content.img.substr(0, 5) == 'FONT:') {
notif .appendChild(notifIcon); aIconCont = document.createElement('div');
aIconCont.className = 'font-icon fa ' + content.img.replace('FONT:', '') + ' fa-4x';
// Add content
var notifTitleNode = document.createTextNode(content.title);
var notifTextNode = document.createTextNode(content.text);
notifContent .className = 'notification-content';
notifTitle .className = 'notification-title';
notifText .className = 'notification-text';
notifTitle .appendChild(notifTitleNode);
notifText .appendChild(notifTextNode);
if(content.link) {
notif .setAttribute('sakurahref', content.link);
notifContent.setAttribute('onclick', content.link.substring(0, 11) == 'javascript:' ? content.link.substring(11) : 'notifyOpen(this.parentNode.id);');
} }
notifContent .appendChild(notifTitle); else {
notifContent .appendChild(notifText); aIconCont = document.createElement('img');
notif .appendChild(notifContent); aIconCont.alt = id;
aIconCont.img = content.img;
// Add close button }
notifClose .className = 'notification-close'; aIcon.appendChild(aIconCont);
notifClose .setAttribute('onclick', 'notifyClose(this.parentNode.id);'); aIcon.className = 'notification-icon';
notifClose .appendChild(notifCloseIcon); alert.appendChild(aIcon);
notif .appendChild(notifClose); // Add the content
aCont.className = 'notification-content';
// Add .clear aTitle.className = 'notification-title';
notifClear .className = 'clear'; aText.className = 'notifcation-text';
notif .appendChild(notifClear); aTitle.textContent = content.title;
aText.textContent = content.text;
// Append the notification to the document so it actually shows up to the user also add the link // Check if a link exists and add if it does
container.appendChild(notif); if ((typeof content.link).toLowerCase() !== 'undefined' && content.link !== null && content.link.length > 1) {
alert.setAttribute('sakurahref', content.link);
// Play sound if requested aCont.setAttribute('onclick', content.link.substr(0, 11) == 'javascript:' ? content.link.substring(11) : 'notifyOpen(this.parentNode.id);');
if(content.sound > 0) { }
// Create sound element and mp3 and ogg sources // Append stuff
var sound = document.createElement('audio'); aCont.appendChild(aTitle);
var soundMP3 = document.createElement('source'); aCont.appendChild(aText);
var soundOGG = document.createElement('source'); alert.appendChild(aCont);
// Add the close button
// Assign the proper attributes to the sources aClose.className = 'notification-close';
soundMP3.setAttribute('src', '//' + sakuraVars.content_path + '/sounds/notify.mp3'); aClose.setAttribute('onclick', 'notifyClose(this.parentNode.id);');
soundMP3.setAttribute('type', 'audio/mp3'); aClose.appendChild(aCIcon);
soundOGG.setAttribute('src', '//' + sakuraVars.content_path + '/sounds/notify.ogg'); alert.appendChild(aClose);
soundOGG.setAttribute('type', 'audio/ogg'); // Append the notification to the document
cont.appendChild(alert);
// Append the children // Play sound if request
sound.appendChild(soundMP3); if (content.sound) {
sound.appendChild(soundOGG); // Create the elements
var sound = document.createElement('audio');
// Play the sound var mp3 = document.createElement('source');
var ogg = document.createElement('source');
// Assign attribs
mp3.type = 'audio/mp3';
ogg.type = 'audio/ogg';
mp3.src = sakuraVars.content_path + '/sounds/notify.mp3';
ogg.src = sakuraVars.content_path + '/sounds/notify.ogg';
// Append
sound.appendChild(mp3);
sound.appendChild(ogg);
// And play
sound.play(); sound.play();
} }
// If keepalive is 0 keep the notification open forever
// If keepalive is 0 keep the notification open "forever" (until the user closes it or changes the page) if (content.timeout > 0) {
if(content.timeout > 0) { // Set a timeout and close after an amount
// Set set a timeout and execute notifyClose() after amount of milliseconds specified setTimeout(function () {
setTimeout(function() { notifyClose(id);
// Use the later defined notifyClose function
notifyClose(identifier);
}, content.timeout); }, content.timeout);
} }
} }
// Closing a notification
// Closing a notification box
function notifyClose(id) { function notifyClose(id) {
// Get the element and assign it to a variable // Get the element
var element = document.getElementById(id); var e = document.getElementById(id);
// Add the animation
// Do the animation e.className = 'notification-exit';
element.className = 'notification-exit'; // Remove after 410 ms
setTimeout(function () {
// Remove the element after 500 milliseconds (animation takes 400)
setTimeout(function() {
// Use the later defined removeId function
Sakura.removeById(id); Sakura.removeById(id);
}, 410); }, 410);
} }
// Opening an alerted link
// Opening a link to a notifcated thing (what even)
function notifyOpen(id) { function notifyOpen(id) {
var sakuraHref = document.getElementById(id).getAttribute('sakurahref'); var sakuraHref = document.getElementById(id).getAttribute('sakurahref');
if ((typeof sakuraHref).toLowerCase() !== 'undefined') {
if(typeof sakuraHref !== 'undefined') { window.location.assign(sakuraHref);
window.location = sakuraHref;
} }
} }
// Request notifications // Request notifications
function notifyRequest(session) { function notifyRequest(session) {
// Check if the document isn't hidden // Check if the document isn't hidden
if(document.hidden) { if (document.hidden) {
return; return;
} }
// Create AJAX object
// Create AJAX var get = new AJAX();
var alertGet = new AJAX(); get.setUrl('/settings.php?request-notifications=true&time=' + Sakura.epoch() + '&session=' + session);
alertGet.setUrl('/settings.php?request-notifications=true&time=' + Sakura.epoch() + '&session=' + session); // Add callbacks
get.addCallback(200, function () {
alertGet.addCallback(200, function () { // Assign the parsed JSON
// Assign the JSON parsed content to a variable var data = JSON.parse(get.response());
var data = JSON.parse(alertGet.response()); // Check if nothing went wrong
if ((typeof data).toLowerCase() === 'undefined') {
// If nothing was set stop // Inform the user
if (typeof data == 'undefined') { throw "No or invalid data was returned";
// Tell the user something went wrong... // Stop
throw "No data returned";
// ...then prevent the function from contiuing
return; return;
} }
// Create an object for every notification
// Go over every return notification and pass the object to it
for (var id in data) { for (var id in data) {
notifyUI(data[id]); notifyUI(data[id]);
} }
}); });
get.start(HTTPMethods.GET);
alertGet.addCallback(0, function () {
// Tell the user something went wrong...
throw "Notification request failed";
});
alertGet.start(HTTPMethods.GET);
} }
// Show the full page busy window
// Show the full-page busy window
function ajaxBusyView(show, message, type) { function ajaxBusyView(show, message, type) {
if (message === void 0) { message = null; }
if (type === void 0) { type = null; }
// Get elements // Get elements
var busyCont = document.getElementById('ajaxBusy'); var cont = document.getElementById('ajaxBusy');
var busyStat = document.getElementById('ajaxStatus'); var stat = document.getElementById('ajaxStatus');
var busyAnim = document.getElementById('ajaxAnimate'); var anim = document.getElementById('ajaxAnimate');
var pageContent = document.getElementById('contentwrapper'); var body = document.getElementById('contentwrapper');
var busyAnimIco; var icon = 'fa fa-4x ';
// Select the proper icon // Select the proper icon
switch(type) { switch (type) {
case 'ok': case 'ok':
busyAnimIco = 'fa fa-check fa-4x'; icon += 'fa-check';
break; break;
case 'fail': case 'fail':
busyAnimIco = 'fa fa-remove fa-4x'; icon += 'fa-remove';
break; break;
case 'busy': case 'busy':
default: default:
busyAnimIco = 'fa fa-refresh fa-spin fa-4x'; icon += 'fa-refresh fa-spin';
break; break;
} }
// If request to show the window, build it
// If requested to show the window build it if (show) {
if(show) { if ((typeof cont).toLowerCase() === 'undefined' || cont === null) {
// Make sure it doesn't exist already
if(busyCont === null) {
// Container // Container
var createBusyCont = document.createElement('div'); var cCont = document.createElement('div');
createBusyCont.className = 'ajax-busy'; cCont.className = 'ajax-busy';
createBusyCont.setAttribute('id', 'ajaxBusy'); cCont.id = 'ajaxBusy';
// Inner
// Inner box var cInner = document.createElement('div');
var createBusyInner = document.createElement('div'); cInner.className = 'ajax-inner';
createBusyInner.className = 'ajax-inner'; cCont.appendChild(cInner);
createBusyCont.appendChild(createBusyInner); // Desc
var cMsg = document.createElement('h2');
// Action description cMsg.id = 'ajaxStatus';
var createBusyMsg = document.createElement('h2'); cInner.appendChild(cMsg);
createBusyMsg.setAttribute('id', 'ajaxStatus'); // Icon
createBusyInner.appendChild(createBusyMsg); var cIco = document.createElement('div');
cIco.id = 'ajaxAnimate';
// FontAwesome icon cInner.appendChild(cIco);
var createBusySpin = document.createElement('div'); // Append to document
createBusySpin.setAttribute('id', 'ajaxAnimate'); body.appendChild(cCont);
createBusyInner.appendChild(createBusySpin); // Reassign
cont = document.getElementById('ajaxBusy');
// Append the element to the actual page stat = document.getElementById('ajaxStatus');
pageContent.appendChild(createBusyCont); anim = document.getElementById('ajaxAnimate');
}
// Reassign the previously assigned variables // Update the icon
busyCont = document.getElementById('ajaxBusy'); anim.className = icon;
busyStat = document.getElementById('ajaxStatus'); // Update the message
busyAnim = document.getElementById('ajaxAnimate'); stat.textContent = (message === null ? '' : message);
} // If the container already exists just continue and update the elements }
else {
// Alter the icon if (cont !== null) {
busyAnim.className = busyAnimIco; var out = setInterval(function () {
if (cont.style.opacity === null || cont.style.opacity === "") {
// Change the message cont.style.opacity = "1";
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 subtract by .1
// If the value isn't 0 yet start subtract .1 from the opacity if (parseInt(cont.style.opacity) > 0) {
if(busyCont.style.opacity > 0) { cont.style.opacity = (parseInt(cont.style.opacity) - 0.1).toString();
busyCont.style.opacity = busyCont.style.opacity - 0.1; }
} else { // When we've reached 0 remove the container element and clear the fadeout interval else {
Sakura.removeById('ajaxBusy'); Sakura.removeById('ajaxBusy');
clearInterval(fadeOut); clearInterval(out);
} }
}, 10); }, 10);
} }
} }
} }
// Making a post request using AJAX // Making a post request using AJAX
function ajaxPost(url, data, callback) { function ajaxPost(url, data, callback) {
// Create AJAX // Create AJAX
var request = new AJAX(); var request = new AJAX();
// Set url // Set url
request.setUrl(url); request.setUrl(url);
// Add callbacks // Add callbacks
request.addCallback(200, function () { request.addCallback(200, function () {
callback.call(request.response()) callback.call(request.response());
}); });
request.addCallback(0, function () { request.addCallback(0, function () {
ajaxBusyView(false); ajaxBusyView(false);
throw "POST Request failed"; throw "POST Request failed";
}); });
// Add header // Add header
request.addHeader('Content-Type', 'application/x-www-form-urlencoded'); request.addHeader('Content-Type', 'application/x-www-form-urlencoded');
// Set the post data // Set the post data
request.setSend(data); request.setSend(data);
// Make the request // Make the request
request.start(HTTPMethods.POST); request.start(HTTPMethods.POST);
// Return the AJAX object
return request;
} }
// Convert a href attr to an object
// Convert href attribute to an object
function prepareAjaxLink(linkId, callback, attrs) { function prepareAjaxLink(linkId, callback, attrs) {
// Get the elements if (attrs === void 0) { attrs = null; }
var link = typeof linkId === 'object' ? linkId : document.getElementById(linkId); // Get element
var link = (typeof linkId).toLowerCase() === 'object' ? linkId : document.getElementById(linkId);
// Catch null // Catch null
if(link == null) { if (link === null) {
return; return;
} }
// Get the raw HREF value
// Get the href value var href = link.getAttribute('href');
var hrefRaw = link.attributes.href.value; // Get the action
var action = href.split('?')[0];
// Get the action path
var action = hrefRaw.split('?')[0];
// Split the request variables // Split the request variables
var variablesNotSplit = hrefRaw.split('?')[1].split('&'); var varEarly = href.split('?')[1].split('&');
// Create storage thing
// Create variables object var variables = new Object();
var variables = {}; // Split them
for (var k in varEarly) {
// Split the name and values of the variables // Split
for(var key in variablesNotSplit) { var newVar = varEarly[k].split('=');
// Split name and value // Push
var newVar = variablesNotSplit[key].split('=');
// Push it into the object
variables[newVar[0]] = newVar[1]; variables[newVar[0]] = newVar[1];
} }
// Add ajax=true // Add ajax=true
variables['ajax'] = true; variables['ajax'] = true;
// Update link attributes // Update link attributes
link.setAttribute('href', 'javascript:void(0);'); link.setAttribute('href', 'javascript:void(0);');
link.setAttribute('onclick', callback +'(\''+ action +'\', JSON.parse(\''+ JSON.stringify(variables) +'\')'+ (typeof attrs != 'undefined' ? attrs : '') +');'); link.setAttribute('onclick', callback + '(\'' + action + '\', JSON.parse(\'' + JSON.stringify(variables) + '\')' + (typeof attrs != 'undefined' ? attrs : '') + ');');
} }
// Prepare a form for an AJAX request
function prepareAjaxForm(formId, message, resetCaptchaOnFailure) { function prepareAjaxForm(formId, message, resetCaptcha) {
if (resetCaptcha === void 0) { resetCaptcha = false; }
// Get the form // Get the form
var form = document.getElementById(formId); var form = document.getElementById(formId);
// Create hidden ajax input
// Create the AJAX form input var hide = document.createElement('input');
var createHidden = document.createElement('input');
// Set the attributes // Set the attributes
createHidden.setAttribute('name', 'ajax'); hide.name = 'ajax';
createHidden.setAttribute('value', 'true'); hide.value = 'true';
createHidden.setAttribute('type', 'hidden'); hide.type = 'hidden';
form.appendChild(createHidden); form.appendChild(hide);
// Update form // Update form
form.setAttribute('onsubmit', 'submitPost(\''+ form.action +'\', formToObject(\''+ formId +'\'), true, \''+ (message ? message : 'Please wait...') +'\', '+ (resetCaptchaOnFailure ? 'true' : 'false') +');'); form.setAttribute('onsubmit', 'submitPost(\'' + form.getAttribute('action') + '\', formToObject(\'' + formId + '\'), true, \'' + (message ? message : 'Please wait...') + '\', ' + (resetCaptcha ? 'true' : 'false') + ');');
form.setAttribute('action', 'javascript:void(0);'); form.setAttribute('action', 'javascript:void(0);');
} }
// Convert form to an object // Convert form to an object
function formToObject(formId) { function formToObject(formId) {
// Get form data // Get the form
var form = document.getElementById(formId); var form = document.getElementById(formId);
// Make an object for the request parts // Make an object for the request parts
var requestParts = {}; var requestParts = new Object();
// Get all the children with a name attr
// Get all children with a name attribute
var children = form.querySelectorAll('[name]'); var children = form.querySelectorAll('[name]');
// Sort the children and make them ready for submission
// Sort children and make them ready for submission for (var i in children) {
for(var i in children) { if ((typeof children[i]).toLowerCase() === 'object') {
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); requestParts[children[i].name] = ((typeof children[i].type !== "undefined" && children[i].type.toLowerCase() == "checkbox") ? (children[i].checked ? 1 : 0) : children[i].value);
} }
} }
// Return the request parts
// Return the object
return requestParts; return requestParts;
} }
// Quickly building a form
// Quickly building a form for god knows what reason
function generateForm(formId, formAttr, formData, appendTo) { function generateForm(formId, formAttr, formData, appendTo) {
// Create form elements and assign ID if (appendTo === void 0) { appendTo = null; }
var i; // Create form element
var form = document.createElement('form'); var form = document.createElement('form');
form.setAttribute('id', formId); form.id = formId;
// Set additional attrs
// Set additional attributes for (var c in formAttr) {
if(formAttr !== null) { form.setAttribute(c, formAttr[c]);
for(i in formAttr) {
form.setAttribute(i, formAttr[i]);
}
} }
// Set data
// Generate input elements for (var a in formData) {
for(i in formData) { var b = document.createElement('input');
var disposableVar = document.createElement('input'); b.type = 'hidden';
disposableVar.setAttribute('type', 'hidden'); b.name = a;
disposableVar.setAttribute('name', i); b.value = formData[a];
disposableVar.setAttribute('value', formData[i]); form.appendChild(b);
form.appendChild(disposableVar);
} }
// Append to something if requested
// Append to another element if requested if (appendTo !== null) {
if(appendTo !== null) {
document.getElementById(appendTo).appendChild(form); document.getElementById(appendTo).appendChild(form);
} }
// Return the completed form
return form; return form;
} }
// Submitting a post using AJAX
// Submitting a form using an AJAX POST request function submitPost(action, requestParts, busyView, msg, resetCaptcha) {
function submitPost(action, requestParts, busyView, msg, resetCaptchaOnFailure) {
// If requested display the busy thing // If requested display the busy thing
if(busyView) { if (busyView) {
ajaxBusyView(true, msg, 'busy'); ajaxBusyView(true, msg, 'busy');
} }
// Submit the AJAX
// Submit the AJAX request var request = ajaxPost(action, requestParts, function () {
var request = ajaxPost(action, requestParts, function() { submitPostHandler(request.response(), busyView, resetCaptcha);
submitPostHandler(this, busyView, resetCaptchaOnFailure);
}); });
} }
// Handling a submitted form using AJAX
// Submitting a form using an AJAX POST request function submitPostHandler(data, busyView, resetCaptcha) {
function submitPostHandler(result, busyView, resetCaptchaOnFailure) { // Split the result
var result = data.split('|');
// Split result // If using the bust view thing update the text displayed to the return of the request
result = result.split('|'); if (busyView) {
// 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')); ajaxBusyView(true, result[0], (result[1] == '1' ? 'ok' : 'fail'));
} }
// Reset captcha
// If request reset the recaptcha on failure if (resetCaptcha && result[1] != '1' && sakuraVars.recaptchaEnabled != '0') {
if(resetCaptchaOnFailure && result[1] != '1' && sakuraVars.recaptchaEnabled != '0') {
grecaptcha.reset(); grecaptcha.reset();
} }
setTimeout(function () {
setTimeout(function(){ if (busyView) {
if(busyView) {
ajaxBusyView(false); ajaxBusyView(false);
} }
if (result[1] == '1') {
if(result[1] == '1') { window.location.assign(result[2]);
window.location = result[2];
} }
}, 2000); }, 2000);
} }
// Check if a password is within the minimum entropy value
// Check if password is within the minimum entropy value
function checkPwdEntropy(pwd) { function checkPwdEntropy(pwd) {
return (Sakura.pwdEntropy(pwd) >= sakuraVars.minPwdEntropy); return (Sakura.entropy(pwd) >= sakuraVars.minPwdEntropy);
} }
// Check registration variables // Check registration variables
function registerVarCheck(id, mode, option) { function registerVarCheck(id, mode, option) {
if (option === void 0) { option = null; }
// Get the element we're working with // Get the element we're working with
var input = document.getElementById(id); var input = document.getElementById(id);
var check = null; var check = null;
// Use the proper mode // Use the proper mode
switch(mode) { switch (mode) {
case 'confirmpw': case 'confirmpw':
option = document.getElementById(option); option = document.getElementById(option);
check = input.value === option.value; check = input.getAttribute('value') === option.value;
break; break;
case 'password': case 'password':
check = checkPwdEntropy(input.value); check = checkPwdEntropy(input.getAttribute('value'));
break; break;
case 'email': case 'email':
check = Sakura.validateEmail(input.value); check = Sakura.validateEmail(input.getAttribute('value'));
break; break;
case 'username': case 'username':
default: default:
check = Sakura.stringLength(input.value, sakuraVars.minUserLen, sakuraVars.maxUserLen); check = Sakura.stringLength(input.getAttribute('value'), sakuraVars.minUserLen, sakuraVars.maxUserLen);
break; break;
} }
if (input.className.indexOf(check ? 'green' : 'red') < 0) {
if(input.className.indexOf(check ? 'green' : 'red') < 0) {
input.className = input.className + ' ' + (check ? 'green' : 'red'); input.className = input.className + ' ' + (check ? 'green' : 'red');
} }
if (input.className.indexOf(check ? 'red' : 'green') > 0) {
if(input.className.indexOf(check ? 'red' : 'green') > 0) {
input.className = input.className.replace(check ? 'red' : 'green', ''); input.className = input.className.replace(check ? 'red' : 'green', '');
} }
} }
// Initialising the element parallax functionality // Initialising the element parallax functionality
function initialiseParallax(id) { function initialiseParallax(id) {
// Assign the element to a variable // Assign the element to a variable
var parallax = document.getElementById(id); var parallax = document.getElementById(id);
// Set proper position values // Set proper position values
parallax.style.top = '-2.5px'; parallax.style.top = '-2.5px';
parallax.style.bottom = '-2.5px'; parallax.style.bottom = '-2.5px';
parallax.style.left = '-2.5px'; parallax.style.left = '-2.5px';
parallax.style.right = '-2.5px'; parallax.style.right = '-2.5px';
// Add the event listener to the body element // Add the event listener to the body element
document.addEventListener("mousemove", function(e) { document.addEventListener("mousemove", function (e) {
// Alter the position of the parallaxed element // Alter the position of the parallaxed element
parallax.style.top = convertParallaxPositionValue(e.clientY, true, false) + 'px'; parallax.style.top = convertParallaxPositionValue(e.clientY, true, false) + 'px';
parallax.style.bottom = convertParallaxPositionValue(e.clientY, true, true) + 'px'; parallax.style.bottom = convertParallaxPositionValue(e.clientY, true, true) + 'px';
parallax.style.left = convertParallaxPositionValue(e.clientX, false, false) + 'px'; parallax.style.left = convertParallaxPositionValue(e.clientX, false, false) + 'px';
parallax.style.right = convertParallaxPositionValue(e.clientX, false, true) + 'px'; parallax.style.right = convertParallaxPositionValue(e.clientX, false, true) + 'px';
}); });
} }
// Converting the position value of the mouseover to a pixel value // Converting the position value of the mouseover to a pixel value
function convertParallaxPositionValue(pos, dir, neg) { function convertParallaxPositionValue(pos, dir, neg) {
// Get the body element // Get the body element
var body = document.getElementsByTagName('body')[0]; var body = document.getElementsByTagName('body')[0];
// Get percentage of current position // Get percentage of current position
var position = (pos / (dir ? body.clientHeight : body.clientWidth)) * 100; var position = (pos / (dir ? body.clientHeight : body.clientWidth)) * 100;
// If someone decided to fuck with the inputs reset it to 0% // If someone decided to fuck with the inputs reset it to 0%
if(position < 0 || position > 100) { if (position < 0 || position > 100) {
position = 0; position = 0;
} }
// Do the first maths // Do the first maths
position = (position / (dir ? 25 : 20)) - 2.5; position = (position / (dir ? 25 : 20)) - 2.5;
// If the negative flag is set inverse the number // If the negative flag is set inverse the number
if(neg) { if (neg) {
position = -position; position = -position;
} }
// Subtract another 2.5 to make the element not go all over the place // Subtract another 2.5 to make the element not go all over the place
position = position - 2.5; position = position - 2.5;
// Return the proper position value // Return the proper position value
return position; return position;
} }
// """"""""Smooth"""""""" scrolling
// Smooth scrolling
function scrollToTop() { function scrollToTop() {
// Get the current position // Get the current position
var windowY = window.pageYOffset - 100; var windowY = window.pageYOffset - 100;
// Move up // Move up
window.scrollTo(0, windowY); window.scrollTo(0, windowY);
// Keep executing this function till we're at the top // Keep executing this function till we're at the top
if(windowY + 1 > 0) { if (windowY + 1 > 0) {
setTimeout(function(){scrollToTop();}, 10); setTimeout(function () { scrollToTop(); }, 10);
} }
} }
// Replace some special tags
function replaceTag(tag) { function replaceTag(tag) {
return {'&': '&amp;', '<': '&lt;', '>': '&gt;'}[tag] || tag; return { '&': '&amp;', '<': '&lt;', '>': '&gt;' }[tag] || tag;
} }
// ^
function safeTagsReplace(str) { function safeTagsReplace(str) {
return str.replace(/[&<>]/g, replaceTag); return str.replace(/[&<>]/g, replaceTag);
} }
// Open a comment reply field
function commentReply(id, session, category, action, avatar) { function commentReply(id, session, category, action, avatar) {
// Find subject post // Find subject post
var replyingTo = document.getElementById('comment-' + id); var replyingTo = document.getElementById('comment-' + id);
// Check if it actually exists // Check if it actually exists
if(typeof replyingTo === 'undefined') { if ((typeof replyingTo).toLowerCase() === 'undefined') {
return false; return;
} }
// Attempt to get previously created box // Attempt to get previously created box
var replyBox = document.getElementById('comment-reply-container-' + id); var replyBox = document.getElementById('comment-reply-container-' + id);
// Remove it if it already exists // Remove it if it already exists
if(replyBox) { if (replyBox) {
Sakura.removeById('comment-reply-container-' + id); Sakura.removeById('comment-reply-container-' + id);
return false; return;
} }
// Container // Container
var replyContainer = document.createElement('li'); var replyContainer = document.createElement('li');
replyContainer.id = 'comment-reply-container-' + id; replyContainer.id = 'comment-reply-container-' + id;
// Form // Form
var replyForm = document.createElement('form'); var replyForm = document.createElement('form');
replyForm.id = 'comment-reply-' + id; replyForm.id = 'comment-reply-' + id;
replyForm.action = action; replyForm.action = action;
replyForm.method = 'post'; replyForm.method = 'post';
// Session // Session
var replyInput = document.createElement('input'); var replyInput = document.createElement('input');
replyInput.type = 'hidden'; replyInput.type = 'hidden';
replyInput.name = 'session'; replyInput.name = 'session';
replyInput.value = session; replyInput.value = session;
replyForm.appendChild(replyInput); replyForm.appendChild(replyInput);
// Category // Category
var replyInput = document.createElement('input'); var replyInput = document.createElement('input');
replyInput.type = 'hidden'; replyInput.type = 'hidden';
replyInput.name = 'category'; replyInput.name = 'category';
replyInput.value = category; replyInput.value = category;
replyForm.appendChild(replyInput); replyForm.appendChild(replyInput);
// Reply ID // Reply ID
var replyInput = document.createElement('input'); var replyInput = document.createElement('input');
replyInput.type = 'hidden'; replyInput.type = 'hidden';
replyInput.name = 'replyto'; replyInput.name = 'replyto';
replyInput.value = id; replyInput.value = id.toString();
replyForm.appendChild(replyInput); replyForm.appendChild(replyInput);
// Mode // Mode
var replyInput = document.createElement('input'); var replyInput = document.createElement('input');
replyInput.type = 'hidden'; replyInput.type = 'hidden';
replyInput.name = 'mode'; replyInput.name = 'mode';
replyInput.value = 'comment'; replyInput.value = 'comment';
replyForm.appendChild(replyInput); replyForm.appendChild(replyInput);
// Comment container // Comment container
var replyDiv = document.createElement('div'); var replyDiv = document.createElement('div');
replyDiv.className = 'comment'; replyDiv.className = 'comment';
// Avatar // Avatar
var replyAvatar = document.createElement('div'); var replyAvatar = document.createElement('div');
replyAvatar.className = 'comment-avatar'; replyAvatar.className = 'comment-avatar';
replyAvatar.style = 'background-image: url(' + avatar + ')'; replyAvatar.style.backgroundImage = 'url(' + avatar + ')';
replyDiv.appendChild(replyAvatar); replyDiv.appendChild(replyAvatar);
// Pointer // Pointer
var replyPoint = document.createElement('div'); var replyPoint = document.createElement('div');
replyPoint.className = 'comment-pointer'; replyPoint.className = 'comment-pointer';
replyDiv.appendChild(replyPoint); replyDiv.appendChild(replyPoint);
// Textarea // Textarea
var replyText = document.createElement('textarea'); var replyText = document.createElement('textarea');
replyText.className = 'comment-content'; replyText.className = 'comment-content';
replyText.name = 'comment'; replyText.name = 'comment';
replyDiv.appendChild(replyText); replyDiv.appendChild(replyText);
// Submit // Submit
var replySubmit = document.createElement('input'); var replySubmit = document.createElement('input');
replySubmit.className = 'comment-submit'; replySubmit.className = 'comment-submit';
@ -620,26 +505,22 @@ function commentReply(id, session, category, action, avatar) {
replySubmit.name = 'submit'; replySubmit.name = 'submit';
replySubmit.value = "\uf1d8"; replySubmit.value = "\uf1d8";
replyDiv.appendChild(replySubmit); replyDiv.appendChild(replySubmit);
// Append to form // Append to form
replyForm.appendChild(replyDiv); replyForm.appendChild(replyDiv);
// Append form to container // Append form to container
replyContainer.appendChild(replyForm); replyContainer.appendChild(replyForm);
// Insert the HTML // Insert the HTML
if(replyingTo.children[1].children.length > 0) { if (replyingTo.children[1].children.length > 0) {
replyingTo.children[1].insertBefore(replyContainer, replyingTo.children[1].firstChild); replyingTo.children[1].insertBefore(replyContainer, replyingTo.children[1].firstChild);
} else { }
else {
replyingTo.children[1].appendChild(replyContainer); replyingTo.children[1].appendChild(replyContainer);
} }
// Prepare AJAX submission // Prepare AJAX submission
prepareAjaxForm(replyForm.id, 'Replying...'); prepareAjaxForm(replyForm.id, 'Replying...');
} }
// Inserting text into text box // Inserting text into text box
// Borrowed from http://stackoverflow.com/questions/1064089/inserting-a-text-where-cursor-is-using-javascript-jquery // Borrowed from http://stackoverflow.com/questions/1064089/inserting-a-text-where-cursor-is-using-javascript-jquery (therefore not in Typescript format, fix this later)
function insertText(areaId, text) { function insertText(areaId, text) {
var txtarea = document.getElementById(areaId); var txtarea = document.getElementById(areaId);
var scrollPos = txtarea.scrollTop; var scrollPos = txtarea.scrollTop;
@ -652,8 +533,8 @@ function insertText(areaId, text) {
range.moveStart('character', -txtarea.value.length); range.moveStart('character', -txtarea.value.length);
strPos = range.text.length; strPos = range.text.length;
} }
else if (br == "ff") strPos = txtarea.selectionStart; else if (br == "ff")
strPos = txtarea.selectionStart;
var front = (txtarea.value).substring(0, strPos); var front = (txtarea.value).substring(0, strPos);
var back = (txtarea.value).substring(strPos, txtarea.value.length); var back = (txtarea.value).substring(strPos, txtarea.value.length);
txtarea.value = front + text + back; txtarea.value = front + text + back;
@ -673,19 +554,19 @@ function insertText(areaId, text) {
} }
txtarea.scrollTop = scrollPos; txtarea.scrollTop = scrollPos;
} }
// Inserting a bbcode // Inserting a bbcode
function insertBBcode(textarea, tag, arg) { function insertBBcode(textarea, tag, arg) {
if (arg === void 0) { arg = false; }
var element = document.getElementById(textarea); var element = document.getElementById(textarea);
var before = "[" + tag + (arg ? "=" : "") + "]"; var before = "[" + tag + (arg ? "=" : "") + "]";
var after = "[/" + tag + "]"; var after = "[/" + tag + "]";
if (document.selection) { if (document.selection) {
element.focus(); element.focus();
var sel = document.selection.createRange(); var sel = document.selection.createRange();
sel.text = before + sel.text + after; sel.text = before + sel.text + after;
element.focus(); element.focus();
} else if (element.selectionStart || element.selectionStart === 0) { }
else if (element.selectionStart || element.selectionStart === 0) {
var startPos = element.selectionStart; var startPos = element.selectionStart;
var endPos = element.selectionEnd; var endPos = element.selectionEnd;
var scrollTop = element.scrollTop; var scrollTop = element.scrollTop;
@ -694,21 +575,14 @@ function insertBBcode(textarea, tag, arg) {
element.selectionStart = startPos + before.length; element.selectionStart = startPos + before.length;
element.selectionEnd = endPos + before.length; element.selectionEnd = endPos + before.length;
element.scrollTop = scrollTop; element.scrollTop = scrollTop;
} else { }
else {
element.value += before + after; element.value += before + after;
element.focus(); element.focus();
} }
} }
// Formatting money // Formatting money
Number.prototype.formatMoney = function(u, c, k) { Number.prototype.formatMoney = function (u, c, k) {
var f = this, 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;
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) : ""); 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

@ -1,591 +0,0 @@
/*
* Sakura Yuuno
*/
// Spawns a notification
function notifyUI(content) {
// Grab the container and create an ID
var cont = document.getElementById('notifications');
var id = 'sakura-notification-' + Date.now();
// Create the elements
var alert = document.createElement('div');
var aIcon = document.createElement('div');
var aCont = document.createElement('div');
var aTitle = document.createElement('div');
var aText = document.createElement('div');
var aClose = document.createElement('div');
var aCIcon = document.createElement('div');
var aClear = document.createElement('div');
var aIconCont;
// Add attributes to the main element
alert.className = 'notification-enter';
alert.id = id;
// Add the icon
if ((typeof content.img).toLowerCase() === 'undefined' && content.img == null && !(content.img.length > 1)) {
aIconCont = document.createElement('div');
aIconCont.className = 'font-icon fa fa-info fa-4x';
}
else if (content.img.substr(0, 5) == 'FONT:') {
aIconCont = document.createElement('div');
aIconCont.className = 'font-icon fa ' + content.img.replace('FONT:', '') + ' fa-4x';
}
else {
aIconCont = document.createElement('img');
aIconCont.alt = id;
aIconCont.img = content.img;
}
aIcon.appendChild(aIconCont);
aIcon.className = 'notification-icon';
alert.appendChild(aIcon);
// Add the content
aCont.className = 'notification-content';
aTitle.className = 'notification-title';
aText.className = 'notifcation-text';
aTitle.textContent = content.title;
aText.textContent = content.text;
// Check if a link exists and add if it does
if ((typeof content.link).toLowerCase() !== 'undefined' && content.link !== null && content.link.length > 1) {
alert.setAttribute('sakurahref', content.link);
aCont.setAttribute('onclick', content.link.substr(0, 11) == 'javascript:' ? content.link.substring(11) : 'notifyOpen(this.parentNode.id);');
}
// Append stuff
aCont.appendChild(aTitle);
aCont.appendChild(aText);
alert.appendChild(aCont);
// Add the close button
aClose.className = 'notification-close';
aClose.setAttribute('onclick', 'notifyClose(this.parentNode.id);');
aClose.appendChild(aCIcon);
alert.appendChild(aClose);
// Append the notification to the document
cont.appendChild(alert);
// Play sound if request
if (content.sound) {
// Create the elements
var sound = document.createElement('audio');
var mp3 = document.createElement('source');
var ogg = document.createElement('source');
// Assign attribs
mp3.type = 'audio/mp3';
ogg.type = 'audio/ogg';
mp3.src = sakuraVars.content_path + '/sounds/notify.mp3';
ogg.src = sakuraVars.content_path + '/sounds/notify.ogg';
// Append
sound.appendChild(mp3);
sound.appendChild(ogg);
// And play
sound.play();
}
// If keepalive is 0 keep the notification open forever
if (content.timeout > 0) {
// Set a timeout and close after an amount
setTimeout(function () {
notifyClose(id);
}, content.timeout);
}
}
// Closing a notification
function notifyClose(id) {
// Get the element
var e = document.getElementById(id);
// Add the animation
e.className = 'notification-exit';
// Remove after 410 ms
setTimeout(function () {
Sakura.removeById(id);
}, 410);
}
// Opening an alerted link
function notifyOpen(id) {
var sakuraHref = document.getElementById(id).getAttribute('sakurahref');
if ((typeof sakuraHref).toLowerCase() !== 'undefined') {
location = new Location();
location.assign(sakuraHref);
window.location = location;
}
}
// Request notifications
function notifyRequest(session) {
// Check if the document isn't hidden
if (document.hidden) {
return;
}
// Create AJAX object
var get = new AJAX();
get.setUrl('/settings.php?request-notifications=true&time=' + Sakura.epoch() + '&session=' + session);
// Add callbacks
get.addCallback(200, function () {
// Assign the parsed JSON
var data = JSON.parse(get.response());
// Check if nothing went wrong
if ((typeof data).toLowerCase() === 'undefined') {
// Inform the user
throw "No or invalid data was returned";
// Stop
return;
}
// Create an object for every notification
for (var id in data) {
notifyUI(data[id]);
}
});
get.start(HTTPMethods.GET);
}
// Show the full page busy window
function ajaxBusyView(show, message, type) {
if (message === void 0) { message = null; }
if (type === void 0) { type = null; }
// Get elements
var cont = document.getElementById('ajaxBusy');
var stat = document.getElementById('ajaxStatus');
var anim = document.getElementById('ajaxAnimate');
var body = document.getElementById('contentwrapper');
var icon = 'fa fa-4x ';
// Select the proper icon
switch (type) {
case 'ok':
icon += 'fa-check';
break;
case 'fail':
icon += 'fa-remove';
break;
case 'busy':
default:
icon += 'fa-refresh fa-spin';
break;
}
// If request to show the window, build it
if (show) {
if ((typeof cont).toLowerCase() === 'undefined' || cont === null) {
// Container
var cCont = document.createElement('div');
cCont.className = 'ajax-busy';
cCont.id = 'ajaxBusy';
// Inner
var cInner = document.createElement('div');
cInner.className = 'ajax-inner';
cCont.appendChild(cInner);
// Desc
var cMsg = document.createElement('h2');
cMsg.id = 'ajaxStatus';
cInner.appendChild(cMsg);
// Icon
var cIco = document.createElement('div');
cIco.id = 'ajaxAnimate';
cInner.appendChild(cIco);
// Append to document
body.appendChild(cCont);
// Reassign
cont = document.getElementById('ajaxBusy');
stat = document.getElementById('ajaxStatus');
anim = document.getElementById('ajaxAnimate');
}
// Update the icon
anim.className = icon;
// Update the message
stat.textContent = (message === null ? '' : message);
}
else {
if (cont !== null) {
var out = setInterval(function () {
if (cont.style.opacity === null || cont.style.opacity === "") {
cont.style.opacity = "1";
}
// If the value isn't 0 yet subtract by .1
if (parseInt(cont.style.opacity) > 0) {
cont.style.opacity = (parseInt(cont.style.opacity) - 0.1).toString();
}
else {
Sakura.removeById('ajaxBusy');
clearInterval(out);
}
}, 10);
}
}
}
// Making a post request using AJAX
function ajaxPost(url, data, callback) {
// Create AJAX
var request = new AJAX();
// Set url
request.setUrl(url);
// Add callbacks
request.addCallback(200, function () {
callback.call(request.response());
});
request.addCallback(0, function () {
ajaxBusyView(false);
throw "POST Request failed";
});
// Add header
request.addHeader('Content-Type', 'application/x-www-form-urlencoded');
// Set the post data
request.setSend(data);
// Make the request
request.start(HTTPMethods.POST);
}
// Convert a href attr to an object
function prepareAjaxLink(linkId, callback, attrs) {
if (attrs === void 0) { attrs = null; }
// Get element
var link = (typeof linkId).toLowerCase() === 'object' ? linkId : document.getElementById(linkId);
// Catch null
if (link === null) {
return;
}
// Get the raw HREF value
var href = link.getAttribute('href');
// Get the action
var action = href.split('?')[0];
// Split the request variables
var varEarly = href.split('?')[1].split('&');
// Create storage thing
var variables = new Object();
// Split them
for (var k in varEarly) {
// Split
var newVar = varEarly[k].split('=');
// Push
variables[newVar[0]] = newVar[1];
}
// Add ajax=true
variables['ajax'] = true;
// Update link attributes
link.setAttribute('href', 'javascript:void(0);');
link.setAttribute('onclick', callback + '(\'' + action + '\', JSON.parse(\'' + JSON.stringify(variables) + '\')' + (typeof attrs != 'undefined' ? attrs : '') + ');');
}
// Prepare a form for an AJAX request
function prepareAjaxForm(formId, message, resetCaptcha) {
if (resetCaptcha === void 0) { resetCaptcha = false; }
// Get the form
var form = document.getElementById(formId);
// Create hidden ajax input
var hide = document.createElement('input');
// Set the attributes
hide.name = 'ajax';
hide.value = 'true';
hide.type = 'hidden';
form.appendChild(hide);
// Update form
form.setAttribute('onsubmit', 'submitPost(\'' + form.getAttribute('action') + '\', formToObject(\'' + formId + '\'), true, \'' + (message ? message : 'Please wait...') + '\', ' + (resetCaptcha ? 'true' : 'false') + ');');
form.setAttribute('action', 'javascript:void(0);');
}
// Convert form to an object
function formToObject(formId) {
// Get the form
var form = document.getElementById(formId);
// Make an object for the request parts
var requestParts = new Object();
// Get all the children with a name attr
var children = form.querySelectorAll('[name]');
// Sort the children and make them ready for submission
for (var i in children) {
if ((typeof children[i]).toLowerCase() === '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 request parts
return requestParts;
}
// Quickly building a form
function generateForm(formId, formAttr, formData, appendTo) {
if (appendTo === void 0) { appendTo = null; }
// Create form element
var form = document.createElement('form');
form.id = formId;
// Set additional attrs
for (var c in formAttr) {
form.setAttribute(c, formAttr[c]);
}
// Set data
for (var a in formData) {
var b = document.createElement('input');
b.type = 'hidden';
b.name = a;
b.value = formData[a];
form.appendChild(b);
}
// Append to something if requested
if (appendTo !== null) {
document.getElementById(appendTo).appendChild(form);
}
return form;
}
// Submitting a post using AJAX
function submitPost(action, requestParts, busyView, msg, resetCaptcha) {
var _this = this;
// If requested display the busy thing
if (busyView) {
ajaxBusyView(true, msg, 'busy');
}
// Submit the AJAX
var request = ajaxPost(action, requestParts, function () {
submitPostHandler(_this, busyView, resetCaptcha);
});
}
// Handling a submitted form using AJAX
function submitPostHandler(result, busyView, resetCaptcha) {
// Split the result
var data = result.split('|');
// If using the bust view thing update the text displayed to the return of the request
if (busyView) {
ajaxBusyView(true, result[0], (result[1] == '1' ? 'ok' : 'fail'));
}
// Reset captcha
if (resetCaptcha && result[1] != '1' && sakuraVars.recaptchaEnabled != '0') {
grecaptcha.reset();
}
setTimeout(function () {
if (busyView) {
ajaxBusyView(false);
}
if (result[1] == '1') {
location = new Location();
location.assign(result[2]);
window.location = location;
}
}, 2000);
}
// Check if a password is within the minimum entropy value
function checkPwdEntropy(pwd) {
return (Sakura.entropy(pwd) >= sakuraVars.minPwdEntropy);
}
// Check registration variables
function registerVarCheck(id, mode, option) {
if (option === void 0) { option = null; }
// 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.getAttribute('value') === option.value;
break;
case 'password':
check = checkPwdEntropy(input.getAttribute('value'));
break;
case 'email':
check = Sakura.validateEmail(input.getAttribute('value'));
break;
case 'username':
default:
check = Sakura.stringLength(input.getAttribute('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);
// Set proper position values
parallax.style.top = '-2.5px';
parallax.style.bottom = '-2.5px';
parallax.style.left = '-2.5px';
parallax.style.right = '-2.5px';
// Add the event listener to the body element
document.addEventListener("mousemove", function (e) {
// Alter the position of the parallaxed element
parallax.style.top = convertParallaxPositionValue(e.clientY, true, false) + 'px';
parallax.style.bottom = convertParallaxPositionValue(e.clientY, true, true) + 'px';
parallax.style.left = convertParallaxPositionValue(e.clientX, false, false) + 'px';
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];
// Get percentage of current position
var position = (pos / (dir ? body.clientHeight : body.clientWidth)) * 100;
// If someone decided to fuck with the inputs reset it to 0%
if (position < 0 || position > 100) {
position = 0;
}
// Do the first maths
position = (position / (dir ? 25 : 20)) - 2.5;
// 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
position = position - 2.5;
// Return the proper position value
return position;
}
// """"""""Smooth"""""""" scrolling
function scrollToTop() {
// Get the current position
var windowY = window.pageYOffset - 100;
// Move up
window.scrollTo(0, windowY);
// Keep executing this function till we're at the top
if (windowY + 1 > 0) {
setTimeout(function () { scrollToTop(); }, 10);
}
}
// Replace some special tags
function replaceTag(tag) {
return { '&': '&amp;', '<': '&lt;', '>': '&gt;' }[tag] || tag;
}
// ^
function safeTagsReplace(str) {
return str.replace(/[&<>]/g, replaceTag);
}
// Open a comment reply field
function commentReply(id, session, category, action, avatar) {
// Find subject post
var replyingTo = document.getElementById('comment-' + id);
// Check if it actually exists
if ((typeof replyingTo).toLowerCase() === 'undefined') {
return;
}
// Attempt to get previously created box
var replyBox = document.getElementById('comment-reply-container-' + id);
// Remove it if it already exists
if (replyBox) {
Sakura.removeById('comment-reply-container-' + id);
return;
}
// Container
var replyContainer = document.createElement('li');
replyContainer.id = 'comment-reply-container-' + id;
// Form
var replyForm = document.createElement('form');
replyForm.id = 'comment-reply-' + id;
replyForm.action = action;
replyForm.method = 'post';
// Session
var replyInput = document.createElement('input');
replyInput.type = 'hidden';
replyInput.name = 'session';
replyInput.value = session;
replyForm.appendChild(replyInput);
// Category
var replyInput = document.createElement('input');
replyInput.type = 'hidden';
replyInput.name = 'category';
replyInput.value = category;
replyForm.appendChild(replyInput);
// Reply ID
var replyInput = document.createElement('input');
replyInput.type = 'hidden';
replyInput.name = 'replyto';
replyInput.value = id.toString();
replyForm.appendChild(replyInput);
// Mode
var replyInput = document.createElement('input');
replyInput.type = 'hidden';
replyInput.name = 'mode';
replyInput.value = 'comment';
replyForm.appendChild(replyInput);
// Comment container
var replyDiv = document.createElement('div');
replyDiv.className = 'comment';
// Avatar
var replyAvatar = document.createElement('div');
replyAvatar.className = 'comment-avatar';
replyAvatar.style.backgroundImage = 'url(' + avatar + ')';
replyDiv.appendChild(replyAvatar);
// Pointer
var replyPoint = document.createElement('div');
replyPoint.className = 'comment-pointer';
replyDiv.appendChild(replyPoint);
// Textarea
var replyText = document.createElement('textarea');
replyText.className = 'comment-content';
replyText.name = 'comment';
replyDiv.appendChild(replyText);
// Submit
var replySubmit = document.createElement('input');
replySubmit.className = 'comment-submit';
replySubmit.type = 'submit';
replySubmit.name = 'submit';
replySubmit.value = "\uf1d8";
replyDiv.appendChild(replySubmit);
// Append to form
replyForm.appendChild(replyDiv);
// Append form to container
replyContainer.appendChild(replyForm);
// Insert the HTML
if (replyingTo.children[1].children.length > 0) {
replyingTo.children[1].insertBefore(replyContainer, replyingTo.children[1].firstChild);
}
else {
replyingTo.children[1].appendChild(replyContainer);
}
// Prepare AJAX submission
prepareAjaxForm(replyForm.id, 'Replying...');
}
// Inserting text into text box
// Borrowed from http://stackoverflow.com/questions/1064089/inserting-a-text-where-cursor-is-using-javascript-jquery (therefore not in Typescript format, fix this later)
function insertText(areaId, text) {
var txtarea = document.getElementById(areaId);
var scrollPos = txtarea.scrollTop;
var strPos = 0;
var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ?
"ff" : (document.selection ? "ie" : false));
if (br == "ie") {
txtarea.focus();
var range = document.selection.createRange();
range.moveStart('character', -txtarea.value.length);
strPos = range.text.length;
}
else if (br == "ff")
strPos = txtarea.selectionStart;
var front = (txtarea.value).substring(0, strPos);
var back = (txtarea.value).substring(strPos, txtarea.value.length);
txtarea.value = front + text + back;
strPos = strPos + text.length;
if (br == "ie") {
txtarea.focus();
var range = document.selection.createRange();
range.moveStart('character', -txtarea.value.length);
range.moveStart('character', strPos);
range.moveEnd('character', 0);
range.select();
}
else if (br == "ff") {
txtarea.selectionStart = strPos;
txtarea.selectionEnd = strPos;
txtarea.focus();
}
txtarea.scrollTop = scrollPos;
}
// Inserting a bbcode
function insertBBcode(textarea, tag, arg) {
if (arg === void 0) { arg = false; }
var element = document.getElementById(textarea);
var before = "[" + tag + (arg ? "=" : "") + "]";
var after = "[/" + tag + "]";
if (document.selection) {
element.focus();
var sel = document.selection.createRange();
sel.text = before + sel.text + after;
element.focus();
}
else if (element.selectionStart || element.selectionStart === 0) {
var startPos = element.selectionStart;
var endPos = element.selectionEnd;
var scrollTop = element.scrollTop;
element.value = element.value.substring(0, startPos) + before + element.value.substring(startPos, endPos) + after + element.value.substring(endPos, element.value.length);
element.focus();
element.selectionStart = startPos + before.length;
element.selectionEnd = endPos + before.length;
element.scrollTop = scrollTop;
}
else {
element.value += before + after;
element.focus();
}
}
// Formatting money
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

@ -127,9 +127,7 @@ function notifyOpen(id: string): void {
var sakuraHref: string = document.getElementById(id).getAttribute('sakurahref'); var sakuraHref: string = document.getElementById(id).getAttribute('sakurahref');
if ((typeof sakuraHref).toLowerCase() !== 'undefined') { if ((typeof sakuraHref).toLowerCase() !== 'undefined') {
location = new Location(); window.location.assign(sakuraHref);
location.assign(sakuraHref);
window.location = location;
} }
} }
@ -247,7 +245,7 @@ function ajaxBusyView(show: boolean, message: string = null, type: string = null
} }
// Making a post request using AJAX // Making a post request using AJAX
function ajaxPost(url: string, data: Object, callback: Function): void { function ajaxPost(url: string, data: Object, callback: Function): AJAX {
// Create AJAX // Create AJAX
var request = new AJAX(); var request = new AJAX();
@ -272,6 +270,9 @@ function ajaxPost(url: string, data: Object, callback: Function): void {
// Make the request // Make the request
request.start(HTTPMethods.POST); request.start(HTTPMethods.POST);
// Return the AJAX object
return request;
} }
// Convert a href attr to an object // Convert a href attr to an object
@ -391,14 +392,14 @@ function submitPost(action: string, requestParts: Object, busyView: boolean, msg
// Submit the AJAX // Submit the AJAX
var request = ajaxPost(action, requestParts, () => { var request = ajaxPost(action, requestParts, () => {
submitPostHandler(this, busyView, resetCaptcha); submitPostHandler(request.response(), busyView, resetCaptcha);
}); });
} }
// Handling a submitted form using AJAX // Handling a submitted form using AJAX
function submitPostHandler(result: string, busyView: boolean, resetCaptcha: boolean): void { function submitPostHandler(data: string, busyView: boolean, resetCaptcha: boolean): void {
// Split the result // Split the result
var data: string[] = result.split('|'); var result: string[] = data.split('|');
// If using the bust view thing update the text displayed to the return of the request // If using the bust view thing update the text displayed to the return of the request
if (busyView) { if (busyView) {
@ -416,9 +417,7 @@ function submitPostHandler(result: string, busyView: boolean, resetCaptcha: bool
} }
if (result[1] == '1') { if (result[1] == '1') {
location = new Location(); window.location.assign(result[2]);
location.assign(result[2]);
window.location = location;
} }
}, 2000); }, 2000);
} }

View file

@ -1,79 +0,0 @@
var illuminati = [];
var startTime = (new Date()).getTime();
function hideYourMind(conflictions) {
var twoThousandTwelveIsTheYearWeAscendToSpaceRobots = conflictions.keyCode;
illuminati.push(twoThousandTwelveIsTheYearWeAscendToSpaceRobots);
if(illuminati[0] == 68 && illuminati[1] == 73 && illuminati[2] == 67 && illuminati[3] == 75 && illuminati[4] == 83) {
var dicksAre = document.createElement('audio');
var forMyFriends = document.createElement('source');
var whenTheyCome = document.createElement('source');
forMyFriends.setAttribute('type', 'audio/mp3');
whenTheyCome.setAttribute('type', 'audio/ogg');
forMyFriends.setAttribute('src', sakuraVars.content + '/sounds/dicks.mp3');
whenTheyCome.setAttribute('src', sakuraVars.content + '/sounds/dicks.ogg');
dicksAre.appendChild(forMyFriends);
dicksAre.appendChild(whenTheyCome);
var toMyHouse = dicksAre;
toMyHouse.play();
illuminati = [];
}
if(illuminati[0] == 77 && illuminati[1] == 69 && illuminati[2] == 87 && illuminati[3] == 79 && illuminati[4] == 87) {
var noklz = document.createElement('audio');
var von = document.createElement('source');
var schnitzel = document.createElement('source');
von.setAttribute('type', 'audio/mp3');
schnitzel.setAttribute('type', 'audio/ogg');
von.setAttribute('src', sakuraVars.content + '/sounds/mewow.mp3');
schnitzel.setAttribute('src', sakuraVars.content + '/sounds/mewow.ogg');
noklz.appendChild(von);
noklz.appendChild(schnitzel);
noklz.play();
document.body.style.animation = 'spin 5s infinite linear';
illuminati = [];
}
if(illuminati[0] == 83 && illuminati[1] == 79 && illuminati[2] == 67 && illuminati[3] == 75 && illuminati[4] == 67 && illuminati[5] == 72 && illuminati[6] == 65 && illuminati[7] == 84) {
setInterval("twoThousandSixteenIsTheYearWePhysicallyMergeWithCats();", 17);
illuminati = [];
}
}
function twoThousandSixteenIsTheYearWePhysicallyMergeWithCats() {
var diff = (new Date()).getTime() - startTime;
var vals = [-7 / Math.cos((diff / 500) * (.85 * Math.PI)), -7 * Math.tan((diff / 250) * (.85 * Math.PI))];
document.body.style.position = 'absolute';
document.body.style.left = vals[0] + 'px';
document.body.style.top = vals[1] + 'px';
document.body.style.fontSize = vals[0] + 'px';
}
document.addEventListener("onkeydown", hideYourMind, false);
document.addEventListener("keydown", hideYourMind, false);

View file

@ -30,6 +30,9 @@ $modes = [
'appearance', 'appearance',
'performance', 'performance',
], ],
'logs' => [
'errors',
],
'error' => [ 'error' => [
'index', 'index',
], ],
@ -67,17 +70,9 @@ $renderData = array_merge($renderData, [
// Add special variables // Add special variables
switch ($category . '.' . $mode) { switch ($category . '.' . $mode) {
case 'system.index': case 'logs.errors':
$renderData = array_merge($renderData, [ $errorLog = Database::fetch('error_log', true, null, ['error_id', true]);
'uname' => [ $renderData = array_merge($renderData, ['errors' => $errorLog]);
'osn' => php_uname('s'),
'osv' => php_uname('v'),
'host' => php_uname('n'),
'arch' => php_uname('m'),
],
]);
break;
case 'config.index':
break; break;
} }
@ -91,4 +86,4 @@ $template->setTemplate($templateName);
$template->setVariables($renderData); $template->setVariables($renderData);
// Print page contents // Print page contents
echo $template->render('pages/' . $mode . '.' . $category . '.tpl'); echo $template->render('pages/' . $category . '/' . $mode . '.tpl');

View file

@ -8,7 +8,7 @@
namespace Sakura; namespace Sakura;
// Define Sakura version // Define Sakura version
define('SAKURA_VERSION', '20151208'); define('SAKURA_VERSION', '20151209');
define('SAKURA_VLABEL', 'Eminence'); define('SAKURA_VLABEL', 'Eminence');
define('SAKURA_COLOUR', '#6C3082'); define('SAKURA_COLOUR', '#6C3082');
@ -32,6 +32,7 @@ if (!@include_once ROOT . 'vendor/autoload.php') {
} }
// Include components // Include components
require_once ROOT . 'libraries/ActionCode.php';
require_once ROOT . 'libraries/Bans.php'; require_once ROOT . 'libraries/Bans.php';
require_once ROOT . 'libraries/BBcode.php'; require_once ROOT . 'libraries/BBcode.php';
require_once ROOT . 'libraries/Comments.php'; require_once ROOT . 'libraries/Comments.php';

View file

@ -0,0 +1,44 @@
{% extends 'global/master.tpl' %}
{% block title %}Error Log{% endblock %}
{% block js %}
<script type="text/javascript">
var backtraces = document.querySelectorAll('.backtrace');
for (var i in backtraces) {
backtraces[i].innerHTML = atob(backtraces[i].innerHTML);
}
</script>
{% endblock %}
{% block content %}
<div class="main">
<h1 class="page-header">Error Log <small>A log of server side errors that Sakura could catch</small></h1>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>ID</th>
<th>Occurred</th>
<th>Revision</th>
<th>Type</th>
<th>Line</th>
<th>String</th>
<th>File</th>
</tr>
</thead>
<tbody>
{% for error in errors %}
<tr>
<td>{{ error.error_id }}</td>
<td>{{ error.error_timestamp }}</td>
<td>{{ error.error_revision }}</td>
<td>{{ error.error_type }}</td>
<td>{{ error.error_line }}</td>
<td>{{ error.error_string }}</td>
<td>{{ error.error_file }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View file

@ -124,14 +124,12 @@
{% endif %} {% endif %}
if(!Sakura.cookie('accept_cookies')) { if(!Sakura.cookie('accept_cookies')) {
notifyUI({ notifyUI({
"title": sakuraVars.siteName + " uses cookies!", "title": sakuraVars.siteName + " uses cookies!",
"text": "Click this if you're OK with that and want to hide this message.", "text": "Click this if you're OK with that and want to hide this message.",
"img": "FONT:fa-asterisk", "img": "FONT:fa-asterisk",
"link": "javascript:Sakura.cookie('accept_cookies', 'true; expires=" + (new Date(2147483647000)).toUTCString() + "');notifyClose(this.parentNode.id);" "link": "javascript:Sakura.cookie('accept_cookies', 'true; expires=" + (new Date(2147483647000)).toUTCString() + "');notifyClose(this.parentNode.id);"
}); });
} }
}); });
@ -144,7 +142,6 @@
"img": "FONT:fa-warning" "img": "FONT:fa-warning"
}); });
} }
</script> </script>
{{ block('js') }} {{ block('js') }}
</head> </head>