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',