2015-04-12 13:33:59 +00:00
/ *
2015-12-09 20:21:08 +00:00
* Sakura Yuuno
2015-04-12 13:33:59 +00:00
* /
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-04-12 13:33:59 +00:00
}
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 ) {
2015-09-10 21:19:51 +00:00
// Check if the document isn't hidden
2015-12-09 20:21:08 +00:00
if ( document . hidden ) {
2015-09-10 21:19:51 +00:00
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
2015-12-06 22:13:29 +00:00
return ;
}
2015-12-09 20:21:08 +00:00
// Create an object for every notification
2015-12-06 22:13:29 +00:00
for ( var id in data ) {
notifyUI ( data [ id ] ) ;
2015-04-12 13:33:59 +00:00
}
2015-12-06 22:13:29 +00:00
} ) ;
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
2015-04-20 19:39:49 +00:00
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 ) {
2015-04-20 19:39:49 +00:00
case 'ok' :
2015-12-09 20:21:08 +00:00
icon += 'fa-check' ;
2015-04-20 19:39:49 +00:00
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' ;
2015-04-20 19:39:49 +00:00
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 ) ;
2015-04-20 19:39:49 +00:00
}
} , 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-12-06 22:13:29 +00:00
// 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 ( ) ) ;
2015-12-06 22:13:29 +00:00
} ) ;
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-04-20 19:39:49 +00:00
}
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
2015-04-20 19:39:49 +00:00
function generateForm ( formId , formAttr , formData , appendTo ) {
2015-12-09 20:21:08 +00:00
if ( appendTo === void 0 ) { appendTo = null ; }
// Create form element
2015-04-20 19:39:49 +00:00
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-04-20 19:39:49 +00:00
}
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 ) {
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 form ;
}
2015-12-09 20:21:08 +00:00
// Submitting a post using AJAX
function submitPost ( action , requestParts , busyView , msg , resetCaptcha ) {
2015-04-20 19:39:49 +00:00
// If requested display the busy thing
2015-12-09 20:21:08 +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-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 ) {
2015-04-20 19:39:49 +00:00
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-04-12 13:33:59 +00:00
}
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 ) ;
2015-12-16 22:54:36 +00:00
check = input . value === option . value ;
2015-05-25 18:18:56 +00:00
break ;
case 'password' :
2015-12-16 22:54:36 +00:00
check = checkPwdEntropy ( input . value ) ;
2015-05-25 18:18:56 +00:00
break ;
case 'email' :
2015-12-16 22:54:36 +00:00
check = Sakura . validateEmail ( input . value ) ;
2015-05-25 18:18:56 +00:00
break ;
case 'username' :
default :
2015-12-16 22:54:36 +00:00
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
2015-09-26 16:12:42 +00:00
function replaceTag ( tag ) {
2015-12-09 20:21:08 +00:00
return { '&' : '&' , '<' : '<' , '>' : '>' } [ tag ] || tag ;
2015-09-26 16:12:42 +00:00
}
2015-12-09 20:21:08 +00:00
// ^
2015-09-26 16:12:42 +00:00
function safeTagsReplace ( str ) {
return str . replace ( /[&<>]/g , replaceTag ) ;
}
2015-12-03 18:41:14 +00:00
// 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)
2015-12-03 18:41:14 +00:00
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 ;
2015-12-03 18:41:14 +00:00
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 ; }
2015-12-03 18:41:14 +00:00
var element = document . getElementById ( textarea ) ;
var before = "[" + tag + ( arg ? "=" : "" ) + "]" ;
2015-12-09 20:21:08 +00:00
var after = "[/" + tag + "]" ;
2015-12-03 18:41:14 +00:00
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 ) {
2015-12-03 18:41:14 +00:00
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 {
2015-12-03 18:41:14 +00:00
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 ;
2015-11-01 16:32:47 +00:00
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
} ;