This repository has been archived on 2024-06-26. You can view files and clone it, but cannot push or open issues or pull requests.
sakura/public/content/data/yuuno/js/yuuno.js

522 lines
18 KiB
JavaScript
Raw Normal View History

/*
2015-12-09 20:21:08 +00:00
* Sakura Yuuno
*/
2015-12-09 20:21:08 +00:00
// Spawns a notification
2015-05-09 00:56:55 +00:00
function notifyUI(content) {
// Grab the container and create an ID
2015-12-09 20:21:08 +00:00
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
2016-03-26 16:36:58 +00:00
if ((typeof content.image).toLowerCase() === 'undefined' || content.image == null || content.image.length < 2) {
2015-12-09 20:21:08 +00:00
aIconCont = document.createElement('div');
aIconCont.className = 'font-icon fa fa-info fa-4x';
}
2016-03-26 16:36:58 +00:00
else if (content.image.substr(0, 5) == 'FONT:') {
2015-12-09 20:21:08 +00:00
aIconCont = document.createElement('div');
2016-03-26 16:36:58 +00:00
aIconCont.className = 'font-icon fa ' + content.image.replace('FONT:', '') + ' fa-4x';
2015-12-09 20:21:08 +00:00
}
else {
aIconCont = document.createElement('img');
aIconCont.alt = id;
2016-03-26 16:36:58 +00:00
aIconCont.src = content.image;
2015-12-09 20:21:08 +00:00
}
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);
// 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);
2015-05-09 00:56:55 +00:00
}, content.timeout);
}
2015-05-09 00:56:55 +00:00
}
2015-12-09 20:21:08 +00:00
// Closing a notification
2015-05-09 00:56:55 +00:00
function notifyClose(id) {
2015-12-09 20:21:08 +00:00
// Get the element
var e = document.getElementById(id);
// Add the animation
e.className = 'notification-exit';
// Remove after 410 ms
setTimeout(function () {
2015-12-06 16:10:24 +00:00
Sakura.removeById(id);
2015-05-09 00:56:55 +00:00
}, 410);
}
2015-12-09 20:21:08 +00:00
// Opening an alerted link
2015-05-09 00:56:55 +00:00
function notifyOpen(id) {
var sakuraHref = document.getElementById(id).getAttribute('sakurahref');
2015-12-09 20:21:08 +00:00
if ((typeof sakuraHref).toLowerCase() !== 'undefined') {
window.location.assign(sakuraHref);
2015-05-25 18:18:56 +00:00
}
2015-05-09 00:56:55 +00:00
}
// Request notifications
function notifyRequest(session) {
// Check if the document isn't hidden
2015-12-09 20:21:08 +00:00
if (document.hidden) {
return;
}
2015-12-09 20:21:08 +00:00
// Create AJAX object
var get = new AJAX();
2016-03-26 16:36:58 +00:00
get.setUrl('/notifications');
2015-12-09 20:21:08 +00:00
// 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;
}
2015-12-09 20:21:08 +00:00
// Create an object for every notification
for (var id in data) {
notifyUI(data[id]);
}
});
2015-12-09 20:21:08 +00:00
get.start(HTTPMethods.GET);
2015-05-09 00:56:55 +00:00
}
2015-12-09 20:21:08 +00:00
// Show the full page busy window
function ajaxBusyView(show, message, type) {
2015-12-09 20:21:08 +00:00
if (message === void 0) { message = null; }
if (type === void 0) { type = null; }
2015-05-05 03:47:58 +00:00
// Get elements
2015-12-09 20:21:08 +00:00
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 ';
2015-05-05 03:47:58 +00:00
// Select the proper icon
2015-12-09 20:21:08 +00:00
switch (type) {
case 'ok':
2015-12-09 20:21:08 +00:00
icon += 'fa-check';
break;
case 'fail':
2015-12-09 20:21:08 +00:00
icon += 'fa-remove';
2015-05-25 18:18:56 +00:00
break;
case 'busy':
default:
2015-12-09 20:21:08 +00:00
icon += 'fa-refresh fa-spin';
break;
}
2015-12-09 20:21:08 +00:00
// If request to show the window, build it
if (show) {
if ((typeof cont).toLowerCase() === 'undefined' || cont === null) {
2015-05-05 03:47:58 +00:00
// Container
2015-12-09 20:21:08 +00:00
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";
2015-05-25 18:18:56 +00:00
}
2015-12-09 20:21:08 +00:00
// 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 {
2015-12-06 16:10:24 +00:00
Sakura.removeById('ajaxBusy');
2015-12-09 20:21:08 +00:00
clearInterval(out);
}
}, 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) {
// Create AJAX
var request = new AJAX();
// Set url
request.setUrl(url);
// Add callbacks
request.addCallback(200, function () {
2015-12-09 20:21:08 +00:00
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);
2015-12-09 20:21:08 +00:00
// Return the AJAX object
return request;
}
2015-12-09 20:21:08 +00:00
// Convert a href attr to an object
2015-08-10 15:52:15 +00:00
function prepareAjaxLink(linkId, callback, attrs) {
2015-12-09 20:21:08 +00:00
if (attrs === void 0) { attrs = null; }
// Get element
var link = (typeof linkId).toLowerCase() === 'object' ? linkId : document.getElementById(linkId);
2015-08-10 15:52:15 +00:00
// Catch null
2015-12-09 20:21:08 +00:00
if (link === null) {
2015-08-10 15:52:15 +00:00
return;
}
2015-12-09 20:21:08 +00:00
// Get the raw HREF value
var href = link.getAttribute('href');
// Get the action
var action = href.split('?')[0];
2015-08-10 15:52:15 +00:00
// Split the request variables
2015-12-09 20:21:08 +00:00
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
2015-08-10 15:52:15 +00:00
variables[newVar[0]] = newVar[1];
}
// Add ajax=true
variables['ajax'] = true;
// Update link attributes
2015-12-09 20:21:08 +00:00
link.setAttribute('href', 'javascript:void(0);');
link.setAttribute('onclick', callback + '(\'' + action + '\', JSON.parse(\'' + JSON.stringify(variables) + '\')' + (typeof attrs != 'undefined' ? attrs : '') + ');');
2015-08-10 15:52:15 +00:00
}
2015-12-09 20:21:08 +00:00
// Prepare a form for an AJAX request
function prepareAjaxForm(formId, message, resetCaptcha) {
if (resetCaptcha === void 0) { resetCaptcha = false; }
2015-09-16 20:34:36 +00:00
// Get the form
var form = document.getElementById(formId);
2015-12-09 20:21:08 +00:00
// Create hidden ajax input
var hide = document.createElement('input');
2015-09-16 20:34:36 +00:00
// Set the attributes
2015-12-09 20:21:08 +00:00
hide.name = 'ajax';
hide.value = 'true';
hide.type = 'hidden';
form.appendChild(hide);
2015-09-16 20:34:36 +00:00
// Update form
2015-12-09 20:21:08 +00:00
form.setAttribute('onsubmit', 'submitPost(\'' + form.getAttribute('action') + '\', formToObject(\'' + formId + '\'), true, \'' + (message ? message : 'Please wait...') + '\', ' + (resetCaptcha ? 'true' : 'false') + ');');
2015-09-16 20:34:36 +00:00
form.setAttribute('action', 'javascript:void(0);');
}
2015-08-10 15:52:15 +00:00
// Convert form to an object
function formToObject(formId) {
2015-12-09 20:21:08 +00:00
// Get the form
2015-08-10 15:52:15 +00:00
var form = document.getElementById(formId);
// Make an object for the request parts
2015-12-09 20:21:08 +00:00
var requestParts = new Object();
// Get all the children with a name attr
2015-08-10 15:52:15 +00:00
var children = form.querySelectorAll('[name]');
2015-12-09 20:21:08 +00:00
// Sort the children and make them ready for submission
for (var i in children) {
if ((typeof children[i]).toLowerCase() === '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
}
}
2015-12-09 20:21:08 +00:00
// Return the request parts
2015-08-10 15:52:15 +00:00
return requestParts;
}
2015-12-09 20:21:08 +00:00
// Quickly building a form
function generateForm(formId, formAttr, formData, appendTo) {
2015-12-09 20:21:08 +00:00
if (appendTo === void 0) { appendTo = null; }
// Create form element
var form = document.createElement('form');
2015-12-09 20:21:08 +00:00
form.id = formId;
// Set additional attrs
for (var c in formAttr) {
form.setAttribute(c, formAttr[c]);
}
2015-12-09 20:21:08 +00:00
// 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);
2015-05-25 18:18:56 +00:00
}
return form;
}
2015-12-09 20:21:08 +00:00
// Submitting a post using AJAX
function submitPost(action, requestParts, busyView, msg, resetCaptcha) {
// If requested display the busy thing
2015-12-09 20:21:08 +00:00
if (busyView) {
ajaxBusyView(true, msg, 'busy');
2015-05-25 18:18:56 +00:00
}
2015-12-09 20:21:08 +00:00
// Submit the AJAX
var request = ajaxPost(action, requestParts, function () {
submitPostHandler(request.response(), busyView, resetCaptcha);
2015-09-16 20:34:36 +00:00
});
}
2015-12-09 20:21:08 +00:00
// Handling a submitted form using AJAX
function submitPostHandler(data, busyView, resetCaptcha) {
// Split the result
var result = data.split('|');
// If using the bust view thing update the text displayed to the return of the request
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
}
2015-12-09 20:21:08 +00:00
// Reset captcha
if (resetCaptcha && result[1] != '1' && sakuraVars.recaptchaEnabled != '0') {
2015-05-25 18:18:56 +00:00
grecaptcha.reset();
}
2015-12-09 20:21:08 +00:00
setTimeout(function () {
if (busyView) {
ajaxBusyView(false);
2015-05-25 18:18:56 +00:00
}
2015-12-09 20:21:08 +00:00
if (result[1] == '1') {
window.location.assign(result[2]);
2015-05-25 18:18:56 +00:00
}
2015-08-20 23:17:27 +00:00
}, 2000);
}
2015-12-09 20:21:08 +00:00
// Check if a password is within the minimum entropy value
2015-05-25 18:18:56 +00:00
function checkPwdEntropy(pwd) {
2015-12-09 20:21:08 +00:00
return (Sakura.entropy(pwd) >= sakuraVars.minPwdEntropy);
2015-05-25 18:18:56 +00:00
}
// Check registration variables
function registerVarCheck(id, mode, option) {
2015-12-09 20:21:08 +00:00
if (option === void 0) { option = null; }
2015-05-25 18:18:56 +00:00
// Get the element we're working with
var input = document.getElementById(id);
var check = null;
// Use the proper mode
2015-12-09 20:21:08 +00:00
switch (mode) {
2015-05-25 18:18:56 +00:00
case 'confirmpw':
option = document.getElementById(option);
check = input.value === option.value;
2015-05-25 18:18:56 +00:00
break;
case 'password':
check = checkPwdEntropy(input.value);
2015-05-25 18:18:56 +00:00
break;
case 'email':
check = Sakura.validateEmail(input.value);
2015-05-25 18:18:56 +00:00
break;
case 'username':
default:
check = Sakura.stringLength(input.value, sakuraVars.minUserLen, sakuraVars.maxUserLen);
2015-05-25 18:18:56 +00:00
break;
}
2015-12-09 20:21:08 +00:00
if (input.className.indexOf(check ? 'green' : 'red') < 0) {
2015-05-25 18:18:56 +00:00
input.className = input.className + ' ' + (check ? 'green' : 'red');
}
2015-12-09 20:21:08 +00:00
if (input.className.indexOf(check ? 'red' : 'green') > 0) {
2015-05-25 18:18:56 +00:00
input.className = input.className.replace(check ? 'red' : 'green', '');
}
}
2015-12-09 20:21:08 +00:00
// Replace some special tags
function replaceTag(tag) {
2015-12-09 20:21:08 +00:00
return { '&': '&amp;', '<': '&lt;', '>': '&gt;' }[tag] || tag;
}
2015-12-09 20:21:08 +00:00
// ^
function safeTagsReplace(str) {
return str.replace(/[&<>]/g, replaceTag);
}
2015-12-09 20:21:08 +00:00
// 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
2015-12-09 20:21:08 +00:00
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
2015-12-09 20:21:08 +00:00
if (replyBox) {
2015-12-06 16:10:24 +00:00
Sakura.removeById('comment-reply-container-' + id);
2015-12-09 20:21:08 +00:00
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';
2015-12-09 20:21:08 +00:00
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';
2015-12-09 20:21:08 +00:00
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
2015-12-09 20:21:08 +00:00
if (replyingTo.children[1].children.length > 0) {
replyingTo.children[1].insertBefore(replyContainer, replyingTo.children[1].firstChild);
2015-12-09 20:21:08 +00:00
}
else {
replyingTo.children[1].appendChild(replyContainer);
}
// Prepare AJAX submission
prepareAjaxForm(replyForm.id, 'Replying...');
}
// Inserting text into text box
2015-12-09 20:21:08 +00:00
// 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;
}
2015-12-09 20:21:08 +00:00
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) {
2015-12-09 20:21:08 +00:00
if (arg === void 0) { arg = false; }
var element = document.getElementById(textarea);
var before = "[" + tag + (arg ? "=" : "") + "]";
2015-12-09 20:21:08 +00:00
var after = "[/" + tag + "]";
if (document.selection) {
element.focus();
var sel = document.selection.createRange();
sel.text = before + sel.text + after;
element.focus();
2015-12-09 20:21:08 +00:00
}
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;
2015-12-09 20:21:08 +00:00
}
else {
element.value += before + after;
element.focus();
}
}
2015-07-01 17:20:20 +00:00
// Formatting money
2015-12-09 20:21:08 +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) : "");
};