2013-12-30 14:42:36 +00:00
// interface_common.js
// 2013 Lucas Leal, Miguel Freitas
//
// Common interface functions to all pages, modal manipulation, button manipulation etc
// Profile, mentions and hashtag modal
// Post actions: submit, count characters
2015-03-01 08:31:56 +00:00
var window _scrollY = 0 ;
2015-05-23 17:26:23 +00:00
function openModal ( modal ) {
2015-08-20 05:30:07 +00:00
if ( ! modal . classBase ) {
2015-05-23 17:26:23 +00:00
modal . classBase = '.modal-wrapper' ;
2014-01-08 08:47:13 +00:00
2015-08-20 05:30:07 +00:00
window _scrollY = window . pageYOffset ;
$ ( 'body' ) . css ( 'overflow' , 'hidden' ) ;
}
2015-05-23 17:26:23 +00:00
$ ( modal . classBase + ':not(#templates *)' ) . remove ( ) ;
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
modal . self = $ ( '#templates ' + modal . classBase ) . clone ( true )
. addClass ( modal . classAdd ) ;
2015-01-22 14:59:00 +00:00
2015-05-23 17:26:23 +00:00
if ( modal . title )
modal . self . find ( '.modal-header h3' ) . html ( modal . title ) ;
if ( modal . content )
modal . content = modal . self . find ( '.modal-content' )
. append ( modal . content ) ;
else
modal . content = modal . self . find ( '.modal-content' ) ;
2015-01-22 14:59:00 +00:00
2015-05-23 17:26:23 +00:00
modal . self . prependTo ( 'body' ) . fadeIn ( 'fast' ) ;
2015-01-22 14:59:00 +00:00
2015-06-11 22:34:59 +00:00
if ( modal . classBase === '.modal-wrapper' ) {
modal . content . outerHeight ( modal . self . height ( ) - modal . self . find ( '.modal-header' ) . outerHeight ( ) ) ;
var windowHeight = $ ( window ) . height ( ) ;
if ( modal . self . outerHeight ( ) > windowHeight ) {
modal . content . outerHeight ( modal . content . outerHeight ( ) - modal . self . outerHeight ( ) + windowHeight ) ;
modal . self . outerHeight ( windowHeight ) ;
modal . self . css ( 'margin-top' , - windowHeight / 2 ) ;
}
}
2015-05-23 17:26:23 +00:00
return modal ;
}
2015-01-22 14:59:00 +00:00
2015-05-23 17:26:23 +00:00
function closeModal ( ) {
closeModalHandler ( '.modal-wrapper' ) ;
2015-08-20 05:30:07 +00:00
2015-05-23 17:26:23 +00:00
window . location . hash = '#' ;
window . scroll ( window . pageXOffset , window _scrollY ) ;
2015-08-20 05:30:07 +00:00
$ ( 'body' ) . css ( {
'overflow' : 'auto' ,
'margin-right' : '0'
} ) ;
2015-01-22 14:59:00 +00:00
}
2015-09-03 22:21:33 +00:00
function closePrompt ( ) {
closeModalHandler ( '.prompt-wrapper' ) ;
}
2015-05-23 17:26:23 +00:00
function closeModalHandler ( classBase ) {
var modalWindows = $ ( classBase + ':not(#templates *)' ) ;
2015-01-22 14:59:00 +00:00
2015-05-23 17:26:23 +00:00
modalWindows . fadeOut ( 'fast' , function ( ) { modalWindows . remove ( ) ; } ) ;
2015-01-22 14:59:00 +00:00
}
2015-09-03 22:21:33 +00:00
function confirmPopup ( event , req ) {
2015-11-01 21:15:58 +00:00
if ( event && event . stopPropagation )
event . stopPropagation ( ) ;
2015-09-03 22:21:33 +00:00
var modal = openModal ( {
classBase : '.prompt-wrapper' ,
classAdd : 'confirm-popup' ,
content : $ ( '#confirm-popup-template' ) . children ( ) . clone ( true ) ,
title : req . titleTxt
} ) ;
if ( req . messageTxt )
modal . content . find ( '.message' ) . text ( req . messageTxt ) ;
var btn = modal . content . find ( '.confirm' ) ;
2015-11-01 21:15:58 +00:00
if ( req . removeConfirm )
btn . remove ( ) ;
else {
if ( req . confirmTxt )
btn . text ( req . confirmTxt ) ;
else
btn . text ( polyglot . t ( 'Confirm' ) ) ;
if ( req . confirmFunc ) {
btn . on ( 'click' , function ( ) {
closePrompt ( ) ;
req . confirmFunc ( req . confirmFuncArgs ) ;
} ) ;
} else
btn . on ( 'click' , closePrompt ) ;
}
2015-09-03 22:21:33 +00:00
var btn = modal . content . find ( '.cancel' ) ;
2015-11-01 21:15:58 +00:00
if ( req . removeCancel )
btn . remove ( ) ;
else {
if ( req . cancelTxt )
btn . text ( req . cancelTxt ) ;
else
btn . text ( polyglot . t ( 'Cancel' ) ) ;
if ( req . cancelFunc ) {
btn . on ( 'click' , function ( ) {
closePrompt ( ) ;
req . cancelFunc ( req . cancelFuncArgs ) ;
} ) ;
} else
btn . on ( 'click' , closePrompt ) ;
}
var btn = modal . self . find ( '.prompt-close' ) ;
if ( req . removeClose )
btn . remove ( ) ;
else {
if ( req . closeFunc ) {
if ( typeof req . closeFunc === 'string' ) {
if ( req . closeFunc === 'confirmFunc' ) {
req . closeFunc = req . confirmFunc ;
req . closeFuncArgs = req . confirmFuncArgs ;
} else if ( req . closeFunc === 'cancelFunc' ) {
req . closeFunc = req . cancelFunc ;
req . closeFuncArgs = req . cancelFuncArgs ;
}
}
btn . on ( 'click' , function ( ) {
closePrompt ( ) ;
req . closeFunc ( req . closeFuncArgs ) ;
} ) ;
}
}
2015-09-03 22:21:33 +00:00
}
2013-12-30 14:42:36 +00:00
function checkNetworkStatusAndAskRedirect ( cbFunc , cbArg ) {
networkUpdate ( function ( args ) {
2015-05-23 17:26:23 +00:00
if ( ! twisterdConnectedAndUptodate ) {
2015-11-01 23:33:51 +00:00
confirmPopup ( null , {
messageTxt : polyglot . t ( 'switch_to_network' ) ,
confirmFunc : $ . MAL . goNetwork
} ) ;
2015-05-23 17:26:23 +00:00
} else {
if ( args . cbFunc )
args . cbFunc ( args . cbArg ) ;
}
} , { cbFunc : cbFunc , cbArg : cbArg } ) ;
2013-12-30 14:42:36 +00:00
}
function timeGmtToText ( t ) {
var d = new Date ( 0 ) ;
d . setUTCSeconds ( t ) ;
2015-05-23 17:26:23 +00:00
return d . toString ( ) . replace ( /GMT.*/g , '' ) ;
2013-12-30 14:42:36 +00:00
}
2014-01-05 16:29:49 +00:00
function timeSincePost ( t ) {
var d = new Date ( 0 ) ;
d . setUTCSeconds ( t ) ;
var now = new Date ( ) ;
var t _delta = Math . ceil ( ( now - d ) / 1000 ) ;
2015-05-23 17:26:23 +00:00
var expression ;
if ( t _delta < 60 )
expression = polyglot . t ( 'seconds' , t _delta ) ;
else if ( t _delta < 3600 ) // 60 * 60
expression = polyglot . t ( 'minutes' , Math . floor ( t _delta / 60 ) ) ;
else if ( t _delta < 86400 ) // 24 * 60 * 60
expression = polyglot . t ( 'hours' , Math . floor ( t _delta / 3600 ) ) ; // 60 * 60
else
expression = polyglot . t ( 'days' , Math . floor ( t _delta / 86400 ) ) ; // 24 * 60 * 60
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
return polyglot . t ( 'time_ago' , { time : expression } ) ;
2013-12-30 14:42:36 +00:00
}
2015-09-03 22:21:33 +00:00
function openGroupProfileModalWithNameHandler ( groupAlias ) {
var modal = openModal ( {
classAdd : 'profile-modal' ,
content : $ ( '#group-profile-modal-template' ) . children ( ) . clone ( true ) ,
title : polyglot . t ( 'users_profile' , { username : '<span>' + groupAlias + '</span>' } )
} ) ;
modal . content . find ( '.profile-card' ) . attr ( 'data-screen-name' , groupAlias ) ;
groupMsgGetGroupInfo ( groupAlias ,
function ( req , ret ) {
if ( ret ) {
2015-10-23 20:20:41 +00:00
req . modal . content . find ( '.profile-bio .group-description' )
. val ( ret . description )
. attr ( 'val-origin' , ret . description )
;
2015-09-03 22:21:33 +00:00
if ( ret . members . indexOf ( defaultScreenName ) !== - 1 )
req . modal . content . find ( '.group-messages-control' ) . children ( 'button' ) . attr ( 'disabled' , false ) ;
var membersList = req . modal . content . find ( '.members' ) ;
var memberTemplate = $ ( '#group-profile-member-template' ) . children ( ) ;
for ( var i = 0 ; i < ret . members . length ; i ++ ) {
var item = memberTemplate . clone ( true ) . appendTo ( membersList ) ;
item . find ( '.twister-user-info' ) . attr ( 'data-screen-name' , ret . members [ i ] ) ;
item . find ( '.twister-user-name' ) . attr ( 'href' , $ . MAL . userUrl ( ret . members [ i ] ) ) ;
getAvatar ( ret . members [ i ] , item . find ( '.twister-user-photo' ) ) ;
getFullname ( ret . members [ i ] , item . find ( '.twister-user-full' ) ) ;
2015-10-27 16:31:04 +00:00
getBioToElem ( ret . members [ i ] , item . find ( '.bio' ) ) ;
2015-09-03 22:21:33 +00:00
}
2015-10-21 21:05:18 +00:00
elemFitNextIntoParentHeight ( req . modal . content . find ( '.profile-card' ) ) ;
2015-09-03 22:21:33 +00:00
}
} , { modal : modal }
) ;
2015-10-21 21:05:18 +00:00
elemFitNextIntoParentHeight ( modal . content . find ( '.profile-card' ) ) ;
2015-09-03 22:21:33 +00:00
}
function openUserProfileModalWithNameHandler ( username ) {
2015-05-23 17:26:23 +00:00
var content = $ ( '#profile-modal-template' ) . children ( ) . clone ( true ) ;
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
updateProfileData ( content , username ) ;
// FIXME following ctc could be part of updateProfileData() when mobile will be ready for this
content . find ( '.tox-ctc' ) . attr ( 'title' , polyglot . t ( 'Copy to clipboard' ) ) ;
content . find ( '.bitmessage-ctc' ) . attr ( 'title' , polyglot . t ( 'Copy to clipboard' ) ) ;
2013-12-30 14:42:36 +00:00
2015-06-11 22:34:59 +00:00
var modal = openModal ( {
2015-05-23 17:26:23 +00:00
classAdd : 'profile-modal' ,
content : content ,
title : polyglot . t ( 'users_profile' , { username : username } )
2015-06-11 22:34:59 +00:00
} ) ;
2014-10-16 08:47:08 +00:00
2015-05-23 17:26:23 +00:00
// setup follow button in profile modal window
2015-06-11 22:34:59 +00:00
var button = modal . content . find ( '.profile-card-buttons .follow' ) ;
2015-03-07 02:16:45 +00:00
if ( button ) {
2015-05-23 17:26:23 +00:00
if ( followingUsers . indexOf ( username ) !== - 1 )
toggleFollowButton ( username , true , function ( ) { setTimeout ( loadModalFromHash , 500 ) ; } ) ;
else
2015-03-07 02:16:45 +00:00
button . on ( 'click' , userClickFollow ) ;
2015-05-23 17:26:23 +00:00
}
2014-10-16 08:47:08 +00:00
2015-10-21 21:05:18 +00:00
elemFitNextIntoParentHeight ( modal . content . find ( '.profile-card' ) ) ;
2015-06-11 22:34:59 +00:00
var postboard = modal . content . find ( '.postboard' ) ;
2015-10-21 21:05:18 +00:00
postboard . find ( 'ol' ) . outerHeight ( postboard . actual ( 'height' )
- postboard . find ( 'h2' ) . actual ( 'outerHeight' , { includeMargin : true } ) ) ;
2013-12-30 14:42:36 +00:00
}
2015-05-23 17:26:23 +00:00
function openHashtagModalFromSearchHandler ( hashtag ) {
var modal = openModal ( {
classAdd : 'hashtag-modal' ,
content : $ ( '#hashtag-modal-template' ) . children ( ) . clone ( true ) ,
title : '#' + hashtag
2013-12-30 14:42:36 +00:00
} ) ;
clearHashtagProcessed ( ) ;
2015-05-23 17:26:23 +00:00
updateHashtagModal ( modal . content . find ( '.postboard-posts' ) , hashtag , 'hashtag' ) ;
2013-12-30 14:42:36 +00:00
}
2015-05-23 17:26:23 +00:00
function updateHashtagModal ( postboard , hashtag , resource , timeoutArgs ) {
if ( postboard . is ( 'html *' ) ) {
requestHashtag ( postboard , hashtag , resource , timeoutArgs ) ;
2015-02-06 04:00:23 +00:00
2015-05-23 17:26:23 +00:00
if ( _hashtagPendingPostsUpdated ) {
if ( resource !== 'mention' && $ . Options . showDesktopNotifPostsModal . val === 'enable' ) {
$ . MAL . showDesktopNotif ( false , polyglot . t ( 'You got' ) + ' ' + polyglot . t ( 'new_posts' , _hashtagPendingPostsUpdated ) + ' ' + polyglot . t ( 'in search result' ) + '.' , false , 'twister_notification_new_posts_modal' , $ . Options . showDesktopNotifPostsModalTimer . val , function ( ) {
$ ( '.postboard-news' ) . hide ( ) ;
displayHashtagPending ( $ ( '.hashtag-modal .postboard-posts' ) ) ;
} , false )
}
_hashtagPendingPostsUpdated = 0 ;
2015-02-14 20:49:19 +00:00
}
2015-02-06 04:00:23 +00:00
2015-05-23 17:26:23 +00:00
// use extended timeout parameters on modal refresh (requires twister_core >= 0.9.14).
// our first query above should be faster (with default timeoutArgs of twisterd),
// then we may possibly collect more posts on our second try by waiting more.
setTimeout ( updateHashtagModal , 5000 , postboard , hashtag , resource , [ 10000 , 2000 , 3 ] ) ;
2015-02-06 04:00:23 +00:00
}
2013-12-30 14:42:36 +00:00
}
2015-05-23 17:26:23 +00:00
function openMentionsModal ( e ) {
2015-02-16 07:32:12 +00:00
if ( e && e . stopPropagation ) {
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
}
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
var userInfo = $ ( this ) . closest ( '[data-screen-name]' ) ;
if ( userInfo . length )
var username = userInfo . attr ( 'data-screen-name' ) ;
else if ( defaultScreenName )
var username = defaultScreenName ;
else {
alert ( polyglot . t ( 'No one can mention you because you are not logged in.' ) ) ;
2015-05-19 18:33:59 +00:00
return ;
2014-03-29 17:16:24 +00:00
}
2013-12-30 14:42:36 +00:00
2014-11-14 20:39:33 +00:00
window . location . hash = '#mentions?user=' + username ;
}
2015-05-23 17:26:23 +00:00
function openMentionsModalHandler ( username ) {
var modal = openModal ( {
classAdd : 'hashtag-modal' ,
content : $ ( '#hashtag-modal-template' ) . children ( ) . clone ( true ) ,
title : polyglot . t ( 'users_mentions' , { username : username } )
} ) ;
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
clearHashtagProcessed ( ) ;
updateHashtagModal ( modal . content . find ( '.postboard-posts' ) , username , 'mention' ) ;
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
if ( username === defaultScreenName ) {
2014-11-14 20:39:33 +00:00
// obtain already cached mention posts from twister_newmsgs.js
2015-05-23 17:26:23 +00:00
processHashtag ( modal . content . find ( '.postboard-posts' ) , defaultScreenName , getMentionsData ( ) ) ;
2014-11-14 20:39:33 +00:00
resetMentionsCount ( ) ;
}
2013-12-30 14:42:36 +00:00
}
2015-05-23 17:26:23 +00:00
function openFollowingModal ( username ) {
var content = $ ( '#following-modal-template' ) . children ( ) . clone ( true ) ;
2014-01-05 18:12:34 +00:00
2015-05-23 17:26:23 +00:00
content . find ( '.following-screen-name b' ) . text ( username ) ;
loadFollowingIntoList ( username , content . closest ( 'ol' ) ) ;
2014-01-05 18:12:34 +00:00
2015-05-23 17:26:23 +00:00
openModal ( {
classAdd : 'following-modal' ,
content : content ,
title : polyglot . t ( 'followed_by' , { username : username } )
} ) ;
2014-05-05 19:28:15 +00:00
}
function fillWhoToFollowModal ( list , hlist , start ) {
2015-05-23 17:26:23 +00:00
var itemTmp = $ ( '#follow-suggestion-template' ) . clone ( true )
. removeAttr ( 'id' ) ;
for ( var i = 0 ; i < followingUsers . length && list . length < start + 20 ; i ++ ) {
if ( typeof twisterFollowingO . followingsFollowings [ followingUsers [ i ] ] !== 'undefined' ) {
for ( var j = 0 ; j < twisterFollowingO . followingsFollowings [ followingUsers [ i ] ] . following . length && list . length < start + 25 ; j ++ ) {
var utf = twisterFollowingO . followingsFollowings [ followingUsers [ i ] ] . following [ j ] ;
if ( followingUsers . indexOf ( utf ) < 0 && list . indexOf ( utf ) < 0 ) {
2014-05-09 09:27:48 +00:00
list . push ( utf ) ;
2014-05-05 19:28:15 +00:00
2015-05-23 17:26:23 +00:00
var item = itemTmp . clone ( true ) ;
2014-05-05 19:28:15 +00:00
2015-05-23 17:26:23 +00:00
item . find ( '.twister-user-info' ) . attr ( 'data-screen-name' , utf ) ;
item . find ( '.twister-user-name' ) . attr ( 'href' , $ . MAL . userUrl ( utf ) ) ;
item . find ( '.twister-by-user-name' ) . attr ( 'href' , $ . MAL . userUrl ( followingUsers [ i ] ) ) ;
item . find ( '.twister-user-tag' ) . text ( '@' + utf ) ;
2014-05-05 19:28:15 +00:00
2015-05-23 17:26:23 +00:00
getAvatar ( utf , item . find ( '.twister-user-photo' ) ) ;
getFullname ( utf , item . find ( '.twister-user-full' ) ) ;
2015-10-27 16:31:04 +00:00
getBioToElem ( utf , item . find ( '.bio' ) ) ;
2015-05-23 17:26:23 +00:00
getFullname ( followingUsers [ i ] , item . find ( '.followed-by' ) . text ( followingUsers [ i ] ) ) ;
2014-05-05 19:28:15 +00:00
item . find ( '.twister-user-remove' ) . remove ( ) ;
hlist . append ( item ) ;
}
}
}
}
2015-05-23 17:26:23 +00:00
itemTmp . remove ( ) ;
2014-05-06 11:43:39 +00:00
2015-05-23 17:26:23 +00:00
if ( i >= followingUsers . length - 1 )
2014-05-06 11:43:39 +00:00
return false ;
2015-05-23 17:26:23 +00:00
2014-05-06 11:43:39 +00:00
// returns true, if there are more...
return true ;
2014-05-05 19:28:15 +00:00
}
2015-01-22 14:59:00 +00:00
function openWhoToFollowModal ( ) {
2015-05-23 17:26:23 +00:00
var modal = openModal ( {
classAdd : 'who-to-follow-modal' ,
title : polyglot . t ( 'Who to Follow' )
} ) ;
2014-05-05 19:28:15 +00:00
var tmplist = [ ] ;
2015-05-23 17:26:23 +00:00
var hlist = $ ( '<ol class="follow-suggestions"></ol>' )
. appendTo ( modal . content ) ;
2014-05-05 19:28:15 +00:00
2015-05-23 17:26:23 +00:00
modal . content . on ( 'scroll' , function ( ) {
if ( modal . content . scrollTop ( ) >= hlist . height ( ) - modal . content . height ( ) - 20 ) {
2014-05-06 11:43:39 +00:00
if ( ! fillWhoToFollowModal ( tmplist , hlist , tmplist . length ) )
2015-05-23 17:26:23 +00:00
modal . content . off ( 'scroll' ) ;
2014-05-05 19:28:15 +00:00
}
} ) ;
fillWhoToFollowModal ( tmplist , hlist , 0 ) ;
}
2015-05-23 17:26:23 +00:00
function newConversationModal ( username , resource ) {
var content = $ ( '#hashtag-modal-template' ) . children ( ) . clone ( true ) ;
2015-05-19 18:33:59 +00:00
2015-05-23 17:26:23 +00:00
requestPost ( content . find ( '.postboard-posts' ) , username , resource ,
function ( args ) {
var postboard = args . content . find ( '.postboard-posts' ) ;
var postLi = postboard . children ( ) . first ( )
. css ( 'display' , 'none' ) ;
getTopPostOfConversation ( postLi , null , postboard ) ;
} , { content : content }
) ;
2015-01-23 08:08:52 +00:00
2015-05-23 17:26:23 +00:00
content . find ( '.postboard-news' ) . on ( 'click' , function ( ) {
2014-05-13 16:46:35 +00:00
$ ( this ) . hide ( ) ;
2015-05-23 17:26:23 +00:00
displayHashtagPending ( $ ( '.conversation-modal .postboard-posts' ) ) ;
2014-05-13 16:46:35 +00:00
} ) ;
2015-05-23 17:26:23 +00:00
return content ;
2014-05-13 16:46:35 +00:00
}
2015-05-23 17:26:23 +00:00
function openConversationClick ( e ) {
2015-01-23 08:48:30 +00:00
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
2015-08-14 21:17:17 +00:00
var postData = $ ( this ) . closest ( e . data . feeder ) ;
2015-01-23 08:48:30 +00:00
2015-05-23 17:26:23 +00:00
window . location . hash = '#conversation?post=' + postData . attr ( 'data-screen-name' ) +
':post' + postData . attr ( 'data-id' ) ;
2015-01-23 08:48:30 +00:00
}
2015-05-23 17:26:23 +00:00
function openConversationModal ( username , resource ) {
openModal ( {
classAdd : 'conversation-modal' ,
content : newConversationModal ( username , resource ) ,
title : polyglot . t ( 'conversation_title' , { username : username } )
} ) ;
2014-05-13 16:46:35 +00:00
}
2015-05-23 17:26:23 +00:00
function watchHashChange ( e ) {
if ( e != null ) {
2015-01-22 15:43:25 +00:00
var prevurlsplit = e . oldURL . split ( '#' ) ;
2015-05-23 17:26:23 +00:00
var prevhashstring = prevurlsplit [ 1 ] ;
2015-01-24 08:44:48 +00:00
2015-05-23 17:26:23 +00:00
var notFirstModalView = ( prevhashstring !== undefined && prevhashstring . length > 0 ) ;
var notNavigatedBackToFirstModalView = ( window . history . state == null ||
( window . history . state != null && window . history . state . showCloseButton !== false ) ) ;
2015-05-19 18:33:59 +00:00
2015-05-23 17:26:23 +00:00
if ( notFirstModalView && notNavigatedBackToFirstModalView ) {
$ ( '.modal-back' ) . css ( 'display' , 'inline' ) ;
2015-01-22 14:59:00 +00:00
} else {
2015-05-23 17:26:23 +00:00
window . history . pushState ( { showCloseButton : false } , null , null ) ;
$ ( '.modal-back' ) . css ( 'display' , 'none' ) ;
2015-01-21 11:10:04 +00:00
}
}
2015-01-22 20:22:23 +00:00
loadModalFromHash ( ) ;
}
2015-05-23 17:26:23 +00:00
function loadModalFromHash ( ) {
var hashstring = decodeURIComponent ( window . location . hash ) ;
2014-10-16 22:17:40 +00:00
var hashdata = hashstring . split ( ':' ) ;
2015-05-23 17:26:23 +00:00
if ( hashdata [ 0 ] !== '#web+twister' )
2015-09-03 22:21:33 +00:00
hashdata = hashstring . match ( /(hashtag|profile|mentions|directmessages|following|conversation)\?(?:group|user|hashtag|post)=(.+)/ ) ; // need to rework hash scheme to use group|user|hashtag|post or drop it
2014-10-16 14:57:25 +00:00
2015-05-23 17:26:23 +00:00
if ( hashdata && hashdata [ 1 ] !== undefined && hashdata [ 2 ] !== undefined ) {
if ( hashdata [ 1 ] === 'profile' )
2015-09-03 22:21:33 +00:00
if ( hashdata [ 2 ] [ 0 ] === '*' )
openGroupProfileModalWithNameHandler ( hashdata [ 2 ] ) ;
else
openUserProfileModalWithNameHandler ( hashdata [ 2 ] ) ;
2015-05-23 17:26:23 +00:00
else if ( hashdata [ 1 ] === 'hashtag' )
2014-11-14 19:21:05 +00:00
openHashtagModalFromSearchHandler ( hashdata [ 2 ] ) ;
2015-05-23 17:26:23 +00:00
else if ( hashdata [ 1 ] === 'mentions' )
2014-11-14 20:39:33 +00:00
openMentionsModalHandler ( hashdata [ 2 ] ) ;
2015-09-03 22:21:33 +00:00
else if ( hashdata [ 1 ] === 'directmessages' ) {
if ( hashdata [ 2 ] [ 0 ] === '*' )
openGroupMessagesModal ( hashdata [ 2 ] ) ;
else
openDmWithUserModal ( hashdata [ 2 ] ) ;
} else if ( hashdata [ 1 ] === 'following' )
2015-01-21 13:13:45 +00:00
openFollowingModal ( hashdata [ 2 ] ) ;
2015-05-23 17:26:23 +00:00
else if ( hashdata [ 1 ] === 'conversation' ) {
splithashdata2 = hashdata [ 2 ] . split ( ':' ) ;
openConversationModal ( splithashdata2 [ 0 ] , splithashdata2 [ 1 ] ) ;
2014-10-16 14:57:25 +00:00
}
2015-05-23 17:26:23 +00:00
} else if ( hashstring === '#directmessages' )
2015-01-21 11:10:04 +00:00
directMessagesPopup ( ) ;
2015-09-03 22:21:33 +00:00
else if ( hashstring === '#groupmessages' )
openGroupMessagesModal ( ) ;
else if ( hashstring === '#groupmessages+newgroup' )
openGroupMessagesNewGroupModal ( ) ;
else if ( hashstring === '#groupmessages+joingroup' )
openGroupMessagesJoinGroupModal ( ) ;
2015-05-23 17:26:23 +00:00
else if ( hashstring === '#whotofollow' )
2015-01-22 14:59:00 +00:00
openWhoToFollowModal ( ) ;
2015-01-22 20:22:23 +00:00
}
2014-10-16 08:47:08 +00:00
2015-05-23 17:26:23 +00:00
function initHashWatching ( ) {
// register custom protocol handler
if ( window . navigator && window . navigator . registerProtocolHandler &&
! _getResourceFromStorage ( 'twister_protocol_registered' ) ) {
window . navigator . registerProtocolHandler (
'web+twister' ,
window . location . protocol + '//' + window . location . host + '/home.html#%s' ,
'Twister'
) ;
_putResourceIntoStorage ( 'twister_protocol_registered' , true ) ;
2014-10-20 22:33:14 +00:00
}
2014-10-16 22:17:40 +00:00
2015-05-23 17:26:23 +00:00
// register hash spy and launch it once
2014-10-16 22:17:40 +00:00
window . addEventListener ( 'hashchange' , watchHashChange , false ) ;
2015-05-23 17:26:23 +00:00
setTimeout ( watchHashChange , 1000 ) ;
2014-10-16 22:17:40 +00:00
}
2015-08-20 12:19:54 +00:00
function reTwistPopup ( event , post , textArea ) {
event . stopPropagation ( ) ;
2015-05-23 17:26:23 +00:00
if ( ! defaultScreenName ) {
2015-05-19 18:33:59 +00:00
alert ( polyglot . t ( 'You have to log in to retransmit messages.' ) ) ;
return ;
2014-03-29 17:16:24 +00:00
}
2014-10-16 08:47:08 +00:00
2015-08-20 12:19:54 +00:00
if ( typeof post === 'undefined' )
2015-10-23 20:39:22 +00:00
post = $ . evalJSON ( $ ( event . target ) . closest ( '.post-data' ) . attr ( 'data-userpost' ) ) ;
2015-08-20 12:19:54 +00:00
2015-08-12 17:10:42 +00:00
var modal = openModal ( {
2015-05-23 17:26:23 +00:00
classBase : '.prompt-wrapper' ,
classAdd : 'reTwist' ,
title : polyglot . t ( 'retransmit_this' )
2015-08-12 17:10:42 +00:00
} ) ;
modal . content
2015-08-20 12:19:54 +00:00
. append ( postToElem ( post , '' ) )
. append ( $ ( '#reTwist-modal-template' ) . children ( ) . clone ( true ) )
2015-08-12 17:10:42 +00:00
;
2015-08-20 12:19:54 +00:00
modal . content . find ( '.switch-mode' )
. text ( polyglot . t ( 'Switch to Reply' ) )
. on ( 'click' , ( function ( event ) { replyInitPopup ( event , post ,
2015-10-23 20:39:22 +00:00
$ ( event . target ) . closest ( 'form' ) . find ( 'textarea' ) . detach ( ) ) ; } ) . bind ( post ) )
2015-08-20 12:19:54 +00:00
;
2015-08-12 17:10:42 +00:00
2015-08-20 12:19:54 +00:00
var replyArea = modal . content . find ( '.post-area .post-area-new' ) ;
if ( typeof textArea === 'undefined' ) {
textArea = replyArea . find ( 'textarea' ) ;
var textAreaPostInline = modal . content . find ( '.post .post-area-new textarea' ) ;
$ . each ( [ 'placeholder' , 'data-reply-to' ] , function ( i , attribute ) {
textArea . attr ( attribute , textAreaPostInline . attr ( attribute ) ) ;
} ) ;
} else {
replyArea . find ( 'textarea' ) . replaceWith ( textArea ) ;
2015-08-20 12:31:16 +00:00
if ( textArea . val ( ) ) {
textArea . focus ( ) ;
replyArea . addClass ( 'open' ) ;
}
2015-08-20 12:19:54 +00:00
}
2015-08-12 17:10:42 +00:00
replyArea . find ( '.post-submit' ) . addClass ( 'with-reference' ) ;
2013-12-30 14:42:36 +00:00
}
2015-05-23 17:26:23 +00:00
// Expande Área do Novo post
2015-08-20 12:19:54 +00:00
function replyInitPopup ( e , post , textArea ) {
2015-05-23 17:26:23 +00:00
var modal = openModal ( {
classBase : '.prompt-wrapper' ,
classAdd : 'reply' ,
title : polyglot . t ( 'reply_to' , { fullname : '<span class="fullname">' + post . userpost . n + '</span>' } )
} ) ;
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
getFullname ( post . userpost . n , modal . self . find ( 'h3 .fullname' ) ) ;
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
modal . content
. append ( postToElem ( post , '' ) )
2015-08-12 17:10:42 +00:00
. append ( $ ( '#reply-modal-template' ) . children ( ) . clone ( true ) )
2015-05-23 17:26:23 +00:00
;
2013-12-30 14:42:36 +00:00
2015-08-20 12:19:54 +00:00
modal . content . find ( '.switch-mode' )
. text ( polyglot . t ( 'Switch to Retransmit' ) )
. on ( 'click' , ( function ( event ) { reTwistPopup ( event , post ,
2015-10-23 20:39:22 +00:00
$ ( event . target ) . closest ( 'form' ) . find ( 'textarea' ) . detach ( ) ) } ) . bind ( post ) )
2015-08-20 12:19:54 +00:00
;
2013-12-30 14:42:36 +00:00
2015-08-20 12:19:54 +00:00
var replyArea = modal . content . find ( '.post-area .post-area-new' ) . addClass ( 'open' ) ;
if ( typeof textArea === 'undefined' ) {
textArea = replyArea . find ( 'textarea' ) ;
var textAreaPostInline = modal . content . find ( '.post .post-area-new textarea' ) ;
$ . each ( [ 'placeholder' , 'data-reply-to' ] , function ( i , attribute ) {
textArea . attr ( attribute , textAreaPostInline . attr ( attribute ) ) ;
} ) ;
} else {
replyArea . find ( 'textarea' ) . replaceWith ( textArea ) ;
}
2015-05-23 17:26:23 +00:00
composeNewPost ( e , replyArea ) ;
2013-12-30 14:42:36 +00:00
}
2015-05-23 17:26:23 +00:00
// abre o menu dropdown de configurações
2015-03-03 23:26:20 +00:00
function dropDownMenu ( ) {
2015-05-23 17:26:23 +00:00
$ ( '.config-menu' ) . slideToggle ( 'fast' ) ;
2013-12-30 14:42:36 +00:00
}
2015-05-23 17:26:23 +00:00
// fecha o config menu ao clicar em qualquer lugar da tela
2015-03-03 23:26:20 +00:00
function closeThis ( ) {
2015-05-23 17:26:23 +00:00
$ ( this ) . slideUp ( 'fast' ) ;
2015-03-03 23:26:20 +00:00
}
2015-03-07 02:16:45 +00:00
function toggleFollowButton ( username , toggleUnfollow , bindFunc ) {
if ( ! username )
2015-03-03 23:26:20 +00:00
return ;
2015-03-07 02:16:45 +00:00
if ( toggleUnfollow ) {
2015-05-23 17:26:23 +00:00
$ ( '[data-screen-name="' + username + '"]' ) . find ( '.follow' )
. removeClass ( 'follow' )
. addClass ( 'unfollow' )
. off ( 'click' )
. on ( 'click' ,
2015-03-07 02:16:45 +00:00
( function ( e ) {
e . stopPropagation ( ) ;
unfollow ( this . username . toString ( ) ,
( function ( ) {
toggleFollowButton ( this . username ) ;
if ( this . bindFunc )
this . bindFunc ;
} ) . bind ( { username : this . username , bindFunc : this . bindFunc } )
) ;
} ) . bind ( { username : username , bindFunc : bindFunc } )
)
. text ( polyglot . t ( 'Unfollow' ) )
2015-05-23 17:26:23 +00:00
. trigger ( 'eventToggleUnfollow' )
;
2015-03-07 02:16:45 +00:00
} else {
2015-05-23 17:26:23 +00:00
$ ( '[data-screen-name="' + username + '"]' ) . find ( '.unfollow' )
. removeClass ( 'unfollow' )
. addClass ( 'follow' )
. off ( 'click' )
. on ( 'click' ,
2015-03-07 02:16:45 +00:00
( function ( e ) {
2015-03-10 17:23:28 +00:00
userClickFollow ( e ) ;
2015-03-07 02:16:45 +00:00
if ( this . bindFunc )
this . bindFunc ;
} ) . bind ( { bindFunc : bindFunc } )
)
. text ( polyglot . t ( 'Follow' ) )
2015-05-23 17:26:23 +00:00
. trigger ( 'eventToggleFollow' ) ;
2015-03-07 02:16:45 +00:00
}
2015-03-03 23:26:20 +00:00
}
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
function postExpandFunction ( e , postLi ) {
if ( ! postLi . hasClass ( 'original' ) )
2013-12-30 14:42:36 +00:00
return ;
2015-05-23 17:26:23 +00:00
var openClass = 'open' ;
var originalPost = postLi . find ( '.post-data.original' ) ;
var postInteractionText = originalPost . find ( '.post-expand' ) ;
var postExpandedContent = originalPost . find ( '.expanded-content' ) ;
var postsRelated = postLi . find ( '.related' ) ;
2014-10-16 08:47:08 +00:00
2015-05-23 17:26:23 +00:00
if ( ! postLi . hasClass ( openClass ) ) {
2013-12-30 14:42:36 +00:00
originalPost . detach ( ) ;
postLi . empty ( ) ;
2015-05-23 17:26:23 +00:00
postLi . addClass ( openClass ) ;
postInteractionText . text ( polyglot . t ( 'Collapse' ) ) ;
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
var itemOl = $ ( '<ol/>' , { class : 'expanded-post' } ) . appendTo ( postLi ) ;
var originalLi = $ ( '<li/>' , { class : 'module post original' } ) . appendTo ( itemOl )
. append ( originalPost ) ;
2013-12-30 14:42:36 +00:00
2015-08-09 22:02:15 +00:00
setPostImagePreview ( postExpandedContent , originalPost . find ( 'a[rel="nofollow"]' ) ) ;
2015-05-23 17:26:23 +00:00
postExpandedContent . slideDown ( 'fast' ) ;
2014-10-16 08:47:08 +00:00
2015-05-23 17:26:23 +00:00
// insert 'reply_to' before
2013-12-30 14:42:36 +00:00
requestRepliedBefore ( originalLi ) ;
// insert replies to this post after
requestRepliesAfter ( originalLi ) ;
// RTs faces and counter
requestRTs ( originalLi ) ;
2015-05-23 17:26:23 +00:00
} else {
postLi . removeClass ( openClass ) ;
2014-05-07 10:28:16 +00:00
2015-05-23 17:26:23 +00:00
postInteractionText . text (
( typeof postLi . find ( '.post-data.original' ) . attr ( 'data-replied-to-id' ) === 'undefined' ) ?
polyglot . t ( 'Expand' ) : polyglot . t ( 'Show conversation' )
) ;
2014-05-07 10:28:16 +00:00
2015-05-23 17:26:23 +00:00
if ( postsRelated )
postsRelated . slideUp ( 'fast' ) ;
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
postExpandedContent . slideUp ( 'fast' , function ( ) {
originalPost . detach ( ) . appendTo ( postLi . empty ( ) ) ;
2013-12-30 14:42:36 +00:00
} ) ;
}
e . stopPropagation ( ) ;
}
2015-05-23 17:26:23 +00:00
function postReplyClick ( e ) {
if ( ! defaultScreenName ) {
2015-05-19 18:33:59 +00:00
e . stopPropagation ( ) ;
alert ( polyglot . t ( 'You have to log in to post replies.' ) ) ;
return ;
2014-03-29 17:16:24 +00:00
}
2015-05-23 17:26:23 +00:00
var post = $ ( this ) . closest ( '.post' ) ;
if ( ! post . hasClass ( 'original' ) )
replyInitPopup ( e , $ . evalJSON ( post . find ( '.post-data' ) . attr ( 'data-userpost' ) ) ) ;
else {
2015-10-23 20:39:22 +00:00
if ( ! post . closest ( '.post.open' ) . length )
2013-12-30 14:42:36 +00:00
postExpandFunction ( e , post ) ;
2015-05-23 17:26:23 +00:00
composeNewPost ( e , post . find ( '.post-area-new' ) ) ;
2013-12-30 14:42:36 +00:00
}
2015-05-23 17:26:23 +00:00
2013-12-30 14:42:36 +00:00
e . stopPropagation ( ) ;
}
2015-05-23 17:26:23 +00:00
// Expande Área do Novo post
function composeNewPost ( e , postAreaNew ) {
2013-12-30 14:42:36 +00:00
e . stopPropagation ( ) ;
2015-05-23 17:26:23 +00:00
if ( ! postAreaNew . hasClass ( 'open' ) ) {
postAreaNew . addClass ( 'open' ) ;
2013-12-30 14:42:36 +00:00
//se o usuário clicar fora é pra fechar
2015-05-23 17:26:23 +00:00
postAreaNew . clickoutside ( unfocusThis ) ;
2014-04-16 22:21:17 +00:00
2015-05-19 18:33:59 +00:00
if ( $ . Options . splitPosts . val === 'enable' )
2014-04-16 22:21:17 +00:00
usePostSpliting = true ;
2015-05-19 18:33:59 +00:00
else if ( $ . Options . splitPosts . val === 'only-new' ) {
2015-05-23 17:26:23 +00:00
var postOrig = postAreaNew . closest ( '.post-data' ) ;
2014-04-16 22:21:17 +00:00
2015-05-23 17:26:23 +00:00
if ( ! postOrig . length )
postOrig = postAreaNew . closest ( '.modal-content' ) . find ( '.post-data' ) ;
2014-04-16 22:21:17 +00:00
2015-05-23 17:26:23 +00:00
if ( postOrig . length )
2014-04-16 22:21:17 +00:00
usePostSpliting = false ;
else
usePostSpliting = true ;
} else
usePostSpliting = false ;
2013-12-30 14:42:36 +00:00
}
2015-05-23 17:26:23 +00:00
var textArea = postAreaNew . find ( 'textarea' ) ;
if ( textArea . attr ( 'data-reply-to' ) && ! textArea . val ( ) . length ) {
textArea . val ( textArea . attr ( 'data-reply-to' ) ) ;
2015-08-07 16:08:46 +00:00
posPostPreview ( textArea ) ;
2013-12-30 14:42:36 +00:00
}
2015-05-23 17:26:23 +00:00
if ( ! postAreaNew . find ( 'textarea:focus' ) . length )
postAreaNew . find ( 'textarea:last' ) . focus ( ) ;
2013-12-30 14:42:36 +00:00
}
2015-07-23 19:51:24 +00:00
function posPostPreview ( event ) {
2015-07-24 21:48:19 +00:00
if ( ! $ . Options . postPreview . val )
return ;
2015-08-07 16:08:46 +00:00
if ( event . jquery ) {
var textArea = event ;
} else {
var textArea = $ ( event . target ) ;
}
2015-07-23 19:51:24 +00:00
var postPreview = textArea . siblings ( '#post-preview' ) ;
2015-07-24 21:19:52 +00:00
if ( ! postPreview . length ) {
postPreview = $ ( '#post-preview-template' ) . children ( ) . clone ( )
. css ( 'margin-left' , textArea . css ( 'margin-left' ) )
. css ( 'margin-right' , textArea . css ( 'margin-right' ) )
;
2015-07-24 22:19:12 +00:00
postPreview . width ( textArea . width ( ) ) ;
postPreview . width ( postPreview . width ( ) // width is not accurate if we do it with textArea.width() directly, don't know why
2015-07-24 21:19:52 +00:00
- postPreview . css ( 'padding-left' ) - postPreview . css ( 'padding-right' ) ) ;
}
2015-07-24 23:13:53 +00:00
if ( textArea [ 0 ] . value . length )
2015-08-11 20:49:30 +00:00
postPreview . html ( htmlFormatMsg ( textArea [ 0 ] . value ) . html ) . show ( ) ;
2015-07-24 23:13:53 +00:00
else
2015-08-21 05:10:46 +00:00
postPreview . hide ( ) ;
2015-07-23 19:51:24 +00:00
textArea . before ( postPreview ) ;
}
2015-05-23 17:26:23 +00:00
// Reduz Área do Novo post
function unfocusThis ( ) {
2015-08-20 12:31:16 +00:00
$ ( this ) . removeClass ( 'open' )
. find ( '#post-preview' ) . slideUp ( 'fast' ) ;
2013-12-30 14:42:36 +00:00
}
2014-05-11 19:18:33 +00:00
function checkPostForMentions ( post , mentions , max ) {
2015-05-23 17:26:23 +00:00
return new RegExp ( '^.{0,' + max . toString ( ) + '}(?:' + mentions . trim ( ) . replace ( / /g , '|' ) + ')' ) . test ( post ) ;
2014-05-11 19:18:33 +00:00
}
2015-05-23 17:26:23 +00:00
var splitedPostsCount = 1 ; // FIXME it could be property of future textAreaInput and composeNewPost united thing; currently stuff is hell
2014-04-16 22:21:17 +00:00
var usePostSpliting = false ;
2015-05-23 17:26:23 +00:00
function replyTextInput ( event ) {
var textArea = $ ( event . target ) ;
2015-10-23 20:39:22 +00:00
var textAreaForm = textArea . closest ( 'form' ) ;
2015-05-23 17:26:23 +00:00
if ( textAreaForm . length ) {
2015-05-19 18:33:59 +00:00
if ( $ . Options . unicodeConversion . val !== 'disable' )
2015-05-23 17:26:23 +00:00
textArea . val ( convert2Unicodes ( textArea . val ( ) , textArea ) ) ;
2015-10-23 20:39:22 +00:00
if ( usePostSpliting && ! textArea . closest ( '.directMessages' ) . length ) {
2015-05-23 17:26:23 +00:00
var caretPos = textArea . caret ( ) ;
var reply _to = textArea . attr ( 'data-reply-to' ) ;
var tas = textAreaForm . find ( 'textarea' ) ;
splitedPostsCount = tas . length ;
var icurrentta = tas . index ( event . target ) ; // current textarea tas index
var i = 0 ;
var pml = getPostSplitingPML ( ) ;
2015-04-10 01:59:57 +00:00
var cci = getPostSpittingCI ( icurrentta ) ;
2014-05-08 20:28:16 +00:00
2015-05-23 17:26:23 +00:00
for ( ; i < tas . length ; i ++ ) {
pml = getPostSplitingPML ( ) ;
if ( tas [ i ] . value . length > pml ) {
2015-04-10 01:59:57 +00:00
var ci = getPostSpittingCI ( i ) ;
2014-05-11 19:18:33 +00:00
if ( i < splitedPostsCount - 1 ) {
2015-05-23 17:26:23 +00:00
tas [ i + 1 ] . value = tas [ i ] . value . substr ( ci ) + tas [ i + 1 ] . value ;
tas [ i ] . value = tas [ i ] . value . substr ( 0 , ci ) ;
2015-04-10 01:59:57 +00:00
if ( caretPos > cci ) {
2015-04-09 17:09:05 +00:00
caretPos -= ci ;
icurrentta += 1 ;
2015-04-10 01:59:57 +00:00
cci = getPostSpittingCI ( icurrentta ) ;
2015-05-23 17:26:23 +00:00
var targetta = $ ( tas [ icurrentta ] ) ;
2015-04-09 17:09:05 +00:00
} else if ( i === icurrentta )
2015-05-23 17:26:23 +00:00
$ ( tas [ i ] ) . caret ( caretPos ) ;
2014-05-11 19:18:33 +00:00
} else {
2015-05-23 17:26:23 +00:00
var oldta = $ ( tas [ i ] ) ;
if ( $ . fn . textcomplete ) {
oldta . textcomplete ( 'destroy' ) ;
event . stopImmediatePropagation ( ) ; // something goes wrong in $.fn.textcomplete if we don't stop this immediately
2015-04-09 17:09:05 +00:00
}
2015-05-23 17:26:23 +00:00
var cp = oldta . val ( ) ;
var newta = $ ( oldta ) . clone ( true )
. val ( cp . substr ( ci ) )
. insertAfter ( oldta )
;
oldta . val ( cp . substr ( 0 , ci ) )
. addClass ( 'splited-post' )
. on ( 'focus' , function ( ) { this . style . height = '80px' ; } )
. on ( 'focusout' , function ( ) { this . style . height = '28px' ; } ) // FIXME move this to CSS
;
tas = textAreaForm . find ( 'textarea' ) ;
splitedPostsCount = tas . length ;
2015-04-12 20:20:41 +00:00
pml = getPostSplitingPML ( ) ;
2015-04-10 01:59:57 +00:00
if ( caretPos > cci ) {
2015-04-09 17:09:05 +00:00
caretPos -= ci ;
icurrentta += 1 ;
2015-04-10 01:59:57 +00:00
cci = getPostSpittingCI ( icurrentta ) ;
2015-05-23 17:26:23 +00:00
var targetta = newta ;
oldta [ 0 ] . style . height = '28px' ; // FIXME move this to CSS
2015-04-10 01:59:57 +00:00
} else if ( i === icurrentta ) {
2015-05-23 17:26:23 +00:00
$ ( tas [ i ] ) . caret ( caretPos ) ;
replyTextUpdateRemaining ( tas [ i ] ) ;
if ( $ . fn . textcomplete )
2015-09-04 23:14:16 +00:00
setTextcompleteOnElement ( tas [ i ] , getMentionsForAutoComplete ( ) ) ;
2015-04-10 01:59:57 +00:00
}
2014-05-11 19:18:33 +00:00
}
2015-05-23 17:26:23 +00:00
} else if ( tas . length > 1 && tas [ i ] . value . length === 0 ) {
if ( i === tas . length - 1 ) {
tas [ i ] . value = tas [ i - 1 ] . value ;
$ ( tas [ i - 1 ] ) . remove ( ) ;
} else
$ ( tas [ i ] ) . remove ( ) ;
tas = textAreaForm . find ( 'textarea' ) ;
i -- ;
splitedPostsCount = tas . length ;
pml = getPostSplitingPML ( ) ;
2015-04-09 17:09:05 +00:00
caretPos = - 1 ;
2015-04-10 01:59:57 +00:00
if ( icurrentta >= i && icurrentta > 0 ) {
2015-04-09 17:09:05 +00:00
icurrentta -= 1 ;
2015-04-10 01:59:57 +00:00
cci = getPostSpittingCI ( icurrentta ) ;
}
2015-05-23 17:26:23 +00:00
var targetta = $ ( tas [ icurrentta ] ) ;
2014-04-16 22:21:17 +00:00
}
2014-04-18 15:55:12 +00:00
}
2015-04-10 01:59:57 +00:00
2015-05-23 17:26:23 +00:00
if ( typeof targetta !== 'undefined' && targetta [ 0 ] !== document . activeElement ) {
textArea = targetta ;
textArea . focus ( ) ;
textArea . caret ( caretPos ) ;
2015-04-09 17:09:05 +00:00
}
2014-04-16 22:21:17 +00:00
}
2015-07-23 19:51:24 +00:00
2015-07-29 12:13:32 +00:00
if ( $ . Options . postPreview . val ) {
if ( textArea [ 0 ] . value . length )
2015-08-11 20:49:30 +00:00
textAreaForm . find ( '#post-preview' ) . html ( htmlFormatMsg ( textArea [ 0 ] . value ) . html ) . show ( ) ;
2015-07-29 12:13:32 +00:00
else
2015-08-20 12:31:16 +00:00
textAreaForm . find ( '#post-preview' ) . html ( '' ) . slideUp ( 'fast' ) ;
2015-07-29 12:13:32 +00:00
}
2015-04-10 01:59:57 +00:00
}
2013-12-30 14:42:36 +00:00
2015-04-10 01:59:57 +00:00
function getPostSplitingPML ( ) {
2015-05-23 17:26:23 +00:00
if ( splitedPostsCount > 1 ) {
var pml = 140 - ( i + 1 ) . toString ( ) . length - splitedPostsCount . toString ( ) . length - 4 ;
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
// if mention exists, we shouldn't add it while posting.
if ( typeof reply _to !== 'undefined' &&
! checkPostForMentions ( tas [ i ] . value , reply _to , pml - reply _to . length ) ) {
pml -= reply _to . length ;
}
} else
var pml = 140 ;
2015-04-10 01:59:57 +00:00
return pml ;
}
function getPostSpittingCI ( ita ) {
var ci ;
2015-05-23 17:26:23 +00:00
var endings = tas [ ita ] . value . match ( /[\\\/\.,:;\?\!\*'"\]\)\}\^\|%\u201D\u2026\u2014\u4E00\u3002\uFF0C\uFF1A\uFF1F\uFF01\u3011>\s]/g ) // unicode escaped stuff is '”…—一。,:?!】
2015-04-10 01:59:57 +00:00
if ( endings ) {
2015-05-23 17:26:23 +00:00
ci = tas [ ita ] . value . lastIndexOf ( endings [ endings . length - 1 ] ) ;
for ( var j = endings . length - 2 ; j >= 0 && ci > pml ; j -- )
ci = tas [ ita ] . value . lastIndexOf ( endings [ j ] , ci - 1 ) ;
2013-12-30 14:42:36 +00:00
}
2015-04-10 01:59:57 +00:00
if ( ! ( ci > 0 ) )
ci = pml ;
return ( ci > pml ) ? pml : ci ;
2013-12-30 14:42:36 +00:00
}
}
2015-04-10 01:59:57 +00:00
function replyTextUpdateRemaining ( ta ) {
2015-05-23 17:26:23 +00:00
if ( ta . target )
ta = ta . target ;
if ( ta === document . activeElement ) {
var textArea = $ ( ta ) ;
2015-10-23 20:39:22 +00:00
var textAreaForm = textArea . closest ( 'form' ) ;
2015-05-23 17:26:23 +00:00
if ( textAreaForm . length ) {
var remainingCount = textAreaForm . find ( '.post-area-remaining' ) ;
2015-04-10 01:59:57 +00:00
var c = replyTextCountRemaining ( ta ) ;
2015-04-09 17:09:05 +00:00
2015-10-23 20:39:22 +00:00
if ( usePostSpliting && ! textArea . closest ( '.directMessages' ) . length && splitedPostsCount > 1 )
2015-05-23 17:26:23 +00:00
remainingCount . text ( ( textAreaForm . find ( 'textarea' ) . index ( ta ) + 1 ) . toString ( )
+ '/' + splitedPostsCount . toString ( ) + ': ' + c . toString ( ) ) ;
2015-04-09 17:09:05 +00:00
else
remainingCount . text ( c . toString ( ) ) ;
2015-05-23 17:26:23 +00:00
var buttonSend = textAreaForm . find ( '.post-submit' ) ;
if ( ! buttonSend . length )
buttonSend = textAreaForm . find ( '.dm-submit' ) ;
2015-04-10 01:59:57 +00:00
var disable = false ;
2015-05-23 17:26:23 +00:00
textAreaForm . find ( 'textarea' ) . each ( function ( ) {
2015-04-10 01:59:57 +00:00
if ( replyTextCountRemaining ( this ) < 0 ) {
disable = true ; // alternatively we could call replyTextInput()
return false ;
}
} ) ;
2015-05-23 17:26:23 +00:00
if ( ! disable && c >= 0 && c < 140 && textArea . val ( ) !== textArea . attr ( 'data-reply-to' ) ) {
remainingCount . removeClass ( 'warn' ) ;
$ . MAL . enableButton ( buttonSend ) ;
2015-04-10 01:59:57 +00:00
} else {
if ( disable )
2015-05-23 17:26:23 +00:00
remainingCount . addClass ( 'warn' ) ;
$ . MAL . disableButton ( buttonSend ) ;
2015-04-10 01:59:57 +00:00
}
2015-04-09 17:09:05 +00:00
}
}
}
2015-04-10 01:59:57 +00:00
function replyTextCountRemaining ( ta ) {
2015-05-23 17:26:23 +00:00
var textArea = $ ( ta ) ;
2015-04-09 17:09:05 +00:00
var c ;
2015-10-23 20:39:22 +00:00
if ( usePostSpliting && ! textArea . closest ( '.directMessages' ) . length && splitedPostsCount > 1 ) {
c = 140 - ta . value . length - ( textArea . closest ( 'form' ) . find ( 'textarea' ) . index ( ta ) + 1 ) . toString ( ) . length - splitedPostsCount . toString ( ) . length - 4 ;
2015-05-23 17:26:23 +00:00
var reply _to = textArea . attr ( 'data-reply-to' ) ;
if ( typeof reply _to !== 'undefined' &&
2015-04-10 01:59:57 +00:00
! checkPostForMentions ( ta . value , reply _to , 140 - c - reply _to . length ) )
2015-05-23 17:26:23 +00:00
c -= reply _to . length ;
2015-04-09 17:09:05 +00:00
} else
c = 140 - ta . value . length ;
return c ;
}
2015-05-23 17:26:23 +00:00
function replyTextKeySend ( event ) {
if ( event . keyCode === 13 ) {
if ( ( ! event . metaKey && ! event . ctrlKey && $ . Options . keysSend . val === 'enter' &&
$ ( '.dropdown-menu' ) . css ( 'display' ) === 'none' )
|| ( ( event . metaKey || event . ctrlKey ) && $ . Options . keysSend . val === 'ctrlenter' ) ) {
var textArea = $ ( event . target ) ;
2015-10-23 20:39:22 +00:00
var textAreaForm = textArea . closest ( 'form' ) ;
2015-05-23 17:26:23 +00:00
var buttonSend = textAreaForm . find ( '.post-submit' ) ;
if ( ! buttonSend . length )
buttonSend = textAreaForm . find ( '.dm-submit' ) ;
if ( buttonSend . length ) {
textArea . val ( textArea . val ( ) . trim ( ) ) ;
if ( ! buttonSend . hasClass ( 'disabled' ) )
buttonSend . click ( ) ;
2015-04-10 01:59:57 +00:00
}
}
}
}
2014-04-07 16:11:41 +00:00
/ *
* unicode convertion list
* k : original string to be replaced
* u : unicode
* n : index of char to be stored and appended to result
* /
var unicodeConversionList = {
2015-05-23 17:26:23 +00:00
'punctuation' : [
2014-04-07 16:11:41 +00:00
{
2015-05-23 17:26:23 +00:00
'k' : /\.\.\./ ,
'u' : '\u2026' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /\.\../ ,
'u' : '\u2025' ,
'n' : 2
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /\?\?/ ,
'u' : '\u2047' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /\?!/ ,
'u' : '\u2048' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /!\?/ ,
'u' : '\u2049' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /!!/ ,
'u' : '\u203C' ,
'n' : - 1
2014-04-07 22:56:12 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /--/ ,
'u' : '\u2014' ,
'n' : - 1
2014-04-07 22:56:12 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /~~/ ,
'u' : '\u2053' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
}
] ,
2015-05-23 17:26:23 +00:00
'emotions' : [
2014-04-07 16:11:41 +00:00
{
2015-05-23 17:26:23 +00:00
'k' : /:.{0,1}D/ ,
'u' : '\uD83D\uDE03' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /(0|O):-{0,1}\)/i ,
'u' : '\uD83D\uDE07' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /:beer:/ ,
'u' : '\uD83C\uDF7A' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /3:-{0,1}\)/ ,
'u' : '\uD83D\uDE08' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /<3/ ,
'u' : '\u2764' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
2014-04-09 14:24:32 +00:00
// disabled due to urls :/
// {
2015-05-23 17:26:23 +00:00
// 'k': /o.O|:\/|:\\/,
// 'u': '\uD83D\uDE15',
// 'n': -1
2014-04-09 14:24:32 +00:00
// },
2014-04-07 16:11:41 +00:00
{
2015-05-23 17:26:23 +00:00
'k' : /:\'\(/ ,
'u' : '\uD83D\uDE22' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /(:|=)-{0,1}\(/ ,
'u' : '\uD83D\uDE1E' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /8(\)<|\|)/ ,
'u' : '\uD83D\uDE0E' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /(:|=)-{0,1}(\)|\])/ ,
'u' : '\uD83D\uDE0A' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /(\(|\[)-{0,1}(:|=)/ ,
'u' : '\uD83D\uDE0A' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /:\*/ ,
'u' : '\uD83D\uDE17' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /\^-{0,1}\^/ ,
'u' : '\uD83D\uDE06' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /:p/i ,
'u' : '\uD83D\uDE1B' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /;-{0,1}\)/ ,
'u' : '\uD83D\uDE09' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /\(-{0,1};/ ,
'u' : '\uD83D\uDE09' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /:(O|0)/ ,
'u' : '\uD83D\uDE2E' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /:@/ ,
'u' : '\uD83D\uDE31' ,
'n' : - 1
2014-04-07 22:56:12 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /:\|/ ,
'u' : '\uD83D\uDE10' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
}
] ,
2015-05-23 17:26:23 +00:00
'signs' : [
2014-04-07 16:11:41 +00:00
{
2015-05-23 17:26:23 +00:00
'k' : / tel(|:|=)/i ,
'u' : ' \u2121' ,
'n' : 4
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /^tel(|:|=)/i ,
'u' : '\u2121' ,
'n' : 3
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : / fax(|:|=)/i ,
'u' : ' \u213B' ,
'n' : 4
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /^fax(|:|=)/i ,
'u' : '\u213B' ,
'n' : 3
2014-04-07 16:11:41 +00:00
}
] ,
2015-05-23 17:26:23 +00:00
'fractions' : [
2014-04-07 16:11:41 +00:00
{
2015-05-23 17:26:23 +00:00
'k' : /1\/2/ ,
'u' : '\u00BD' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /1\/3/ ,
'u' : '\u2153' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /2\/3/ ,
'u' : '\u2154' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /1\/4/ ,
'u' : '\u00BC' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /3\/4/ ,
'u' : '\u00BE' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /1\/5/ ,
'u' : '\u2155' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /2\/5/ ,
'u' : '\u2156' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /3\/5/ ,
'u' : '\u2157' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /4\/5/ ,
'u' : '\u2158' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /1\/6/ ,
'u' : '\u2159' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /5\/6/ ,
'u' : '\u215A' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /1\/7/ ,
'u' : '\u2150' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /1\/8/ ,
'u' : '\u215B' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /3\/8/ ,
'u' : '\u215C' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /5\/8/ ,
'u' : '\u215D' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /7\/8/ ,
'u' : '\u215E' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /1\/9/ ,
'u' : '\u2151' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
} ,
{
2015-05-23 17:26:23 +00:00
'k' : /1\/10/ ,
'u' : '\u2152' ,
'n' : - 1
2014-04-07 16:11:41 +00:00
}
2015-05-23 17:26:23 +00:00
] } ;
2014-04-07 16:11:41 +00:00
2014-07-31 18:43:01 +00:00
// Marks ranges in a message where unicode replacements will be ignored (inside URLs).
2015-05-23 17:26:23 +00:00
function getRangesForUnicodeConversion ( msg ) {
if ( ! msg )
return ;
2014-10-16 08:47:08 +00:00
2014-07-31 18:43:01 +00:00
var tempMsg = msg ;
var results = [ ] ;
var regexHttpStart = /http[s]?:\/\// ;
var regexHttpEnd = /[ \n\t]/ ;
2015-05-23 17:26:23 +00:00
var start = 0 , end , position , rep = true ;
2014-10-16 08:47:08 +00:00
2014-07-31 18:43:01 +00:00
position = tempMsg . search ( regexHttpStart ) ;
2015-05-23 17:26:23 +00:00
while ( position !== - 1 ) {
2014-07-31 18:43:01 +00:00
end = start + position ;
2015-05-23 17:26:23 +00:00
if ( end > start )
2014-07-31 18:43:01 +00:00
results . push ( { start : start , end : end , replace : rep } ) ;
rep = ! rep ;
start = end ;
tempMsg = tempMsg . substring ( position , tempMsg . length ) ;
2014-10-16 08:47:08 +00:00
2015-05-23 17:26:23 +00:00
if ( rep === true )
2014-07-31 18:43:01 +00:00
position = tempMsg . search ( regexHttpStart ) ;
else
position = tempMsg . search ( regexHttpEnd ) ;
2014-04-07 16:11:41 +00:00
}
2015-05-23 17:26:23 +00:00
2014-07-31 18:43:01 +00:00
end = msg . length ;
2015-05-23 17:26:23 +00:00
if ( end > start )
2014-07-31 18:43:01 +00:00
results . push ( { start : start , end : end , replace : rep } ) ;
2014-10-16 08:47:08 +00:00
return results ;
2014-07-31 18:43:01 +00:00
}
2014-04-07 16:11:41 +00:00
2015-05-23 17:26:23 +00:00
function getUnicodeReplacement ( msg , list , ranges , ta ) {
if ( ! msg || ! list || ! ranges )
return ;
if ( ranges . length === 0 )
return '' ;
2014-10-16 08:47:08 +00:00
2014-07-31 18:43:01 +00:00
var position , substrings = [ ] ;
2015-05-23 17:26:23 +00:00
for ( var j = 0 ; j < ranges . length ; j ++ ) {
2014-07-31 18:43:01 +00:00
substrings [ j ] = msg . substring ( ranges [ j ] . start , ranges [ j ] . end ) ;
2015-05-23 17:26:23 +00:00
if ( ranges [ j ] . replace === true ) {
for ( var i = 0 ; i < list . length ; i ++ ) {
2014-07-31 18:43:01 +00:00
position = substrings [ j ] . search ( list [ i ] . k ) ;
2015-05-23 17:26:23 +00:00
if ( position !== - 1 && ta . data ( 'disabledUnicodeRules' ) . indexOf ( list [ i ] . u ) === - 1 ) {
2014-07-31 18:43:01 +00:00
var oldSubstring = substrings [ j ] ;
substrings [ j ] = substrings [ j ] . replace ( list [ i ] . k , list [ i ] . u ) ;
2014-10-16 08:47:08 +00:00
2014-07-31 18:43:01 +00:00
var len = oldSubstring . length - substrings [ j ] . length + list [ i ] . u . length ;
2015-05-23 17:26:23 +00:00
ta . data ( 'unicodeConversionStack' ) . unshift ( {
'k' : oldSubstring . substr ( position , len ) ,
'u' : list [ i ] . u ,
'p' : ranges [ j ] . start + position
2014-07-31 18:43:01 +00:00
} ) ;
}
}
}
}
var returnString = substrings [ 0 ] ;
2015-05-23 17:26:23 +00:00
for ( var j = 1 ; j < ranges . length ; j ++ ) {
2014-07-31 18:43:01 +00:00
returnString += substrings [ j ] ;
}
return returnString ;
}
2014-04-07 16:11:41 +00:00
2015-05-23 17:26:23 +00:00
function convert2Unicodes ( s , ta ) {
if ( ! ta . data ( 'unicodeConversionStack' ) ) // A stack of undo steps
ta . data ( 'unicodeConversionStack' , [ ] ) ;
if ( ! ta . data ( 'disabledUnicodeRules' ) ) // A list of conversion rules that are temporarily disabled
ta . data ( 'disabledUnicodeRules' , [ ] ) ;
2014-07-31 18:43:01 +00:00
var ranges = getRangesForUnicodeConversion ( s ) ;
2014-10-16 08:47:08 +00:00
2015-05-23 17:26:23 +00:00
if ( $ . Options . unicodeConversion . val === 'enable' || $ . Options . convertPunctuationsOpt . val )
s = getUnicodeReplacement ( s , unicodeConversionList . punctuation , ranges , ta ) ;
if ( $ . Options . unicodeConversion . val === 'enable' || $ . Options . convertEmotionsOpt . val )
s = getUnicodeReplacement ( s , unicodeConversionList . emotions , ranges , ta ) ;
if ( $ . Options . unicodeConversion . val === 'enable' || $ . Options . convertSignsOpt . val )
s = getUnicodeReplacement ( s , unicodeConversionList . signs , ranges , ta ) ;
if ( $ . Options . unicodeConversion . val === 'enable' || $ . Options . convertFractionsOpt . val )
s = getUnicodeReplacement ( s , unicodeConversionList . fractions , ranges , ta ) ;
if ( ta . data ( 'unicodeConversionStack' ) . length > 0 ) {
var ub = ta . closest ( '.post-area-new' ) . find ( '.undo-unicode' ) ;
ub . text ( polyglot . t ( 'undo' ) + ': ' + ta . data ( 'unicodeConversionStack' ) [ 0 ] . u ) ;
2014-04-07 16:11:41 +00:00
$ . MAL . enableButton ( ub ) ;
2015-05-19 18:33:59 +00:00
} else
2015-05-23 17:26:23 +00:00
$ . MAL . disableButton ( ta . closest ( '.post-area-new' ) . find ( '.undo-unicode' ) ) ;
2014-04-07 16:11:41 +00:00
2014-07-31 18:43:01 +00:00
return s ;
2014-04-07 16:11:41 +00:00
}
function undoLastUnicode ( e ) {
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
2015-05-23 17:26:23 +00:00
var $ta = $ ( this ) . closest ( '.post-area-new' ) . find ( 'textarea' ) ;
if ( $ta . data ( 'unicodeConversionStack' ) . length === 0 )
2014-04-07 16:11:41 +00:00
return ;
2015-05-23 17:26:23 +00:00
var uc = $ta . data ( 'unicodeConversionStack' ) . shift ( ) ;
2014-04-07 16:11:41 +00:00
var pt = $ta . val ( ) ;
2014-10-16 08:47:08 +00:00
2014-07-31 18:43:01 +00:00
// If the text was shifted, and character is no longer at the saved position, this function
// searches for it to the right. If it is not there, it searches in the oposite direction.
// if it's not there either, it means it was deleted, so it is skipped.
var substrLeft = pt . substring ( 0 , uc . p ) ;
var substrRight = pt . substring ( uc . p , pt . length ) ;
2015-05-23 17:26:23 +00:00
if ( substrRight . search ( uc . u ) !== - 1 ) {
2014-07-31 18:43:01 +00:00
substrRight = substrRight . replace ( uc . u , uc . k ) ;
$ta . val ( substrLeft + substrRight ) ;
2015-05-23 17:26:23 +00:00
$ta . data ( 'disabledUnicodeRules' ) . push ( uc . u ) ;
} else if ( substrLeft . search ( uc . u ) !== - 1 ) {
2014-07-31 18:43:01 +00:00
var closestToTheLeft = substrLeft . lastIndexOf ( uc . u ) ;
var substrCenter = substrLeft . substring ( closestToTheLeft , substrLeft . length ) . replace ( uc . u , uc . k ) ;
substrLeft = substrLeft . substring ( 0 , closestToTheLeft ) ;
$ta . val ( substrLeft + substrCenter + substrRight ) ;
2015-05-23 17:26:23 +00:00
$ta . data ( 'disabledUnicodeRules' ) . push ( uc . u ) ;
2014-04-07 17:22:47 +00:00
}
2014-04-07 16:11:41 +00:00
2015-05-23 17:26:23 +00:00
if ( $ta . data ( 'unicodeConversionStack' ) . length > 0 )
$ ( this ) . text ( polyglot . t ( 'undo' ) + ': ' + $ta . data ( 'unicodeConversionStack' ) [ 0 ] . u ) ;
else {
$ ( this ) . text ( 'undo' ) ;
2014-04-07 16:11:41 +00:00
$ . MAL . disableButton ( $ ( this ) ) ;
2014-07-31 18:43:01 +00:00
}
2014-04-07 16:11:41 +00:00
}
2015-05-23 17:26:23 +00:00
function postSubmit ( e , oldLastPostId ) {
2015-08-12 17:10:42 +00:00
var btnPostSubmit ;
2014-05-19 19:00:31 +00:00
if ( e instanceof $ ) {
2015-08-12 17:10:42 +00:00
btnPostSubmit = e ;
2014-05-19 19:00:31 +00:00
//check if previous part was sent...
2015-05-23 17:26:23 +00:00
if ( oldLastPostId === lastPostId ) {
2015-08-12 17:10:42 +00:00
setTimeout ( postSubmit , 1000 , btnPostSubmit , oldLastPostId ) ;
2014-05-20 13:17:31 +00:00
return ;
}
2014-05-19 19:00:31 +00:00
} else {
2014-04-16 22:21:17 +00:00
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
2015-08-12 17:10:42 +00:00
btnPostSubmit = $ ( this ) ;
2014-04-16 22:21:17 +00:00
}
2015-08-12 17:10:42 +00:00
$ . MAL . disableButton ( btnPostSubmit ) ;
2014-05-19 19:00:31 +00:00
2015-08-12 17:10:42 +00:00
var textArea = btnPostSubmit . closest ( '.post-area-new' ) . find ( 'textarea' ) ;
2013-12-30 14:42:36 +00:00
2015-08-20 12:31:16 +00:00
textArea . siblings ( '#post-preview' ) . slideUp ( 'fast' ) ;
2015-07-24 21:19:52 +00:00
2015-08-12 17:10:42 +00:00
var postData = btnPostSubmit . closest ( '.post-data' ) ;
if ( ! postData . length ) {
postData = btnPostSubmit . closest ( '.modal-content' ) . find ( '.post-data' ) ;
2014-01-11 00:23:39 +00:00
}
2014-04-16 22:21:17 +00:00
2015-08-12 17:10:42 +00:00
if ( btnPostSubmit . hasClass ( 'with-reference' ) ) {
2015-08-13 14:05:15 +00:00
var doSubmitPost = function ( postText , postData ) {
2015-08-12 17:10:42 +00:00
newRtMsg ( postData , postText ) ;
}
} else {
if ( splitedPostsCount > 1 ) {
if ( textArea . length < splitedPostsCount ) {
//current part will be sent as reply to the previous part...
postData = $ ( '<div data-id="' + lastPostId + '" data-screen-name="' + defaultScreenName + '"></div>' ) ;
}
}
2015-08-13 14:05:15 +00:00
var doSubmitPost = function ( postText , postData ) {
2015-08-12 17:10:42 +00:00
newPostMsg ( postText , postData ) ;
2014-04-16 22:21:17 +00:00
}
}
2015-08-12 17:10:42 +00:00
if ( textArea . length <= 1 ) {
2014-05-08 20:28:16 +00:00
if ( splitedPostsCount > 1 ) {
2015-08-12 17:10:42 +00:00
var postText = '' ;
var reply _to = textArea . attr ( 'data-reply-to' ) ;
var val = textArea . val ( ) ;
2015-05-23 17:26:23 +00:00
if ( typeof reply _to === 'undefined' || checkPostForMentions ( val , reply _to , 140 ) )
2015-08-12 17:10:42 +00:00
postText = val + ' (' + splitedPostsCount . toString ( ) + '/' + splitedPostsCount . toString ( ) + ')' ;
2014-05-08 20:28:16 +00:00
else
2015-08-12 17:10:42 +00:00
postText = reply _to + val + ' (' + splitedPostsCount . toString ( ) + '/' + splitedPostsCount . toString ( ) + ')' ;
2014-05-08 20:28:16 +00:00
2015-08-12 17:10:42 +00:00
doSubmitPost ( postText , postData ) ;
2014-05-08 20:28:16 +00:00
} else
2015-08-12 17:10:42 +00:00
doSubmitPost ( textArea . val ( ) , postData ) ;
2014-04-16 22:21:17 +00:00
splitedPostsCount = 1 ;
} else {
2015-08-12 17:10:42 +00:00
var postText = '' ;
var reply _to = textArea . attr ( 'data-reply-to' ) ;
var val = textArea [ 0 ] . value ;
2015-05-23 17:26:23 +00:00
if ( typeof reply _to === 'undefined' || checkPostForMentions ( val , reply _to , 140 ) )
2015-08-12 17:10:42 +00:00
postText = val + ' (' + ( splitedPostsCount - textArea . length + 1 ) . toString ( ) + '/' + splitedPostsCount . toString ( ) + ')' ;
2014-05-11 19:18:33 +00:00
else
2015-08-12 17:10:42 +00:00
postText = reply _to + val + ' (' + ( splitedPostsCount - textArea . length + 1 ) . toString ( ) + '/' + splitedPostsCount . toString ( ) + ')' ;
2014-05-08 20:28:16 +00:00
2015-08-12 17:10:42 +00:00
$ ( textArea [ 0 ] ) . remove ( ) ;
2014-04-16 22:21:17 +00:00
2014-05-20 13:17:31 +00:00
oldLastPostId = lastPostId ;
2015-08-12 17:10:42 +00:00
doSubmitPost ( postText , postData ) ;
setTimeout ( postSubmit , 1000 , btnPostSubmit , oldLastPostId ) ;
2014-04-16 22:21:17 +00:00
return ;
}
2013-12-30 14:42:36 +00:00
2015-10-23 20:39:22 +00:00
if ( btnPostSubmit . closest ( '.prompt-wrapper' ) . length )
2015-09-03 22:21:33 +00:00
closePrompt ( ) ;
2015-08-12 17:10:42 +00:00
else {
textArea . val ( '' ) . attr ( 'placeholder' , polyglot . t ( 'Your message was sent!' ) ) ;
2015-10-23 20:39:22 +00:00
var tweetForm = btnPostSubmit . closest ( 'form' ) ;
2015-08-12 17:10:42 +00:00
var remainingCount = tweetForm . find ( '.post-area-remaining' ) ;
remainingCount . text ( 140 ) ;
if ( btnPostSubmit . closest ( '.post-area,.post-reply-content' ) ) {
$ ( '.post-area-new' ) . removeClass ( 'open' ) . find ( 'textarea' ) . blur ( ) ;
} ;
textArea . data ( 'unicodeConversionStack' , [ ] ) ;
textArea . data ( 'disabledUnicodeRules' , [ ] ) ;
}
2013-12-30 14:42:36 +00:00
}
2015-05-23 17:26:23 +00:00
function retweetSubmit ( e ) {
2013-12-30 14:42:36 +00:00
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
2015-05-23 17:26:23 +00:00
newRtMsg ( $ ( this ) . closest ( '.prompt-wrapper' ) . find ( '.post-data' ) ) ;
2013-12-30 14:42:36 +00:00
2015-09-03 22:21:33 +00:00
closePrompt ( ) ;
2013-12-30 14:42:36 +00:00
}
2014-04-10 21:57:49 +00:00
function changeStyle ( ) {
var style , profile , menu ;
2015-05-19 18:33:59 +00:00
var theme = $ . Options . theme . val ;
2014-09-19 22:09:08 +00:00
2015-05-23 17:26:23 +00:00
if ( theme === 'nin' ) {
2014-09-19 22:09:08 +00:00
style = 'theme_nin/css/style.css' ;
profile = 'theme_nin/css/profile.css' ;
$ . getScript ( 'theme_nin/js/theme_option.js' ) ;
2015-05-23 17:26:23 +00:00
} else if ( theme === 'calm' ) {
2014-04-10 21:57:49 +00:00
style = 'theme_calm/css/style.css' ;
profile = 'theme_calm/css/profile.css' ;
2015-05-23 17:26:23 +00:00
} else if ( theme === 'original' ) {
2014-09-19 22:09:08 +00:00
style = 'css/style.css' ;
profile = 'css/profile.css' ;
2014-11-04 16:34:42 +00:00
$ . getScript ( 'theme_original/js/theme_option.js' ) ;
2014-09-19 22:09:08 +00:00
}
2014-11-04 16:34:42 +00:00
2014-04-10 21:57:49 +00:00
$ ( '#stylecss' ) . attr ( 'href' , style ) ;
$ ( '#profilecss' ) . attr ( 'href' , profile ) ;
2015-05-23 17:26:23 +00:00
$ ( '<style type="text/css"> .selectable_theme:not(.theme_' + theme + ')' +
'{display:none!important;}\n</style>' ) . appendTo ( 'head' ) ;
setTimeout ( function ( ) { $ ( menu ) . removeAttr ( 'style' ) ; } , 0 ) ;
2014-04-10 21:57:49 +00:00
}
2013-12-30 14:42:36 +00:00
2015-03-30 00:16:41 +00:00
function getMentionsForAutoComplete ( ) {
2015-05-23 17:26:23 +00:00
if ( defaultScreenName && typeof followingUsers !== 'undefined' ) {
2015-03-30 00:16:41 +00:00
var suggests = followingUsers . slice ( ) ;
if ( suggests . indexOf ( defaultScreenName ) > - 1 )
suggests . splice ( suggests . indexOf ( defaultScreenName ) , 1 ) ;
if ( suggests . length > 0 ) {
suggests . sort ( ) ;
return [ {
mentions : suggests ,
match : /\B@(\w*)$/ ,
search : function ( term , callback ) {
callback ( $ . map ( this . mentions , function ( mention ) {
return mention . indexOf ( term ) === 0 ? mention : null ;
} ) ) ;
} ,
index : 1 ,
replace : function ( mention ) {
return '@' + mention + ' ' ;
}
} ] ;
2014-04-10 21:57:49 +00:00
}
}
}
2013-12-30 14:42:36 +00:00
2014-05-20 16:38:34 +00:00
function replaceDashboards ( ) {
2015-05-23 17:26:23 +00:00
var width = $ ( window ) . width ( ) ;
var wrapper = $ ( '.wrapper' ) ;
if ( width >= 1200 && ! wrapper . hasClass ( 'w1200' ) ) {
wrapper . addClass ( 'w1200' ) ;
2014-05-20 16:38:34 +00:00
$ ( '.userMenu' ) . addClass ( 'w1200' ) ;
2015-04-20 21:00:05 +00:00
$ ( '.module.who-to-follow' ) . detach ( ) . appendTo ( $ ( '.dashboard.right' ) ) ;
$ ( '.module.twistday-reminder' ) . detach ( ) . appendTo ( $ ( '.dashboard.right' ) ) ;
2015-05-23 17:26:23 +00:00
} else if ( width < 1200 && wrapper . hasClass ( 'w1200' ) ) {
wrapper . removeClass ( 'w1200' ) ;
2014-05-20 16:38:34 +00:00
$ ( '.userMenu' ) . removeClass ( 'w1200' ) ;
2015-04-20 21:00:05 +00:00
$ ( '.module.who-to-follow' ) . detach ( ) . insertAfter ( $ ( '.module.mini-profile' ) ) ;
$ ( '.module.twistday-reminder' ) . detach ( ) . insertAfter ( $ ( '.module.toptrends' ) ) ;
2014-05-20 16:38:34 +00:00
}
}
2013-12-30 14:42:36 +00:00
function initInterfaceCommon ( ) {
2015-09-03 22:21:33 +00:00
$ ( '.modal-close, .modal-blackout' ) . not ( '.prompt-close' ) . on ( 'click' , function ( ) {
2015-05-23 17:26:23 +00:00
if ( $ ( '.modal-content' ) . attr ( 'style' ) != undefined )
$ ( '.modal-content' ) . removeAttr ( 'style' ) ;
2014-04-10 21:57:49 +00:00
$ ( '.modal-back' ) . css ( 'display' , 'none' ) ;
2014-05-07 10:28:16 +00:00
$ ( '.mark-all-as-read' ) . css ( 'display' , 'none' ) ;
2015-05-23 17:26:23 +00:00
closeModal ( ) ;
2014-04-10 21:57:49 +00:00
} ) ;
2015-01-21 11:10:04 +00:00
2015-07-19 00:23:50 +00:00
$ ( '.modal-back' ) . on ( 'click' , function ( ) { history . back ( ) ; } ) ;
2015-09-03 22:21:33 +00:00
$ ( '.prompt-close' ) . on ( 'click' , closePrompt ) ;
2015-01-22 14:59:00 +00:00
2015-01-21 11:10:04 +00:00
/ *
2015-05-23 17:26:23 +00:00
$ ( '.modal-back' ) . on ( 'click' , function ( ) {
if ( $ ( '.modal-content .direct-messages-list' ) [ 0 ] ) return ;
2014-04-10 21:57:49 +00:00
directMessagesPopup ( ) ;
2015-05-23 17:26:23 +00:00
$ ( '.modal-content' ) . removeAttr ( 'style' ) ;
2014-04-10 21:57:49 +00:00
} ) ;
2015-01-21 11:10:04 +00:00
* /
2015-05-23 17:26:23 +00:00
$ ( '.post-text' ) . on ( 'click' , 'a' , function ( e ) { e . stopPropagation ( ) ; } ) ;
$ ( '.post-reply' ) . on ( 'click' , postReplyClick ) ;
$ ( '.post-propagate' ) . on ( 'click' , reTwistPopup ) ;
$ ( '.userMenu-config' ) . clickoutside ( closeThis . bind ( $ ( '.config-menu' ) ) ) ;
$ ( '.userMenu-config-dropdown' ) . on ( 'click' , dropDownMenu ) ;
$ ( '.module.post' ) . on ( 'click' , function ( e ) {
if ( e . button === 0 && window . getSelection ( ) == 0 )
postExpandFunction ( e , $ ( this ) ) ;
2015-03-01 08:31:56 +00:00
} ) ;
2015-05-23 17:26:23 +00:00
$ ( '.post-area-new' )
. on ( 'click' , function ( e ) { composeNewPost ( e , $ ( this ) ) ; } )
. clickoutside ( unfocusThis )
. children ( 'textarea' )
. on ( {
2015-07-23 19:51:24 +00:00
'focus' : posPostPreview ,
2015-05-23 17:26:23 +00:00
'input' : replyTextInput , // input event fires in modern browsers (IE9+) on any changes in textarea (and copypasting with mouse too)
'input focus' : replyTextUpdateRemaining ,
'keyup' : replyTextKeySend
} )
;
$ ( '.post-submit' ) . on ( 'click' , postSubmit ) ;
$ ( '.modal-propagate' ) . on ( 'click' , retweetSubmit ) ;
2015-08-14 21:17:17 +00:00
$ ( '.expanded-content .show-more' ) . on ( 'click' ,
{ feeder : '.module.post.original.open .module.post.original .post-data' } , openConversationClick ) ;
2013-12-30 14:42:36 +00:00
2015-05-19 18:33:59 +00:00
if ( $ . Options . unicodeConversion . val === 'disable' )
2015-05-23 17:26:23 +00:00
$ ( '.undo-unicode' ) . on ( 'click' , undoLastUnicode ) . css ( 'display' , 'none' ) ;
2014-04-07 16:11:41 +00:00
else
2015-05-23 17:26:23 +00:00
$ ( '.undo-unicode' ) . on ( 'click' , undoLastUnicode ) ;
2014-04-07 16:11:41 +00:00
2015-05-23 17:26:23 +00:00
$ ( '.open-profile-modal' ) . on ( 'click' , function ( e ) { e . stopPropagation ( ) ; } ) ;
//$('.open-hashtag-modal').on('click', openHashtagModal);
//$('.open-following-modal').on('click', openFollowingModal);
$ ( '.userMenu-connections a' ) . on ( 'click' , openMentionsModal ) ;
$ ( '.mentions-from-user' ) . on ( 'click' , openMentionsModal ) ;
2013-12-30 14:42:36 +00:00
2015-05-23 17:26:23 +00:00
$ ( '#hashtag-modal-template .postboard-news' ) . on ( 'click' , function ( ) {
$ ( this ) . hide ( ) ;
displayHashtagPending ( $ ( '.hashtag-modal .postboard-posts' ) ) ;
} ) ;
2014-03-25 03:01:30 +00:00
2014-05-20 16:38:34 +00:00
replaceDashboards ( ) ;
2015-05-23 17:26:23 +00:00
$ ( window ) . resize ( replaceDashboards ) ;
2015-04-14 17:39:20 +00:00
2015-10-23 20:20:41 +00:00
$ ( '.profile-card .profile-bio .group-description' )
. on ( 'focus' , function ( event ) {
$ ( event . target )
. siblings ( '.save' ) . show ( )
. siblings ( '.cancel' ) . show ( )
;
} )
. on ( 'input' ,
{ parentSelector : '.profile-bio' , enterSelector : '.save' } , inputEnterActivator )
. siblings ( '.save' ) . on ( 'click' , function ( event ) {
var elemEvent = $ ( event . target ) ;
var descElem = elemEvent . siblings ( '.group-description' ) ;
groupMsgSetGroupDescription ( elemEvent . closest ( '.profile-card' ) . attr ( 'data-screen-name' ) ,
descElem . val ( ) . trim ( ) ,
function ( req ) {
req . descElem . attr ( 'val-origin' , req . descElem . val ( ) . trim ( ) )
. siblings ( '.save' ) . hide ( )
. siblings ( '.cancel' ) . hide ( )
;
} , { descElem : descElem }
) ;
} )
. siblings ( '.cancel' ) . on ( 'click' , function ( event ) { // FIXME it would be nice to bind some 'clickoutside' event instead and remove cancel button, but current implementation of that doesn't unbind events when element dies
var descElem = $ ( event . target ) . hide ( )
. siblings ( '.save' ) . hide ( )
. siblings ( '.group-description' )
;
descElem . val ( descElem . attr ( 'val-origin' ) ) ;
} )
;
2015-05-23 17:26:23 +00:00
$ ( '.tox-ctc' ) . on ( 'click' , promptCopyAttrData ) ;
$ ( '.bitmessage-ctc' ) . on ( 'click' , promptCopyAttrData ) ;
2015-03-30 00:16:41 +00:00
2015-05-23 17:26:23 +00:00
if ( $ . fn . textcomplete ) {
2015-09-04 23:14:16 +00:00
$ ( '.post-area-new textarea' )
. on ( 'focus' , { req : getMentionsForAutoComplete } , setTextcompleteOnEventTarget )
. on ( 'focusout' , unsetTextcompleteOnEventTarget )
;
2015-03-30 00:16:41 +00:00
}
}
2015-05-23 17:26:23 +00:00
function promptCopyAttrData ( event ) {
window . prompt ( polyglot . t ( 'copy_to_clipboard' ) , $ ( event . target ) . attr ( 'data' ) ) ;
}
2015-04-20 21:00:05 +00:00
function initInterfaceModule ( module ) {
return $ ( '.module.' + module ) . html ( $ ( '#' + module + '-template' ) . html ( ) ) . show ( ) ;
}
function killInterfaceModule ( module ) {
$ ( '.module.' + module ) . empty ( ) . hide ( ) ;
}
2015-03-30 00:16:41 +00:00
2015-10-21 21:05:18 +00:00
function elemFitNextIntoParentHeight ( elem ) {
var parent = elem . parent ( ) ;
var elemNext = elem . nextAll ( ) ;
var elemNextHeight = parent . actual ( 'height' ) - elem . actual ( 'outerHeight' , { includeMargin : true } ) ;
if ( elemNextHeight > 0 ) // FIXME actually it's here because of nin theme's two vertical columns layout of profile modal
elemNext . outerHeight ( elemNextHeight ) ;
else
elemNext . outerHeight ( parent . actual ( 'outerHeight' ) ) ;
}
2015-09-03 22:21:33 +00:00
function inputEnterActivator ( event ) {
var elemEvent = $ ( event . target ) ;
2015-10-23 20:39:22 +00:00
elemEvent . closest ( event . data . parentSelector ) . find ( event . data . enterSelector )
2015-09-03 22:21:33 +00:00
. attr ( 'disabled' , elemEvent . val ( ) . trim ( ) === '' ) ;
}
2015-05-23 17:26:23 +00:00
function setTextcompleteOnEventTarget ( event ) {
// cursor has not set yet and we need to wait 100ms to skip global click event
2015-09-04 23:14:16 +00:00
setTimeout ( setTextcompleteOnElement , 100 , event . target ,
typeof event . data . req === 'function' ? event . data . req ( ) : event . data . req ) ;
2015-04-14 17:39:20 +00:00
}
2015-09-04 23:14:16 +00:00
function setTextcompleteOnElement ( elem , req ) {
2015-05-23 17:26:23 +00:00
elem = $ ( elem ) ;
2015-09-04 23:14:16 +00:00
elem . textcomplete ( req , {
2015-10-23 20:39:22 +00:00
appendTo : ( elem . closest ( '.dashboard' ) . length ) ? elem . parent ( ) : $ ( 'body' ) ,
2015-05-23 17:26:23 +00:00
listPosition : setTextcompleteDropdownListPos
} ) ;
2015-04-10 01:59:57 +00:00
}
2015-09-04 23:14:16 +00:00
function unsetTextcompleteOnEventTarget ( event ) {
$ ( event . target ) . textcomplete ( 'destroy' ) ;
}
2015-03-30 00:16:41 +00:00
// following workaround function is for calls from $.fn.textcomplete only
// we need this because currently implementation of caret position detection is way too imperfect
function setTextcompleteDropdownListPos ( position ) {
position = this . _applyPlacement ( position ) ;
2015-10-23 20:39:22 +00:00
if ( this . option . appendTo . closest ( '.dashboard' ) . length > 0 ) {
2015-05-23 17:26:23 +00:00
position . position = 'fixed' ;
position . top = ( parseFloat ( position . top ) - window . pageYOffset ) . toString ( ) + 'px' ;
} else
position . position = 'absolute' ;
2015-03-30 00:16:41 +00:00
this . $el . css ( position ) ;
return this ;
2014-01-18 15:09:32 +00:00
}
2015-07-17 20:17:28 +00:00
$ ( document ) . ready ( function ( )
{
var path = window . location . pathname ;
var page = path . split ( "/" ) . pop ( ) ;
if ( page . indexOf ( "following.html" ) === 0 ) {
initInterfaceFollowing ( ) ;
} else if ( page . indexOf ( "login.html" ) === 0 ) {
initInterfaceLogin ( ) ;
} else if ( page . indexOf ( "network.html" ) === 0 ) {
initInterfaceNetwork ( ) ;
2015-07-19 00:23:50 +00:00
} else if ( page . indexOf ( 'options.html' ) === 0 ) {
initInterfaceCommon ( ) ;
$ . Options . initControls ( ) ;
2015-07-17 20:17:28 +00:00
} else if ( page . indexOf ( "profile-edit.html" ) === 0 ) {
initProfileEdit ( ) ;
}
changeStyle ( ) ;
} ) ;