diff --git a/_sakura/changelog.json b/_sakura/changelog.json
index a4acdd6..2b08a59 100644
--- a/_sakura/changelog.json
+++ b/_sakura/changelog.json
@@ -25,7 +25,8 @@
"20150503",
"20150503.1",
"20150504",
- "20150504.1"
+ "20150504.1",
+ "20150505"
]
@@ -914,6 +915,23 @@
"change": "Add beginning parts of the warning systems."
}
+ ],
+
+ "20150505": [
+
+ {
+ "type": "UPD",
+ "change": "getWarnings() can now return all warnings when the first parameter is false."
+ },
+ {
+ "type": "ADD",
+ "change": "Added parallax effect to profile backgrounds."
+ },
+ {
+ "type": "ADD",
+ "change": "Added comments to the Yuuno JavaScript."
+ }
+
]
}
diff --git a/_sakura/components/Users.php b/_sakura/components/Users.php
index 132d564..8a3f6bd 100644
--- a/_sakura/components/Users.php
+++ b/_sakura/components/Users.php
@@ -919,12 +919,12 @@ class Users {
}
// Get all warnings issued to a user (or all warnings a user issued)
- public static function getWarnings($uid, $iid = false) {
+ public static function getWarnings($uid = 0, $iid = false) {
// Do the database query
- $warnings = Database::fetch('warnings', true, [
+ $warnings = Database::fetch('warnings', true, ($uid ? [
($iid ? 'iid' : 'uid') => [$uid, '=']
- ]);
+ ] : null));
// Return all the warnings
return $warnings;
diff --git a/_sakura/sakura.php b/_sakura/sakura.php
index c47d24c..df0eae5 100644
--- a/_sakura/sakura.php
+++ b/_sakura/sakura.php
@@ -8,7 +8,7 @@
namespace Sakura;
// Define Sakura version
-define('SAKURA_VERSION', '20150504');
+define('SAKURA_VERSION', '20150505');
define('SAKURA_VLABEL', 'Heliotrope');
define('SAKURA_VTYPE', 'Development');
define('SAKURA_COLOUR', '#DF73FF');
diff --git a/_sakura/templates/yuuno/main/profile.tpl b/_sakura/templates/yuuno/main/profile.tpl
index 4d69e2e..dedc0bc 100644
--- a/_sakura/templates/yuuno/main/profile.tpl
+++ b/_sakura/templates/yuuno/main/profile.tpl
@@ -11,7 +11,7 @@
{% else %}
-
@@ -64,7 +64,7 @@
{% else %}
{% if profile.warnings %}
Bad
- This user has {{ profile.warnings|length }} warning{% if profile.warnings|length != 1 %}s{% endif %}.
After 5 to 10 more warnings (depending on what they are for) this user may be permanently banned.
+ This user has {{ profile.warnings|length }} warning{% if profile.warnings|length != 1 %}s{% endif %}.
After 5 to 10 warnings (depending on what they are for) this user may be permanently banned.
{% else %}
Good
{% endif %}
@@ -76,5 +76,10 @@
+ {% if profile.user.background_url %}
+
+ {% endif %}
{% endif %}
{% include 'global/footer.tpl' %}
diff --git a/content/data/yuuno/js/yuuno.js b/content/data/yuuno/js/yuuno.js
index 9d26bdc..5909a86 100644
--- a/content/data/yuuno/js/yuuno.js
+++ b/content/data/yuuno/js/yuuno.js
@@ -2,54 +2,78 @@
* 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;
return;
-
+
default:
return;
+
}
+
}
+// Toggling the menu on mobile devices
function mobileMenu(mode) {
+
+ // Assign the elements to variables
var ucpMenuBtn = document.getElementById('navMenuSite');
var navMenuBtn = document.getElementById('navMenuUser');
var mobMenuBtn = document.getElementById('mobileNavToggle');
+ // Open or close the menus depending on the values
if(mode) {
+
+ // Alter the classes
ucpMenuBtn.className = ucpMenuBtn.className + ' menu-hid';
navMenuBtn.className = navMenuBtn.className + ' menu-hid';
-
+
+ // Update the button
mobMenuBtn.innerHTML = 'Close Menu';
mobMenuBtn.setAttribute('onclick', 'mobileMenu(false);');
+
} else {
+
+ // Alter the classes
ucpMenuBtn.className = ucpMenuBtn.className.replace(' menu-hid', '');
navMenuBtn.className = navMenuBtn.className.replace(' menu-hid', '');
-
+
+ // Update the button
mobMenuBtn.innerHTML = 'Open Menu';
mobMenuBtn.setAttribute('onclick', 'mobileMenu(true);');
+
}
+
}
+// Event watcher for the scroll-to-top button
window.onscroll = function() {
+
+ // Assign the gotop button to a variable
var gotop = document.getElementById('gotop');
-
- if(this.pageYOffset < 112) {
- if(gotop.getAttribute('class').indexOf('hidden') < 0)
- gotop.setAttribute('class', gotop.getAttribute('class') + ' hidden');
- } else if(this.pageYOffset > 112)
- gotop.setAttribute('class', gotop.getAttribute('class').replace(' hidden', ''));
+
+ // If the vertical offset of the page is below 112px (just below the header) keep the button hidden
+ if(this.pageYOffset < 112) {
+ if(gotop.getAttribute('class').indexOf('hidden') < 0)
+ gotop.setAttribute('class', gotop.getAttribute('class') + ' hidden');
+ } else if(this.pageYOffset > 112) // Else show it
+ gotop.setAttribute('class', gotop.getAttribute('class').replace(' hidden', ''));
+
};
+// Get the current unix/epoch timestamp
function epochTime() {
- var time = Date.now();
- time = time / 1000;
- return Math.floor(time);
+
+ return Math.floor(Date.now() / 1000);
+
}
/*
@@ -119,53 +143,78 @@ function notificationRequest() {
setTimeout(notificationRequest, 5000);
}*/
+// Donate page specific features
function donatePage(id) {
+
+ // Get the featureBoxDesc elements
var featureBoxDesc = document.getElementsByClassName('featureBoxDesc');
+ // If an id wasn't set assume that we're doing initialisation
if(!id) {
+
+ // Go over every element and add donateClosed to the end of the class
for(var i = 0; i < featureBoxDesc.length; i++)
featureBoxDesc[i].className = featureBoxDesc[i].className + ' donateClosed';
-
+
+ // Then stop the execution of the function
return;
+
}
-
+
+ // Get the second child of the featureBox (which is the description)
var featureBox = document.getElementById(id).children[1];
-
+
+ // Search for donateOpened in the class and if found...
if(featureBox.className.search('donateOpened') > 0) {
+
+ // replace it with nothing and add donateClosed to the class
featureBox.className = featureBox.className.replace(' donateOpened', '');
featureBox.className = featureBox.className + ' donateClosed';
-
- return;
+
} else {
+
+ // Else do the opposite of what was described above
featureBox.className = featureBox.className.replace(' donateClosed', '');
featureBox.className = featureBox.className + ' donateOpened';
-
- return;
+
}
-
- return;
+
}
+// 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');
var busyAnim = document.getElementById('ajaxAnimate');
var pageContent = document.getElementById('contentwrapper');
+ // Select the proper icon
switch(type) {
default:
@@ -181,69 +230,106 @@ function ajaxBusyView(show, message, type) {
}
+ // 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';
createBusyCont.setAttribute('id', 'ajaxBusy');
+ // Inner box
var createBusyInner = document.createElement('div');
createBusyInner.className = 'ajax-inner';
createBusyCont.appendChild(createBusyInner);
+ // Action description
var createBusyMsg = document.createElement('h2');
createBusyMsg.setAttribute('id', 'ajaxStatus');
createBusyInner.appendChild(createBusyMsg);
+ // FontAwesome icon
var createBusySpin = document.createElement('div');
createBusySpin.setAttribute('id', 'ajaxAnimate');
createBusyInner.appendChild(createBusySpin);
+ // Append the element to the actual page
pageContent.appendChild(createBusyCont);
-
+
+ // Reassign the previously assigned variables
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
busyAnim.className = busyAnimIco;
- if(message == null)
- busyStat.innerHTML = 'Please wait';
- else
- busyStat.innerHTML = message;
- } else {
+ // 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 - .1;
- } else {
+
+ } 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) {
+
+ // Create a new XMLHttpRequest
var req = new XMLHttpRequest();
+
+ // Open a post request
req.open("POST", url, false);
+
+ // Set the request header to a form
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+ // Combine name and value with an = inbetween
var query = [];
for(var i in data)
query.push(encodeURIComponent(i) +"="+ encodeURIComponent(data[i]));
+ // Join the array and submit the request
req.send(query.join("&"));
+ // If the HTTP resonse was 200 return the page
if(req.status === 200)
return req.responseText;
- else
+ else // Else return nothing
return "";
+
}
// Quickly building a form for god knows what reason
@@ -347,3 +433,56 @@ function submitPost(formId, busyView, msg) {
return;
}
+
+// 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;
+
+}
diff --git a/main/.htaccess b/main/.htaccess
index 3e7e4bd..0ec8633 100644
--- a/main/.htaccess
+++ b/main/.htaccess
@@ -31,6 +31,9 @@ RewriteRule ^news?/?$ news.php
RewriteRule ^news/([0-9]+)$ news.php?id=$1
RewriteRule ^news.xml$ news.php?xml
+## Settings
+RewriteRule ^settings?/?$ settings.php
+
## Members
RewriteRule ^members?/?$ members.php
RewriteRule ^members/([a-z]+)?/?$ members.php?sort=$1
diff --git a/main/index.php b/main/index.php
index 5d969bc..6081937 100644
--- a/main/index.php
+++ b/main/index.php
@@ -16,10 +16,10 @@ $renderData['page'] = [
'articleCount' => count($renderData['newsPosts'])
];
$renderData['stats'] = [
- 'userCount' => ($userCount = count($users = Users::getAllUsers(false))) .' user'. ($userCount == 1 ? '' : 's'),
- 'newestUser' => max($users),
- 'lastRegDate' => ($lastRegDate = date_diff(date_create(date('Y-m-d', max($users)['regdate'])), date_create(date('Y-m-d')))->format('%a')) .' day'. ($lastRegDate == 1 ? '' : 's'),
- 'chatOnline' => ($chatOnline = count(SockChat::getOnlineUsers())) .' user'. ($chatOnline == 1 ? '' : 's'),
+ 'userCount' => ($_INDEX_USER_COUNT = count($_INDEX_USERS = Users::getAllUsers(false))) .' user'. ($_INDEX_USER_COUNT == 1 ? '' : 's'),
+ 'newestUser' => ($_INDEX_NEWEST_USER = max($_INDEX_USERS)),
+ 'lastRegDate' => ($_INDEX_LAST_REGDATE = date_diff(date_create(date('Y-m-d', $_INDEX_NEWEST_USER['regdate'])), date_create(date('Y-m-d')))->format('%a')) .' day'. ($_INDEX_LAST_REGDATE == 1 ? '' : 's'),
+ 'chatOnline' => ($_INDEX_CHAT_ONLINE = count(SockChat::getOnlineUsers())) .' user'. ($_INDEX_CHAT_ONLINE == 1 ? '' : 's'),
'onlineUsers' => Users::checkAllOnline()
];
diff --git a/main/profile.php b/main/profile.php
index 3a03e69..21f3edb 100644
--- a/main/profile.php
+++ b/main/profile.php
@@ -40,8 +40,8 @@ if(isset($_GET['u'])) {
$renderData['page'] = [
'title' => ($_PROFILE_USER_DATA['id'] < 1 || $_PROFILE_USER_DATA['password_algo'] == 'nologin' ? 'User not found!' : 'Profile of '. $_PROFILE_USER_DATA['username']),
'style' => ($_PROFILE_USER_DATA['background_url'] ? [
- '.userBackground' => [
- 'background' => 'url("/bg/'. $_PROFILE_USER_DATA['id'] .'") no-repeat fixed center center / cover transparent !important',
+ '#userBackground' => [
+ 'background' => 'url("/bg/'. $_PROFILE_USER_DATA['id'] .'") no-repeat center center / cover transparent !important',
'position' => 'fixed',
'top' => '0',
'bottom' => '0',