typescript because fuck rubberscript
seriously why is javascript so globally loved
This commit is contained in:
parent
fd6baecb7d
commit
3b3b6f1c3e
7 changed files with 301 additions and 146 deletions
|
@ -47,11 +47,11 @@ class BBcode
|
|||
self::$bbcode->addCodeDefinition($builder->build());
|
||||
|
||||
// Box tag
|
||||
$builder = new CodeDefinitionBuilder('box', '<div class="spoiler-box-container"><div class="spoiler-box-title" onclick="toggleClass(this.parentNode.children[1], \'hidden\');">Click to open</div><div class="spoiler-box-content hidden">{param}</div></div>');
|
||||
$builder = new CodeDefinitionBuilder('box', '<div class="spoiler-box-container"><div class="spoiler-box-title" onclick="Sakura.toggleClass(this.parentNode.children[1], \'hidden\');">Click to open</div><div class="spoiler-box-content hidden">{param}</div></div>');
|
||||
self::$bbcode->addCodeDefinition($builder->build());
|
||||
|
||||
// Box tag
|
||||
$builder = new CodeDefinitionBuilder('box', '<div class="spoiler-box-container"><div class="spoiler-box-title" onclick="toggleClass(this.parentNode.children[1], \'hidden\');">{option}</div><div class="spoiler-box-content hidden">{param}</div></div>');
|
||||
$builder = new CodeDefinitionBuilder('box', '<div class="spoiler-box-container"><div class="spoiler-box-title" onclick="Sakura.toggleClass(this.parentNode.children[1], \'hidden\');">{option}</div><div class="spoiler-box-content hidden">{param}</div></div>');
|
||||
$builder->setUseOption(true);
|
||||
self::$bbcode->addCodeDefinition($builder->build());
|
||||
|
||||
|
|
14
libraries/Router.php
Normal file
14
libraries/Router.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/*
|
||||
* Router class
|
||||
*/
|
||||
|
||||
namespace Sakura;
|
||||
|
||||
/**
|
||||
* Class Router
|
||||
* @package Sakura
|
||||
*/
|
||||
class Router
|
||||
{
|
||||
}
|
|
@ -2,26 +2,6 @@
|
|||
* Sakura Yuuno JavaScript
|
||||
*/
|
||||
|
||||
// Get or set cookies
|
||||
function cookieData(action, name, data) {
|
||||
switch(action) {
|
||||
case 'get':
|
||||
return (result = new RegExp('(^|; )' + encodeURIComponent(name) + '=([^;]*)').exec(document.cookie)) ? result[2] : '';
|
||||
|
||||
case 'set':
|
||||
document.cookie = name + '=' + data + '; path=/';
|
||||
return null;
|
||||
|
||||
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
|
||||
|
@ -133,7 +113,7 @@ function notifyClose(id) {
|
|||
// Remove the element after 500 milliseconds (animation takes 400)
|
||||
setTimeout(function() {
|
||||
// Use the later defined removeId function
|
||||
removeId(id);
|
||||
Sakura.removeId(id);
|
||||
}, 410);
|
||||
}
|
||||
|
||||
|
@ -155,7 +135,7 @@ function notifyRequest(session) {
|
|||
|
||||
// Create XMLHttpRequest and notifyURL
|
||||
var notificationWatcher = new XMLHttpRequest();
|
||||
var notifyURL = '//' + sakuraVars.urlMain + '/settings.php?request-notifications=true&time=' + epochTime() + '&session=' + session;
|
||||
var notifyURL = '//' + sakuraVars.urlMain + '/settings.php?request-notifications=true&time=' + Sakura.epoch() + '&session=' + session;
|
||||
|
||||
// Wait for the ready state to change
|
||||
notificationWatcher.onreadystatechange = function() {
|
||||
|
@ -203,40 +183,6 @@ function notifyRequest(session) {
|
|||
notificationWatcher.send();
|
||||
}
|
||||
|
||||
// Toggle a class on an element
|
||||
function toggleClass(element, name) {
|
||||
// Attempt to get the index
|
||||
var indexOf = element.className.indexOf(name);
|
||||
|
||||
if (indexOf < 0) {
|
||||
element.className += ' ' + name;
|
||||
} else {
|
||||
element.className = element.className.replace(name, '').trim();
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -312,7 +258,7 @@ function ajaxBusyView(show, message, type) {
|
|||
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');
|
||||
Sakura.removeId('ajaxBusy');
|
||||
clearInterval(fadeOut);
|
||||
}
|
||||
}, 10);
|
||||
|
@ -519,84 +465,9 @@ function submitPostHandler(result, busyView, resetCaptchaOnFailure) {
|
|||
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if it meets the maximum
|
||||
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);
|
||||
return (Sakura.pwdEntropy(pwd) >= sakuraVars.minPwdEntropy);
|
||||
}
|
||||
|
||||
// Check registration variables
|
||||
|
@ -617,12 +488,12 @@ function registerVarCheck(id, mode, option) {
|
|||
break;
|
||||
|
||||
case 'email':
|
||||
check = validateEmail(input.value);
|
||||
check = Sakura.validateEmail(input.value);
|
||||
break;
|
||||
|
||||
case 'username':
|
||||
default:
|
||||
check = checkStringLength(input.value, sakuraVars.minUserLen, sakuraVars.maxUserLen);
|
||||
check = Sakura.stringLength(input.value, sakuraVars.minUserLen, sakuraVars.maxUserLen);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -722,7 +593,7 @@ function commentReply(id, session, category, action, avatar) {
|
|||
|
||||
// Remove it if it already exists
|
||||
if(replyBox) {
|
||||
removeId('comment-reply-container-' + id);
|
||||
Sakura.removeId('comment-reply-container-' + id);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
126
public/content/scripts/sakura.js
Normal file
126
public/content/scripts/sakura.js
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Shared client side code
|
||||
*/
|
||||
// Meta functions
|
||||
var Sakura = (function () {
|
||||
function Sakura() {
|
||||
}
|
||||
// Get or set a cookie value
|
||||
Sakura.cookie = function (name, value) {
|
||||
if (value === void 0) { value = null; }
|
||||
// If value is null only get the cookie's value
|
||||
if (value) {
|
||||
// Delete the old instance
|
||||
document.cookie = this.cookiePrefix + name + '=;expires=Thu, 01 Jan 1970 00:00:01 GMT; path=' + this.cookiePath;
|
||||
// Assign the cookie
|
||||
document.cookie = this.cookiePrefix + name + '=' + value + '; path=' + this.cookiePath;
|
||||
// Pass the value through
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
// Perform a regex on document.cookie
|
||||
var get = new RegExp('(^|; )' + encodeURIComponent(this.cookiePrefix + name) + '=([^;]*)').exec(document.cookie);
|
||||
// If anything was returned return it (professional phrasing)
|
||||
return get ? get[2] : '';
|
||||
}
|
||||
};
|
||||
// Unix timestamp
|
||||
Sakura.epoch = function () {
|
||||
return Math.floor(Date.now() / 1000);
|
||||
};
|
||||
// Toggle a class
|
||||
Sakura.toggleClass = function (element, name) {
|
||||
// Check if the class already exists and if not add it
|
||||
if (element.className.indexOf(name) < 0) {
|
||||
element.className += ' ' + name;
|
||||
}
|
||||
else {
|
||||
element.className = element.className.replace(name, '').trim();
|
||||
}
|
||||
};
|
||||
// Remove every element with a specific class name
|
||||
Sakura.removeByClass = function (name) {
|
||||
// Get the elements
|
||||
var objs = document.getElementsByClassName(name);
|
||||
// Use a while loop to remove each element
|
||||
while (objs.length > 0) {
|
||||
objs[0].parentNode.removeChild(objs[0]);
|
||||
}
|
||||
};
|
||||
// Remove a single element with a specific id
|
||||
Sakura.removeById = function (id) {
|
||||
// Get the element
|
||||
var obj = document.getElementById(id);
|
||||
// If the element exists use the parent node to remove it
|
||||
if (typeof (obj) != "undefined" && obj !== null) {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
};
|
||||
// Alternative for Math.log2() since it's still experimental
|
||||
Sakura.log2 = function (num) {
|
||||
return Math.log(num) / Math.log(2);
|
||||
};
|
||||
// Get the number of unique characters in a string
|
||||
Sakura.unique = function (string) {
|
||||
// Store the already found character
|
||||
var used = [];
|
||||
// The amount of characters we've already found
|
||||
var count = 0;
|
||||
// Count the amount of unique characters
|
||||
for (var i = 0; i < string.length; i++) {
|
||||
// Check if we already counted this character
|
||||
if (used.indexOf(string[i]) == -1) {
|
||||
// Push the character into the used array
|
||||
used.push(string[i]);
|
||||
// Up the count
|
||||
count++;
|
||||
}
|
||||
}
|
||||
// Return the count
|
||||
return count;
|
||||
};
|
||||
// Calculate password entropy
|
||||
Sakura.entropy = function (string) {
|
||||
// Decode utf-8 encoded characters
|
||||
string = utf8.decode(string);
|
||||
// Count the unique characters in the string
|
||||
var unique = this.unique(string);
|
||||
// Do the entropy calculation
|
||||
return unique * this.log2(256);
|
||||
};
|
||||
// Validate string lengths
|
||||
Sakura.stringLength = function (string, minimum, maximum) {
|
||||
// Get length of string
|
||||
var length = string.length;
|
||||
// Check if it meets the minimum/maximum
|
||||
if (length < minimum || length > maximum) {
|
||||
return false;
|
||||
}
|
||||
// If it passes both return true
|
||||
return true;
|
||||
};
|
||||
// Validate email address formats
|
||||
Sakura.validateEmail = function (email) {
|
||||
// RFC compliant e-mail address regex
|
||||
var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,48})+$/;
|
||||
// Test it on the email var which'll return a boolean
|
||||
return re.test(email);
|
||||
};
|
||||
Sakura.cookiePrefix = ""; // Cookie prefix, gets prepended to cookie names
|
||||
Sakura.cookiePath = "/"; // Cookie path, can in most cases be left untouched
|
||||
return Sakura;
|
||||
})();
|
||||
// UTF-8 functions
|
||||
var utf8 = (function () {
|
||||
function utf8() {
|
||||
}
|
||||
// Encode a utf-8 string
|
||||
utf8.encode = function (string) {
|
||||
return unescape(encodeURIComponent(string));
|
||||
};
|
||||
// Decode a utf-8 string
|
||||
utf8.decode = function (string) {
|
||||
return decodeURIComponent(escape(string));
|
||||
};
|
||||
return utf8;
|
||||
})();
|
144
public/content/scripts/sakura.ts
Normal file
144
public/content/scripts/sakura.ts
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Shared client side code
|
||||
*/
|
||||
|
||||
// Meta functions
|
||||
class Sakura {
|
||||
public static cookiePrefix: string = ""; // Cookie prefix, gets prepended to cookie names
|
||||
public static cookiePath: string = "/"; // Cookie path, can in most cases be left untouched
|
||||
|
||||
// Get or set a cookie value
|
||||
public static cookie(name: string, value: string = null): string {
|
||||
// If value is null only get the cookie's value
|
||||
if (value) {
|
||||
// Delete the old instance
|
||||
document.cookie = this.cookiePrefix + name + '=;expires=Thu, 01 Jan 1970 00:00:01 GMT; path=' + this.cookiePath;
|
||||
|
||||
// Assign the cookie
|
||||
document.cookie = this.cookiePrefix + name + '=' + value + '; path=' + this.cookiePath;
|
||||
|
||||
// Pass the value through
|
||||
return value;
|
||||
} else {
|
||||
// Perform a regex on document.cookie
|
||||
var get = new RegExp('(^|; )' + encodeURIComponent(this.cookiePrefix + name) + '=([^;]*)').exec(document.cookie);
|
||||
|
||||
// If anything was returned return it (professional phrasing)
|
||||
return get ? get[2] : '';
|
||||
}
|
||||
}
|
||||
|
||||
// Unix timestamp
|
||||
public static epoch(): number {
|
||||
return Math.floor(Date.now() / 1000);
|
||||
}
|
||||
|
||||
// Toggle a class
|
||||
public static toggleClass(element: HTMLElement, name: string): void {
|
||||
// Check if the class already exists and if not add it
|
||||
if (element.className.indexOf(name) < 0) {
|
||||
element.className += ' ' + name;
|
||||
} else { // If so remove it and kill additional spaces
|
||||
element.className = element.className.replace(name, '').trim();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove every element with a specific class name
|
||||
public static removeByClass(name: string): void {
|
||||
// Get the elements
|
||||
var objs = document.getElementsByClassName(name);
|
||||
|
||||
// Use a while loop to remove each element
|
||||
while (objs.length > 0) {
|
||||
objs[0].parentNode.removeChild(objs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a single element with a specific id
|
||||
public static removeById(id: string): void {
|
||||
// Get the element
|
||||
var obj = document.getElementById(id);
|
||||
|
||||
// If the element exists use the parent node to remove it
|
||||
if (typeof (obj) != "undefined" && obj !== null) {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
}
|
||||
|
||||
// Alternative for Math.log2() since it's still experimental
|
||||
public static log2(num: number): number {
|
||||
return Math.log(num) / Math.log(2);
|
||||
}
|
||||
|
||||
// Get the number of unique characters in a string
|
||||
public static unique(string: string): number {
|
||||
// Store the already found character
|
||||
var used: string[] = [];
|
||||
|
||||
// The amount of characters we've already found
|
||||
var count: number = 0;
|
||||
|
||||
// Count the amount of unique characters
|
||||
for (var i = 0; i < string.length; i++) {
|
||||
// Check if we already counted this character
|
||||
if (used.indexOf(string[i]) == -1) {
|
||||
// Push the character into the used array
|
||||
used.push(string[i]);
|
||||
|
||||
// Up the count
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the count
|
||||
return count;
|
||||
}
|
||||
|
||||
// Calculate password entropy
|
||||
public static entropy(string: string): number {
|
||||
// Decode utf-8 encoded characters
|
||||
string = utf8.decode(string);
|
||||
|
||||
// Count the unique characters in the string
|
||||
var unique: number = this.unique(string);
|
||||
|
||||
// Do the entropy calculation
|
||||
return unique * this.log2(256);
|
||||
}
|
||||
|
||||
// Validate string lengths
|
||||
public static stringLength(string: string, minimum: number, maximum: number): boolean {
|
||||
// Get length of string
|
||||
var length = string.length;
|
||||
|
||||
// Check if it meets the minimum/maximum
|
||||
if (length < minimum || length > maximum) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it passes both return true
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validate email address formats
|
||||
public static validateEmail(email: string): boolean {
|
||||
// RFC compliant e-mail address regex
|
||||
var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,48})+$/;
|
||||
|
||||
// Test it on the email var which'll return a boolean
|
||||
return re.test(email);
|
||||
}
|
||||
}
|
||||
|
||||
// UTF-8 functions
|
||||
class utf8 {
|
||||
// Encode a utf-8 string
|
||||
public static encode(string): string {
|
||||
return unescape(encodeURIComponent(string));
|
||||
}
|
||||
|
||||
// Decode a utf-8 string
|
||||
public static decode(string): string {
|
||||
return decodeURIComponent(escape(string));
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
namespace Sakura;
|
||||
|
||||
// Define Sakura version
|
||||
define('SAKURA_VERSION', '20151204');
|
||||
define('SAKURA_VERSION', '20151206');
|
||||
define('SAKURA_VLABEL', 'Eminence');
|
||||
define('SAKURA_COLOUR', '#6C3082');
|
||||
|
||||
|
|
|
@ -32,18 +32,15 @@
|
|||
<link rel="stylesheet" type="text/css" href="{{ sakura.resources }}/css/yuuno.css" />
|
||||
{{ block('css') }}
|
||||
<!-- JS -->
|
||||
<script type="text/javascript" src="{{ sakura.contentPath }}/scripts/sakura.js"></script>
|
||||
<script type="text/javascript" src="{{ sakura.resources }}/js/yuuno.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
// Create an object so we can access certain settings from remote JavaScript files
|
||||
var sakuraVars = {
|
||||
|
||||
"cookie": {
|
||||
|
||||
"prefix": "{{ sakura.cookie.prefix }}",
|
||||
"domain": "{{ sakura.cookie.domain }}",
|
||||
"path": "{{ sakura.cookie.path }}"
|
||||
|
||||
},
|
||||
|
||||
"siteName": "{{ sakura.siteName }}",
|
||||
|
@ -56,9 +53,12 @@
|
|||
"maxUserLen": {{ sakura.maxUsernameLength }},
|
||||
"minPwdEntropy": {{ sakura.minPwdEntropy }},
|
||||
"checkLogin": {% if session.checkLogin %}true{% else %}false{% endif %}
|
||||
|
||||
};
|
||||
|
||||
// Set cookie prefix and path
|
||||
Sakura.cookiePrefix = "{{ sakura.cookie.prefix }}";
|
||||
Sakura.cookiePath = "{{ sakura.cookie.path }}";
|
||||
|
||||
// Space for things that need to happen onload
|
||||
window.addEventListener("load", function() {
|
||||
|
||||
|
@ -123,13 +123,13 @@
|
|||
|
||||
{% endif %}
|
||||
|
||||
if(!cookieData('get', sakuraVars.cookie.prefix +'accept_cookies')) {
|
||||
if(!Sakura.cookie('accept_cookies')) {
|
||||
|
||||
notifyUI({
|
||||
"title": sakuraVars.siteName + " uses cookies!",
|
||||
"text": "Click this if you're OK with that and want to hide this message.",
|
||||
"img": "FONT:fa-asterisk",
|
||||
"link": "javascript:cookieData('set', '" + sakuraVars.cookie.prefix + "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);"
|
||||
});
|
||||
|
||||
}
|
||||
|
|
Reference in a new issue