2015-04-12 13:33:59 +00:00
|
|
|
/*
|
|
|
|
* Sakura Yuuno JavaScript
|
|
|
|
*/
|
|
|
|
|
2015-05-09 00:56:55 +00:00
|
|
|
// Create a notification box
|
|
|
|
function notifyUI(content) {
|
|
|
|
// Grab the container and create an ID
|
|
|
|
var container = document.getElementById('notifications');
|
|
|
|
var identifier = 'sakura-notification-' + Date.now();
|
|
|
|
|
|
|
|
// Create the notification element and children
|
|
|
|
var notif = document.createElement('div');
|
|
|
|
var notifIcon = document.createElement('div');
|
|
|
|
var notifContent = document.createElement('div');
|
|
|
|
var notifTitle = document.createElement('div');
|
|
|
|
var notifText = document.createElement('div');
|
|
|
|
var notifClose = document.createElement('div');
|
2015-09-07 20:53:47 +00:00
|
|
|
var notifCloseIcon = document.createElement('div');
|
2015-05-09 00:56:55 +00:00
|
|
|
var notifClear = document.createElement('div');
|
2015-05-25 18:18:56 +00:00
|
|
|
var iconCont;
|
2015-05-09 00:56:55 +00:00
|
|
|
|
|
|
|
// Add ID and class on notification container
|
|
|
|
notif.className = 'notification-enter';
|
|
|
|
notif.setAttribute('id', identifier);
|
|
|
|
|
|
|
|
// Add icon
|
|
|
|
notifIcon .className = 'notification-icon';
|
|
|
|
if(content.img.substring(0, 5) == "FONT:") {
|
|
|
|
|
2015-05-25 18:18:56 +00:00
|
|
|
iconCont = document.createElement('div');
|
2015-05-09 00:56:55 +00:00
|
|
|
iconCont.className = 'font-icon fa ' + content.img.replace('FONT:', '') + ' fa-4x';
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2015-05-25 18:18:56 +00:00
|
|
|
iconCont = document.createElement('img');
|
2015-05-09 00:56:55 +00:00
|
|
|
iconCont.setAttribute('alt', identifier);
|
|
|
|
iconCont.setAttribute('src', content.img);
|
|
|
|
|
2015-04-12 13:33:59 +00:00
|
|
|
}
|
2015-05-09 00:56:55 +00:00
|
|
|
notifIcon .appendChild(iconCont);
|
|
|
|
notif .appendChild(notifIcon);
|
|
|
|
|
|
|
|
// 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);
|
2015-09-06 01:04:55 +00:00
|
|
|
notifContent.setAttribute('onclick', content.link.substring(0, 11) == 'javascript:' ? content.link.substring(11) : 'notifyOpen(this.parentNode.id);');
|
2015-05-09 00:56:55 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
notifContent .appendChild(notifTitle);
|
|
|
|
notifContent .appendChild(notifText);
|
|
|
|
notif .appendChild(notifContent);
|
|
|
|
|
|
|
|
// Add close button
|
|
|
|
notifClose .className = 'notification-close';
|
|
|
|
notifClose .setAttribute('onclick', 'notifyClose(this.parentNode.id);');
|
2015-09-07 20:53:47 +00:00
|
|
|
notifClose .appendChild(notifCloseIcon);
|
2015-05-09 00:56:55 +00:00
|
|
|
notif .appendChild(notifClose);
|
|
|
|
|
|
|
|
// Add .clear
|
|
|
|
notifClear .className = 'clear';
|
|
|
|
notif .appendChild(notifClear);
|
|
|
|
|
|
|
|
// Append the notification to the document so it actually shows up to the user also add the link
|
|
|
|
container.appendChild(notif);
|
|
|
|
|
|
|
|
// Play sound if requested
|
|
|
|
if(content.sound > 0) {
|
|
|
|
// Create sound element and mp3 and ogg sources
|
|
|
|
var sound = document.createElement('audio');
|
|
|
|
var soundMP3 = document.createElement('source');
|
|
|
|
var soundOGG = document.createElement('source');
|
|
|
|
|
|
|
|
// Assign the proper attributes to the sources
|
2015-08-09 20:27:03 +00:00
|
|
|
soundMP3.setAttribute('src', '//' + sakuraVars.content_path + '/sounds/notify.mp3');
|
2015-05-09 00:56:55 +00:00
|
|
|
soundMP3.setAttribute('type', 'audio/mp3');
|
2015-08-09 20:27:03 +00:00
|
|
|
soundOGG.setAttribute('src', '//' + sakuraVars.content_path + '/sounds/notify.ogg');
|
2015-05-09 00:56:55 +00:00
|
|
|
soundOGG.setAttribute('type', 'audio/ogg');
|
|
|
|
|
|
|
|
// Append the children
|
|
|
|
sound.appendChild(soundMP3);
|
|
|
|
sound.appendChild(soundOGG);
|
|
|
|
|
|
|
|
// Play the sound
|
|
|
|
sound.play();
|
2015-04-12 13:33:59 +00:00
|
|
|
}
|
2015-05-09 00:56:55 +00:00
|
|
|
|
|
|
|
// If keepalive is 0 keep the notification open "forever" (until the user closes it or changes the page)
|
|
|
|
if(content.timeout > 0) {
|
|
|
|
// Set set a timeout and execute notifyClose() after amount of milliseconds specified
|
|
|
|
setTimeout(function() {
|
|
|
|
// Use the later defined notifyClose function
|
|
|
|
notifyClose(identifier);
|
|
|
|
}, content.timeout);
|
2015-04-12 13:33:59 +00:00
|
|
|
}
|
2015-05-09 00:56:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Closing a notification box
|
|
|
|
function notifyClose(id) {
|
|
|
|
// Get the element and assign it to a variable
|
|
|
|
var element = document.getElementById(id);
|
|
|
|
|
|
|
|
// Do the animation
|
|
|
|
element.className = 'notification-exit';
|
|
|
|
|
|
|
|
// Remove the element after 500 milliseconds (animation takes 400)
|
|
|
|
setTimeout(function() {
|
|
|
|
// Use the later defined removeId function
|
2015-12-06 01:52:35 +00:00
|
|
|
Sakura.removeId(id);
|
2015-05-09 00:56:55 +00:00
|
|
|
}, 410);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Opening a link to a notifcated thing (what even)
|
|
|
|
function notifyOpen(id) {
|
|
|
|
var sakuraHref = document.getElementById(id).getAttribute('sakurahref');
|
|
|
|
|
2015-05-25 18:18:56 +00:00
|
|
|
if(typeof sakuraHref !== 'undefined') {
|
2015-05-09 00:56:55 +00:00
|
|
|
window.location = sakuraHref;
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
2015-05-09 00:56:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Request notifications
|
|
|
|
function notifyRequest(session) {
|
2015-09-10 21:19:51 +00:00
|
|
|
// Check if the document isn't hidden
|
|
|
|
if(document.hidden) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-05-09 00:56:55 +00:00
|
|
|
// Create XMLHttpRequest and notifyURL
|
|
|
|
var notificationWatcher = new XMLHttpRequest();
|
2015-12-06 01:52:35 +00:00
|
|
|
var notifyURL = '//' + sakuraVars.urlMain + '/settings.php?request-notifications=true&time=' + Sakura.epoch() + '&session=' + session;
|
2015-05-09 00:56:55 +00:00
|
|
|
|
|
|
|
// Wait for the ready state to change
|
|
|
|
notificationWatcher.onreadystatechange = function() {
|
|
|
|
// Wait for it to reach the "complete" stage
|
|
|
|
if(notificationWatcher.readyState === 4) {
|
|
|
|
// Continue if the HTTP return was 200
|
|
|
|
if(notificationWatcher.status === 200) {
|
|
|
|
// Assign the JSON parsed content to a variable
|
|
|
|
var notifyGet = JSON.parse(notificationWatcher.responseText);
|
|
|
|
|
|
|
|
// If nothing was set stop
|
|
|
|
if(typeof notifyGet == 'undefined') {
|
|
|
|
// Tell the user something went wrong...
|
|
|
|
notifyUI({
|
|
|
|
"title": "An error occurred!",
|
|
|
|
"text": "If this problem persists please report this to the administrator.",
|
|
|
|
"img": "FONT:fa-exclamation-triangle",
|
|
|
|
"timeout": 60000,
|
|
|
|
"sound": false
|
|
|
|
});
|
|
|
|
|
|
|
|
// ...then prevent the function from contiuing
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Go over every return notification and pass the object to it
|
2015-05-25 18:18:56 +00:00
|
|
|
for(var notifyID in notifyGet) {
|
2015-05-09 00:56:55 +00:00
|
|
|
notifyUI(notifyGet[notifyID]);
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
2015-10-19 21:25:20 +00:00
|
|
|
} else if((notificationWatcher.status + '').substring(0, 1) == '5') {
|
2015-05-09 00:56:55 +00:00
|
|
|
// ELse tell the user there was an internal server error...
|
|
|
|
notifyUI({
|
|
|
|
"title": "An internal server error occurred!",
|
|
|
|
"text": "If this problem persists please report this to the administrator.",
|
|
|
|
"img": "FONT:fa-chain-broken",
|
|
|
|
"timeout": 60000,
|
|
|
|
"sound": false
|
|
|
|
});
|
2015-04-12 13:33:59 +00:00
|
|
|
}
|
|
|
|
}
|
2015-05-25 18:18:56 +00:00
|
|
|
};
|
2015-05-09 00:56:55 +00:00
|
|
|
|
|
|
|
// Make the request
|
|
|
|
notificationWatcher.open('GET', notifyURL, true);
|
|
|
|
notificationWatcher.send();
|
|
|
|
}
|
2015-04-12 13:33:59 +00:00
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// Show the full-page busy window
|
2015-04-20 19:39:49 +00:00
|
|
|
function ajaxBusyView(show, message, type) {
|
2015-05-05 03:47:58 +00:00
|
|
|
// Get elements
|
2015-04-20 19:39:49 +00:00
|
|
|
var busyCont = document.getElementById('ajaxBusy');
|
|
|
|
var busyStat = document.getElementById('ajaxStatus');
|
|
|
|
var busyAnim = document.getElementById('ajaxAnimate');
|
|
|
|
var pageContent = document.getElementById('contentwrapper');
|
2015-05-25 18:18:56 +00:00
|
|
|
var busyAnimIco;
|
2015-04-20 19:39:49 +00:00
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// Select the proper icon
|
2015-04-20 19:39:49 +00:00
|
|
|
switch(type) {
|
|
|
|
case 'ok':
|
2015-05-25 18:18:56 +00:00
|
|
|
busyAnimIco = 'fa fa-check fa-4x';
|
2015-04-20 19:39:49 +00:00
|
|
|
break;
|
|
|
|
case 'fail':
|
2015-05-25 18:18:56 +00:00
|
|
|
busyAnimIco = 'fa fa-remove fa-4x';
|
|
|
|
break;
|
|
|
|
case 'busy':
|
|
|
|
default:
|
|
|
|
busyAnimIco = 'fa fa-refresh fa-spin fa-4x';
|
2015-04-20 19:39:49 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// If requested to show the window build it
|
2015-04-20 19:39:49 +00:00
|
|
|
if(show) {
|
2015-05-05 03:47:58 +00:00
|
|
|
// Make sure it doesn't exist already
|
2015-05-25 18:18:56 +00:00
|
|
|
if(busyCont === null) {
|
2015-05-05 03:47:58 +00:00
|
|
|
// Container
|
2015-04-20 19:39:49 +00:00
|
|
|
var createBusyCont = document.createElement('div');
|
|
|
|
createBusyCont.className = 'ajax-busy';
|
|
|
|
createBusyCont.setAttribute('id', 'ajaxBusy');
|
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// Inner box
|
2015-04-20 19:39:49 +00:00
|
|
|
var createBusyInner = document.createElement('div');
|
|
|
|
createBusyInner.className = 'ajax-inner';
|
|
|
|
createBusyCont.appendChild(createBusyInner);
|
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// Action description
|
2015-04-20 19:39:49 +00:00
|
|
|
var createBusyMsg = document.createElement('h2');
|
|
|
|
createBusyMsg.setAttribute('id', 'ajaxStatus');
|
|
|
|
createBusyInner.appendChild(createBusyMsg);
|
2015-04-12 13:33:59 +00:00
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// FontAwesome icon
|
2015-04-20 19:39:49 +00:00
|
|
|
var createBusySpin = document.createElement('div');
|
|
|
|
createBusySpin.setAttribute('id', 'ajaxAnimate');
|
|
|
|
createBusyInner.appendChild(createBusySpin);
|
2015-04-12 13:33:59 +00:00
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// Append the element to the actual page
|
2015-04-20 19:39:49 +00:00
|
|
|
pageContent.appendChild(createBusyCont);
|
2015-05-05 03:47:58 +00:00
|
|
|
|
|
|
|
// Reassign the previously assigned variables
|
2015-04-20 19:39:49 +00:00
|
|
|
busyCont = document.getElementById('ajaxBusy');
|
|
|
|
busyStat = document.getElementById('ajaxStatus');
|
|
|
|
busyAnim = document.getElementById('ajaxAnimate');
|
2015-05-05 03:47:58 +00:00
|
|
|
} // If the container already exists just continue and update the elements
|
|
|
|
|
|
|
|
// Alter the icon
|
2015-04-20 19:39:49 +00:00
|
|
|
busyAnim.className = busyAnimIco;
|
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// Change the message
|
2015-05-25 18:18:56 +00:00
|
|
|
busyStat.innerHTML = (message === null ? 'Unknown' : message);
|
2015-05-05 03:47:58 +00:00
|
|
|
} else { // If show is false remove the element...
|
|
|
|
// ...but just do nothing if the container doesn't exist
|
2015-05-25 18:18:56 +00:00
|
|
|
if(busyCont !== null) {
|
2015-05-05 03:47:58 +00:00
|
|
|
// Create the fadeout with a 10ms interval
|
2015-04-20 19:39:49 +00:00
|
|
|
var fadeOut = setInterval(function() {
|
2015-05-05 03:47:58 +00:00
|
|
|
// Set an opacity if it doesn't exist yet
|
2015-05-25 18:18:56 +00:00
|
|
|
if(busyCont.style.opacity === null || busyCont.style.opacity === "") {
|
2015-04-20 19:39:49 +00:00
|
|
|
busyCont.style.opacity = 1;
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// If the value isn't 0 yet start subtract .1 from the opacity
|
2015-04-20 19:39:49 +00:00
|
|
|
if(busyCont.style.opacity > 0) {
|
2015-05-25 18:18:56 +00:00
|
|
|
busyCont.style.opacity = busyCont.style.opacity - 0.1;
|
2015-05-05 03:47:58 +00:00
|
|
|
} else { // When we've reached 0 remove the container element and clear the fadeout interval
|
2015-12-06 01:52:35 +00:00
|
|
|
Sakura.removeId('ajaxBusy');
|
2015-04-20 19:39:49 +00:00
|
|
|
clearInterval(fadeOut);
|
|
|
|
}
|
|
|
|
}, 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// Making a post request using AJAX
|
2015-09-16 20:34:36 +00:00
|
|
|
function ajaxPost(url, data, callback) {
|
2015-05-05 03:47:58 +00:00
|
|
|
// Combine name and value with an = inbetween
|
2015-04-20 19:39:49 +00:00
|
|
|
var query = [];
|
2015-05-25 18:18:56 +00:00
|
|
|
for(var i in data) {
|
2015-04-20 19:39:49 +00:00
|
|
|
query.push(encodeURIComponent(i) +"="+ encodeURIComponent(data[i]));
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
|
|
|
|
2015-09-16 20:34:36 +00:00
|
|
|
// Join the array
|
|
|
|
query = query.join("&");
|
|
|
|
|
|
|
|
// Create XMLHttpRequest
|
|
|
|
var request = new XMLHttpRequest();
|
|
|
|
|
|
|
|
// Open a post request
|
|
|
|
request.open('POST', url, true);
|
|
|
|
|
|
|
|
// Wait for the readiness to change
|
|
|
|
request.onreadystatechange = function() {
|
|
|
|
// Wait for completion
|
|
|
|
if(request.readyState === 4) {
|
|
|
|
if(request.status === 200) {
|
|
|
|
callback.call(request.responseText);
|
|
|
|
} else {
|
|
|
|
ajaxBusyView(false);
|
|
|
|
|
|
|
|
notifyUI({
|
|
|
|
"title": "An internal server error occurred!",
|
|
|
|
"text": "If this problem persists please report this to the administrator.",
|
|
|
|
"img": "FONT:fa-chain-broken",
|
|
|
|
"timeout": 60000,
|
|
|
|
"sound": false
|
|
|
|
});
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2015-10-18 19:06:30 +00:00
|
|
|
};
|
2015-09-16 20:34:36 +00:00
|
|
|
|
|
|
|
// Set headers
|
|
|
|
request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
2015-04-20 19:39:49 +00:00
|
|
|
|
2015-09-16 20:34:36 +00:00
|
|
|
// Submit the request
|
|
|
|
request.send(query);
|
2015-04-20 19:39:49 +00:00
|
|
|
}
|
|
|
|
|
2015-08-10 15:52:15 +00:00
|
|
|
// Convert href attribute to an object
|
|
|
|
function prepareAjaxLink(linkId, callback, attrs) {
|
|
|
|
// Get the elements
|
|
|
|
var link = typeof linkId === 'object' ? linkId : document.getElementById(linkId);
|
|
|
|
|
|
|
|
// Catch null
|
|
|
|
if(link == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the href value
|
|
|
|
var hrefRaw = link.attributes.href.value;
|
|
|
|
|
|
|
|
// Get the action path
|
|
|
|
var action = hrefRaw.split('?')[0];
|
|
|
|
|
|
|
|
// Split the request variables
|
|
|
|
var variablesNotSplit = hrefRaw.split('?')[1].split('&');
|
|
|
|
|
|
|
|
// Create variables object
|
|
|
|
var variables = {};
|
|
|
|
|
|
|
|
// Split the name and values of the variables
|
|
|
|
for(var key in variablesNotSplit) {
|
|
|
|
// Split name and value
|
|
|
|
var newVar = variablesNotSplit[key].split('=');
|
|
|
|
|
|
|
|
// Push it into the object
|
|
|
|
variables[newVar[0]] = newVar[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add ajax=true
|
|
|
|
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 : '') +');');
|
|
|
|
}
|
|
|
|
|
2015-09-16 20:34:36 +00:00
|
|
|
function prepareAjaxForm(formId, message, resetCaptchaOnFailure) {
|
|
|
|
// Get the form
|
|
|
|
var form = document.getElementById(formId);
|
|
|
|
|
|
|
|
// Create the AJAX form input
|
|
|
|
var createHidden = document.createElement('input');
|
|
|
|
|
|
|
|
// Set the attributes
|
|
|
|
createHidden.setAttribute('name', 'ajax');
|
|
|
|
createHidden.setAttribute('value', 'true');
|
|
|
|
createHidden.setAttribute('type', 'hidden');
|
|
|
|
form.appendChild(createHidden);
|
|
|
|
|
|
|
|
// Update form
|
|
|
|
form.setAttribute('onsubmit', 'submitPost(\''+ form.action +'\', formToObject(\''+ formId +'\'), true, \''+ (message ? message : 'Please wait...') +'\', '+ (resetCaptchaOnFailure ? 'true' : 'false') +');');
|
|
|
|
form.setAttribute('action', 'javascript:void(0);');
|
|
|
|
}
|
|
|
|
|
2015-08-10 15:52:15 +00:00
|
|
|
// Convert form to an object
|
|
|
|
function formToObject(formId) {
|
|
|
|
// Get form data
|
|
|
|
var form = document.getElementById(formId);
|
|
|
|
|
|
|
|
// Make an object for the request parts
|
2015-10-18 19:06:30 +00:00
|
|
|
var requestParts = {};
|
2015-08-10 15:52:15 +00:00
|
|
|
|
|
|
|
// Get all children with a name attribute
|
|
|
|
var children = form.querySelectorAll('[name]');
|
|
|
|
|
|
|
|
// Sort children and make them ready for submission
|
|
|
|
for(var i in children) {
|
|
|
|
if(typeof children[i] == 'object') {
|
2015-08-23 22:08:36 +00:00
|
|
|
requestParts[children[i].name] = ((typeof children[i].type !== "undefined" && children[i].type.toLowerCase() == "checkbox") ? (children[i].checked ? 1 : 0) : children[i].value);
|
2015-08-10 15:52:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the object
|
|
|
|
return requestParts;
|
|
|
|
}
|
|
|
|
|
2015-04-20 19:39:49 +00:00
|
|
|
// Quickly building a form for god knows what reason
|
|
|
|
function generateForm(formId, formAttr, formData, appendTo) {
|
|
|
|
// Create form elements and assign ID
|
2015-05-25 18:18:56 +00:00
|
|
|
var i;
|
2015-04-20 19:39:49 +00:00
|
|
|
var form = document.createElement('form');
|
|
|
|
form.setAttribute('id', formId);
|
|
|
|
|
|
|
|
// Set additional attributes
|
2015-05-25 18:18:56 +00:00
|
|
|
if(formAttr !== null) {
|
|
|
|
for(i in formAttr) {
|
2015-04-20 19:39:49 +00:00
|
|
|
form.setAttribute(i, formAttr[i]);
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
2015-04-20 19:39:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Generate input elements
|
2015-05-25 18:18:56 +00:00
|
|
|
for(i in formData) {
|
2015-04-20 19:39:49 +00:00
|
|
|
var disposableVar = document.createElement('input');
|
|
|
|
disposableVar.setAttribute('type', 'hidden');
|
|
|
|
disposableVar.setAttribute('name', i);
|
|
|
|
disposableVar.setAttribute('value', formData[i]);
|
|
|
|
form.appendChild(disposableVar);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append to another element if requested
|
2015-05-25 18:18:56 +00:00
|
|
|
if(appendTo !== null) {
|
2015-04-20 19:39:49 +00:00
|
|
|
document.getElementById(appendTo).appendChild(form);
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
|
|
|
|
2015-04-20 19:39:49 +00:00
|
|
|
// Return the completed form
|
|
|
|
return form;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Submitting a form using an AJAX POST request
|
2015-08-10 15:52:15 +00:00
|
|
|
function submitPost(action, requestParts, busyView, msg, resetCaptchaOnFailure) {
|
2015-04-20 19:39:49 +00:00
|
|
|
// If requested display the busy thing
|
2015-05-25 18:18:56 +00:00
|
|
|
if(busyView) {
|
2015-04-20 19:39:49 +00:00
|
|
|
ajaxBusyView(true, msg, 'busy');
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
|
|
|
|
2015-04-20 19:39:49 +00:00
|
|
|
// Submit the AJAX request
|
2015-09-16 20:34:36 +00:00
|
|
|
var request = ajaxPost(action, requestParts, function() {
|
|
|
|
submitPostHandler(this, busyView, resetCaptchaOnFailure);
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Submitting a form using an AJAX POST request
|
|
|
|
function submitPostHandler(result, busyView, resetCaptchaOnFailure) {
|
|
|
|
|
|
|
|
// Split result
|
|
|
|
result = result.split('|');
|
2015-04-20 19:39:49 +00:00
|
|
|
|
|
|
|
// If using the busy view thing update the text displayed to the return of the request
|
2015-05-25 18:18:56 +00:00
|
|
|
if(busyView) {
|
2015-09-16 20:34:36 +00:00
|
|
|
ajaxBusyView(true, result[0], (result[1] == '1' ? 'ok' : 'fail'));
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If request reset the recaptcha on failure
|
2015-09-23 20:45:42 +00:00
|
|
|
if(resetCaptchaOnFailure && result[1] != '1' && sakuraVars.recaptchaEnabled != '0') {
|
2015-05-25 18:18:56 +00:00
|
|
|
grecaptcha.reset();
|
|
|
|
}
|
|
|
|
|
2015-04-20 19:39:49 +00:00
|
|
|
setTimeout(function(){
|
2015-05-25 18:18:56 +00:00
|
|
|
if(busyView) {
|
2015-04-20 19:39:49 +00:00
|
|
|
ajaxBusyView(false);
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
|
|
|
|
2015-09-16 20:34:36 +00:00
|
|
|
if(result[1] == '1') {
|
|
|
|
window.location = result[2];
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
2015-08-20 23:17:27 +00:00
|
|
|
}, 2000);
|
2015-04-20 19:39:49 +00:00
|
|
|
|
2015-04-12 13:33:59 +00:00
|
|
|
}
|
2015-05-05 03:47:58 +00:00
|
|
|
|
2015-05-25 18:18:56 +00:00
|
|
|
// Check if password is within the minimum entropy value
|
|
|
|
function checkPwdEntropy(pwd) {
|
2015-12-06 01:52:35 +00:00
|
|
|
return (Sakura.pwdEntropy(pwd) >= sakuraVars.minPwdEntropy);
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check registration variables
|
|
|
|
function registerVarCheck(id, mode, option) {
|
|
|
|
// Get the element we're working with
|
|
|
|
var input = document.getElementById(id);
|
|
|
|
var check = null;
|
|
|
|
|
|
|
|
// Use the proper mode
|
|
|
|
switch(mode) {
|
|
|
|
case 'confirmpw':
|
|
|
|
option = document.getElementById(option);
|
|
|
|
check = input.value === option.value;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'password':
|
|
|
|
check = checkPwdEntropy(input.value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'email':
|
2015-12-06 01:52:35 +00:00
|
|
|
check = Sakura.validateEmail(input.value);
|
2015-05-25 18:18:56 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'username':
|
|
|
|
default:
|
2015-12-06 01:52:35 +00:00
|
|
|
check = Sakura.stringLength(input.value, sakuraVars.minUserLen, sakuraVars.maxUserLen);
|
2015-05-25 18:18:56 +00:00
|
|
|
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', '');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// 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%
|
2015-05-25 18:18:56 +00:00
|
|
|
if(position < 0 || position > 100) {
|
2015-05-05 03:47:58 +00:00
|
|
|
position = 0;
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// Do the first maths
|
|
|
|
position = (position / (dir ? 25 : 20)) - 2.5;
|
|
|
|
|
|
|
|
// If the negative flag is set inverse the number
|
2015-05-25 18:18:56 +00:00
|
|
|
if(neg) {
|
2015-05-05 03:47:58 +00:00
|
|
|
position = -position;
|
2015-05-25 18:18:56 +00:00
|
|
|
}
|
|
|
|
|
2015-05-05 03:47:58 +00:00
|
|
|
// Subtract another 2.5 to make the element not go all over the place
|
2015-08-20 23:17:27 +00:00
|
|
|
position = position - 2.5;
|
2015-05-05 03:47:58 +00:00
|
|
|
|
|
|
|
// Return the proper position value
|
|
|
|
return position;
|
|
|
|
}
|
2015-05-24 22:06:53 +00:00
|
|
|
|
|
|
|
// Smooth scrolling
|
2015-05-25 18:18:56 +00:00
|
|
|
function scrollToTop() {
|
2015-05-24 22:06:53 +00:00
|
|
|
// Get the current position
|
2015-05-25 18:18:56 +00:00
|
|
|
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);
|
|
|
|
}
|
2015-05-24 22:06:53 +00:00
|
|
|
}
|
|
|
|
|
2015-09-26 16:12:42 +00:00
|
|
|
function replaceTag(tag) {
|
|
|
|
return {'&': '&', '<': '<', '>': '>'}[tag] || tag;
|
|
|
|
}
|
|
|
|
|
|
|
|
function safeTagsReplace(str) {
|
|
|
|
return str.replace(/[&<>]/g, replaceTag);
|
|
|
|
}
|
|
|
|
|
2015-10-06 19:51:07 +00:00
|
|
|
function commentReply(id, session, category, action, avatar) {
|
|
|
|
// Find subject post
|
|
|
|
var replyingTo = document.getElementById('comment-' + id);
|
|
|
|
|
|
|
|
// Check if it actually exists
|
|
|
|
if(typeof replyingTo === 'undefined') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-10-10 15:51:24 +00:00
|
|
|
// Attempt to get previously created box
|
|
|
|
var replyBox = document.getElementById('comment-reply-container-' + id);
|
|
|
|
|
|
|
|
// Remove it if it already exists
|
|
|
|
if(replyBox) {
|
2015-12-06 01:52:35 +00:00
|
|
|
Sakura.removeId('comment-reply-container-' + id);
|
2015-10-10 15:51:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-10-06 19:51:07 +00:00
|
|
|
// Container
|
|
|
|
var replyContainer = document.createElement('li');
|
2015-10-10 15:51:24 +00:00
|
|
|
replyContainer.id = 'comment-reply-container-' + id;
|
2015-10-06 19:51:07 +00:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
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 = 'background-image: 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
|
2015-10-10 15:51:24 +00:00
|
|
|
if(replyingTo.children[1].children.length > 0) {
|
|
|
|
replyingTo.children[1].insertBefore(replyContainer, replyingTo.children[1].firstChild);
|
|
|
|
} else {
|
|
|
|
replyingTo.children[1].appendChild(replyContainer);
|
|
|
|
}
|
2015-10-06 19:51:07 +00:00
|
|
|
|
|
|
|
// Prepare AJAX submission
|
|
|
|
prepareAjaxForm(replyForm.id, 'Replying...');
|
|
|
|
}
|
|
|
|
|
2015-12-03 18:41:14 +00:00
|
|
|
// Inserting text into text box
|
|
|
|
// Borrowed from http://stackoverflow.com/questions/1064089/inserting-a-text-where-cursor-is-using-javascript-jquery
|
|
|
|
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) {
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-01 17:20:20 +00:00
|
|
|
// Formatting money
|
2015-11-01 16:32:47 +00:00
|
|
|
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) : "");
|
2015-10-06 19:51:07 +00:00
|
|
|
};
|