2013-08-19 22:30:57 +09:00
/ * · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
· ·
· ·
· Q V I T T E R ·
· ·
· http : //github.com/hannesmannerheim/qvitter ·
· ·
· ·
· < o ) ·
· / _ //// ·
· ( _ _ _ _ / ·
· ( o < ·
· o > \ \ \ \ _ \ ·
· \ \ ) \ _ _ _ _ ) ·
· ·
· ·
· ·
· Qvitter is free software : you can redistribute it and / or modify it ·
· under the terms of the GNU Affero General Public License as published by ·
· the Free Software Foundation , either version three of the License or ( at ·
· your option ) any later version . ·
· ·
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
· WARRANTY ; without even the implied warranty of MERCHANTABILTY or FITNESS ·
· FOR A PARTICULAR PURPOSE . See the GNU Affero General Public License for ·
· more details . ·
· ·
· You should have received a copy of the GNU Affero General Public License ·
· along with Qvitter . If not , see < http : //www.gnu.org/licenses/>. ·
· ·
· Contact h @ nnesmannerhe . im if you have any questions . ·
· ·
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · * /
2013-08-26 03:11:53 +09:00
2014-01-29 03:42:47 +09:00
// object to keep old states of streams in, to speed up stream change
window . oldStreams = new Object ( ) ;
2013-08-19 22:30:57 +09:00
/ * ·
·
2014-05-14 16:46:07 +09:00
· Update stream on back button
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · · · · · * /
2014-05-14 16:46:07 +09:00
window . onpopstate = function ( event ) {
if ( event && event . state ) {
display _spinner ( ) ;
setNewCurrentStream ( event . state . strm , function ( ) {
remove _spinner ( ) ;
} , false ) ;
2013-08-19 22:30:57 +09:00
}
}
2013-09-03 01:13:15 +09:00
/ * ·
·
· fix login and register box to top when they reach top
·
· · · · · · · · · · · · · * /
$ ( window ) . scroll ( function ( e ) {
2014-09-25 06:20:35 +09:00
if ( $ ( this ) . scrollTop ( ) > ( $ ( '#feed' ) . offset ( ) . top - 50 ) && $ ( '#login-content' ) . css ( 'position' ) != 'fixed' ) {
2013-09-03 01:13:15 +09:00
$ ( '#login-content, .front-signup' ) . not ( '#popup-signup' ) . css ( { 'position' : 'fixed' , 'top' : '50px' } ) ;
}
2014-09-25 06:20:35 +09:00
else if ( $ ( this ) . scrollTop ( ) < ( $ ( '#feed' ) . offset ( ) . top - 50 ) && $ ( '#login-content' ) . css ( 'position' ) != 'absolute' ) {
2013-09-03 01:13:15 +09:00
$ ( '#login-content, .front-signup' ) . not ( '#popup-signup' ) . css ( { 'position' : 'absolute' , 'top' : 'auto' } ) ;
}
} ) ;
/ * ·
·
· Tooltip to show what federated means
·
· · · · · · · · · · · · · * /
$ ( '#federated-tooltip' ) . on ( 'mouseenter' , function ( ) {
$ ( '#what-is-federation' ) . fadeIn ( 100 ) ;
} ) ;
$ ( '#what-is-federation' ) . on ( 'mouseleave' , function ( ) {
$ ( '#what-is-federation' ) . fadeOut ( 100 ) ;
} ) ;
/ * ·
·
· Register
·
· · · · · · · · · · · · · * /
2014-05-16 11:07:30 +09:00
if ( ! window . registrationsClosed ) {
$ ( '.front-signup input, .front-signup button' ) . removeAttr ( 'disabled' ) ; // clear this onload
$ ( '#signup-btn-step1' ) . click ( function ( ) {
2014-11-28 05:04:41 +09:00
$ ( document ) . trigger ( 'onClickStep1Register' ) ; // hook
2014-01-29 03:42:47 +09:00
2014-05-16 11:07:30 +09:00
display _spinner ( ) ;
$ ( '.front-signup input, .front-signup button' ) . addClass ( 'disabled' ) ;
$ ( '.front-signup input, .front-signup button' ) . attr ( 'disabled' , 'disabled' ) ;
// 7 s timeout to annoy human spammers
setTimeout ( function ( ) {
remove _spinner ( ) ;
popUpAction ( 'popup-register' , window . sL . signUp , '<div id="popup-signup" class="front-signup">' +
'<div class="signup-input-container"><div id="atsign">@</div><input placeholder="' + window . sL . registerNickname + '" type="text" autocomplete="off" class="text-input" id="signup-user-nickname-step2"><div class="fieldhelp">a-z0-9</div></div>' +
'<div class="signup-input-container"><input placeholder="' + window . sL . signUpFullName + '" type="text" autocomplete="off" class="text-input" id="signup-user-name-step2" value="' + $ ( '#signup-user-name' ) . val ( ) + '"></div>' +
'<div class="signup-input-container"><input placeholder="' + window . sL . signUpEmail + '" type="text" autocomplete="off" id="signup-user-email-step2" value="' + $ ( '#signup-user-email' ) . val ( ) + '"></div>' +
'<div class="signup-input-container"><input placeholder="' + window . sL . registerHomepage + '" type="text" autocomplete="off" class="text-input" id="signup-user-homepage-step2"></div>' +
'<div class="signup-input-container"><input placeholder="' + window . sL . registerBio + '" type="text" autocomplete="off" class="text-input" id="signup-user-bio-step2"></div>' +
'<div class="signup-input-container"><input placeholder="' + window . sL . registerLocation + '" type="text" autocomplete="off" class="text-input" id="signup-user-location-step2"></div>' +
'<div class="signup-input-container"><input placeholder="' + window . sL . loginPassword + '" type="password" class="text-input" id="signup-user-password1-step2" value="' + $ ( '#signup-user-password' ) . val ( ) + '"><div class="fieldhelp">>5</div></div>' +
'<div class="signup-input-container"><input placeholder="' + window . sL . registerRepeatPassword + '" type="password" class="text-input" id="signup-user-password2-step2"></div>' +
2015-01-26 23:58:42 +09:00
'<div id="signup-terms-header">' + window . sL . showTerms . replace ( /{site-title}/g , window . siteTitle ) + '</div><div id="signup-terms-container"></div>' +
2014-05-16 11:07:30 +09:00
'<button id="signup-btn-step2" class="signup-btn disabled" type="submit">' + window . sL . signUpButtonText + '</button>' +
'</div>' , false ) ;
2013-09-03 01:13:15 +09:00
2014-05-16 11:07:30 +09:00
// ask api if nickname is ok, if no typing for 1 s
$ ( '#signup-user-nickname-step2' ) . on ( 'keyup' , function ( ) {
clearTimeout ( window . checkNicknameTimeout ) ;
if ( $ ( '#signup-user-nickname-step2' ) . val ( ) . length > 1 && /^[a-zA-Z0-9]+$/ . test ( $ ( '#signup-user-nickname-step2' ) . val ( ) ) ) {
$ ( '#signup-user-nickname-step2' ) . addClass ( 'nickname-taken' ) ;
if ( $ ( '.spinner-wrap' ) . length == 0 ) {
$ ( '#signup-user-nickname-step2' ) . after ( '<div class="spinner-wrap"><div class="spinner"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div></div>' ) ;
}
window . checkNicknameTimeout = setTimeout ( function ( ) {
2014-09-25 06:20:35 +09:00
$ . get ( window . apiRoot + 'check_nickname.json?nickname=' + encodeURIComponent ( $ ( '#signup-user-nickname-step2' ) . val ( ) ) , function ( data ) {
2014-05-16 11:07:30 +09:00
$ ( '.spinner-wrap' ) . remove ( ) ;
2014-09-25 06:20:35 +09:00
if ( data == 0 ) {
2014-05-16 11:07:30 +09:00
$ ( '#signup-user-password2-step2' ) . trigger ( 'keyup' ) ; // revalidates
}
2014-05-28 03:40:51 +09:00
else {
2014-05-16 11:07:30 +09:00
$ ( '#signup-user-nickname-step2' ) . removeClass ( 'nickname-taken' ) ;
$ ( '#signup-user-password2-step2' ) . trigger ( 'keyup' ) ;
}
} ) ;
} , 1000 ) ;
}
else {
$ ( '.spinner-wrap' ) . remove ( ) ;
}
} ) ;
2013-09-03 01:13:15 +09:00
2014-05-16 11:07:30 +09:00
// validate on keyup
$ ( '#popup-register input' ) . on ( 'keyup' , function ( ) {
if ( validateRegisterForm ( $ ( '#popup-register' ) ) ) {
if ( ! $ ( '#signup-user-nickname-step2' ) . hasClass ( 'nickname-taken' ) ) {
$ ( '#signup-btn-step2' ) . removeClass ( 'disabled' ) ;
}
else {
$ ( '#signup-btn-step2' ) . addClass ( 'disabled' ) ;
}
2013-09-03 01:13:15 +09:00
}
else {
2014-05-16 11:07:30 +09:00
$ ( '#signup-btn-step2' ) . addClass ( 'disabled' ) ;
2013-09-03 01:13:15 +09:00
}
2014-05-16 11:07:30 +09:00
} ) ;
$ ( '#popup-register input' ) . trigger ( 'keyup' ) ;
2013-09-03 01:13:15 +09:00
2014-05-16 11:07:30 +09:00
// submit on enter
$ ( 'input#signup-user-name-step2,input#signup-user-email-step2,input#signup-user-password1-step2, input#signup-user-password2-step2' ) . keyup ( function ( e ) {
if ( e . keyCode == 13 ) {
$ ( '#signup-btn-step2' ) . trigger ( 'click' ) ;
}
} ) ;
2013-09-03 01:13:15 +09:00
2014-05-16 11:07:30 +09:00
$ ( '#signup-btn-step2' ) . click ( function ( ) {
2014-11-24 21:47:45 +09:00
if ( ! $ ( this ) . hasClass ( 'disabled' ) ) {
$ ( '#popup-register input,#popup-register button' ) . addClass ( 'disabled' ) ;
display _spinner ( ) ;
$ . ajax ( { url : window . apiRoot + 'account/register.json' ,
type : "POST" ,
data : {
nickname : $ ( '#signup-user-nickname-step2' ) . val ( ) ,
email : $ ( '#signup-user-email-step2' ) . val ( ) ,
fullname : $ ( '#signup-user-name-step2' ) . val ( ) ,
homepage : $ ( '#signup-user-homepage-step2' ) . val ( ) ,
bio : $ ( '#signup-user-bio-step2' ) . val ( ) ,
location : $ ( '#signup-user-location-step2' ) . val ( ) ,
password : $ ( '#signup-user-password1-step2' ) . val ( ) ,
confirm : $ ( '#signup-user-password2-step2' ) . val ( ) ,
cBS : window . cBS ,
cBSm : window . cBSm ,
username : 'none' ,
} ,
dataType : "json" ,
error : function ( data ) { console . log ( 'error' ) ; console . log ( data ) ; } ,
success : function ( data ) {
remove _spinner ( ) ;
if ( typeof data . error == 'undefined' ) {
$ ( 'input#nickname' ) . val ( $ ( '#signup-user-nickname-step2' ) . val ( ) ) ;
$ ( 'input#password' ) . val ( $ ( '#signup-user-password1-step2' ) . val ( ) ) ;
$ ( 'input#rememberme' ) . prop ( 'checked' , true ) ;
$ ( '#submit-login' ) . trigger ( 'click' ) ;
$ ( '#popup-register' ) . remove ( ) ;
}
else {
alert ( 'Try again! ' + data . error ) ;
$ ( '#popup-register input,#popup-register button' ) . removeClass ( 'disabled' ) ;
}
2013-09-03 01:13:15 +09:00
2014-11-24 21:47:45 +09:00
}
} ) ;
}
2014-05-16 11:07:30 +09:00
} ) ;
2013-09-03 01:13:15 +09:00
2014-05-16 11:07:30 +09:00
// reactivate register form on popup close
$ ( '#popup-register' ) . on ( 'remove' , function ( ) {
$ ( '.front-signup input, .front-signup button' ) . removeAttr ( 'disabled' ) ;
$ ( '.front-signup input, .front-signup button' ) . removeClass ( 'disabled' ) ;
} ) ;
} , 7000 ) ;
} ) ;
// submit on enter
$ ( 'input#signup-user-name,input#signup-user-email,input#signup-user-password' ) . keyup ( function ( e ) {
if ( e . keyCode == 13 ) {
$ ( '#signup-btn-step1' ) . trigger ( 'click' ) ;
}
} ) ;
}
2013-09-03 01:13:15 +09:00
2015-01-26 03:05:09 +09:00
/ * ·
·
· Show / hide Terms of Use
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'click' , '#signup-terms-header' , function ( ) {
if ( $ ( '#signup-terms-container' ) . text ( ) . length > 0 ) {
$ ( '#signup-terms-container' ) . html ( '' ) ;
}
else {
if ( window . customTermsOfUse ) {
$ ( '#signup-terms-container' ) . html ( window . customTermsOfUse ) ;
}
else {
getDoc ( 'terms' , function ( termsHtml ) {
$ ( '#signup-terms-container' ) . html ( termsHtml ) ;
} ) ;
}
}
} ) ;
2013-09-03 01:13:15 +09:00
2013-08-19 22:30:57 +09:00
/ * ·
·
2015-02-25 06:36:36 +09:00
· set language , autologin or show welcome screen
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · · · · · * /
$ ( '#submit-login' ) . removeAttr ( 'disabled' ) ; // might be remebered by browser...
2013-08-26 05:34:09 +09:00
$ ( window ) . load ( function ( ) {
2013-08-19 22:30:57 +09:00
2015-02-25 06:36:36 +09:00
// set language, from local storage, else browser language, else english (english also if no localstorage availible)
var browserLang = navigator . language || navigator . userLanguage ;
if ( browserLang . substring ( 0 , 5 ) . toLowerCase ( ) == 'zh-cn' ) {
browserLang = 'zh_cn' ;
}
else if ( browserLang . substring ( 0 , 5 ) . toLowerCase ( ) == 'zh-tw' ) {
browserLang = 'zh_tw' ;
2013-08-19 22:30:57 +09:00
}
else {
2015-02-25 06:36:36 +09:00
browserLang = browserLang . substring ( 0 , 2 ) ;
}
window . selectedLanguage = 'en' ;
if ( localStorageIsEnabled ( ) ) {
if ( typeof localStorage . selectedLanguage != 'undefined' && localStorage . selectedLanguage != null ) {
window . selectedLanguage = localStorage . selectedLanguage ;
}
2015-02-25 07:34:52 +09:00
else if ( typeof window . availableLanguages [ browserLang ] != 'undefined' ) {
2015-02-25 06:36:36 +09:00
window . selectedLanguage = browserLang ;
}
}
// if this is a RTL-language, add rt classes and change some things
if ( window . selectedLanguage == 'ar' ) {
$ ( 'body' ) . addClass ( 'rtl' ) ;
$ ( 'title' ) . html ( '‫ترك' ) ;
}
else if ( window . selectedLanguage == 'fa' ) {
$ ( 'body' ) . addClass ( 'rtl' ) ;
$ ( 'title' ) . html ( '‫واگذارنده' ) ;
}
2015-02-25 08:12:20 +09:00
// if we already have this version of this language in localstorage, we
// use that cached version. we do this because $.ajax doesn't respect caching, it seems
if ( localStorageIsEnabled ( )
&& ( typeof localStorage [ 'languageData-' + window . availableLanguages [ window . selectedLanguage ] ] != 'undefined' && localStorage [ 'languageData-' + window . availableLanguages [ window . selectedLanguage ] ] !== null ) ) {
proceedToSetLanguageAndLogin ( JSON . parse ( localStorage [ 'languageData-' + window . availableLanguages [ window . selectedLanguage ] ] ) ) ;
}
// if we need to get the language file from the server
else {
$ . ajax ( {
dataType : "json" ,
url : window . fullUrlToThisQvitterApp + 'locale/' + window . availableLanguages [ window . selectedLanguage ] ,
error : function ( data ) { console . log ( data ) } ,
success : function ( data ) {
// store this response in localstorage
if ( localStorageIsEnabled ( ) ) {
localStorage [ 'languageData-' + window . availableLanguages [ window . selectedLanguage ] ] = JSON . stringify ( data ) ;
}
proceedToSetLanguageAndLogin ( data ) ;
}
} ) ;
2015-02-25 06:36:36 +09:00
2015-02-25 08:12:20 +09:00
}
2015-02-25 06:36:36 +09:00
2015-02-25 08:12:20 +09:00
} ) ;
// proceed to set language and login
function proceedToSetLanguageAndLogin ( data ) {
window . sL = data ;
2015-02-25 06:36:36 +09:00
2015-02-25 08:12:20 +09:00
window . siteTitle = $ ( 'head title' ) . html ( ) ; // remember this for later use
2015-02-25 06:36:36 +09:00
2015-02-25 08:12:20 +09:00
// replace placeholders in translation
$ . each ( window . sL , function ( k , v ) {
window . sL [ k ] = v . replace ( /{site-title}/g , window . siteTitle ) ;
2015-02-25 06:36:36 +09:00
} ) ;
2015-02-25 08:12:20 +09:00
// set some static string
$ ( '.front-welcome-text h1' ) . html ( window . sL . welcomeHeading ) ;
if ( window . enableWelcomeText ) {
$ ( '.front-welcome-text p' ) . html ( window . sL . welcomeText ) ;
}
$ ( '#nickname' ) . attr ( 'placeholder' , window . sL . loginUsername ) ;
$ ( '#password' ) . attr ( 'placeholder' , window . sL . loginPassword ) ;
$ ( 'button#submit-login' ) . html ( window . sL . loginSignIn ) ;
$ ( '#rememberme_label' ) . html ( window . sL . loginRememberMe ) ;
$ ( '#forgot-password' ) . html ( window . sL . loginForgotPassword ) ;
$ ( '.front-signup h2' ) . html ( '<strong>' + window . sL . newToQuitter + '</strong> ' + window . sL . signUp ) ;
$ ( '#signup-user-name' ) . attr ( 'placeholder' , window . sL . signUpFullName ) ;
$ ( '#signup-user-email' ) . attr ( 'placeholder' , window . sL . signUpEmail ) ;
$ ( '#signup-user-password' ) . attr ( 'placeholder' , window . sL . loginPassword ) ;
$ ( '.front-signup button.signup-btn' ) . html ( window . sL . signUpButtonText ) ;
$ ( '#user-queets .label' ) . html ( window . sL . notices ) ;
$ ( '#user-following .label' ) . html ( window . sL . following ) ;
$ ( '#user-followers .label' ) . html ( window . sL . followers ) ;
$ ( '#user-groups .label' ) . html ( window . sL . groups ) ;
$ ( '#queet-box' ) . html ( window . sL . compose ) ;
$ ( '#queet-box' ) . attr ( 'data-start-text' , encodeURIComponent ( window . sL . compose ) ) ;
$ ( '#user-footer .queet-button button' ) . html ( window . sL . queetVerb ) ;
$ ( '#feed-header-inner h2' ) . html ( window . sL . queetsNounPlural ) ;
$ ( '#logout' ) . html ( window . sL . logout ) ;
$ ( '#settings' ) . html ( window . sL . settings ) ;
$ ( '#other-servers-link' ) . html ( window . sL . otherServers ) ;
$ ( '.language-dropdown .dropdown-toggle small' ) . html ( window . sL . languageSelected ) ;
$ ( '.language-dropdown .current-language' ) . html ( window . sL . languageName ) ;
$ ( '.stream-selection[data-stream-name="statuses/friends_timeline.json"]' ) . prepend ( window . sL . timeline ) ;
$ ( '.stream-selection[data-stream-name="statuses/friends_timeline.json"]' ) . attr ( 'data-stream-header' , window . sL . timeline ) ;
$ ( '.stream-selection[data-stream-name="statuses/mentions.json"]' ) . prepend ( window . sL . mentions ) ;
$ ( '.stream-selection[data-stream-name="statuses/mentions.json"]' ) . attr ( 'data-stream-header' , window . sL . mentions ) ;
$ ( '.stream-selection[data-stream-name="qvitter/statuses/notifications.json"]' ) . prepend ( window . sL . notifications ) ;
$ ( '.stream-selection[data-stream-name="qvitter/statuses/notifications.json"]' ) . attr ( 'data-stream-header' , window . sL . notifications ) ;
$ ( '.stream-selection[data-stream-name="favorites.json"]' ) . prepend ( window . sL . favoritesNoun ) ;
$ ( '.stream-selection[data-stream-name="favorites.json"]' ) . attr ( 'data-stream-header' , window . sL . favoritesNoun ) ;
$ ( '.stream-selection[data-stream-name="statuses/public_timeline.json"]' ) . prepend ( window . sL . publicTimeline ) ;
$ ( '.stream-selection[data-stream-name="statuses/public_timeline.json"]' ) . attr ( 'data-stream-header' , window . sL . publicTimeline ) ;
$ ( '.stream-selection[data-stream-name="statuses/public_and_external_timeline.json"]' ) . prepend ( window . sL . publicAndExtTimeline ) ;
$ ( '.stream-selection[data-stream-name="statuses/public_and_external_timeline.json"]' ) . attr ( 'data-stream-header' , window . sL . publicAndExtTimeline ) ;
$ ( '#search-query' ) . attr ( 'placeholder' , window . sL . searchVerb ) ;
$ ( '#faq-link' ) . html ( window . sL . FAQ ) ;
$ ( '#invite-link' ) . html ( window . sL . inviteAFriend ) ;
$ ( '#classic-link' ) . html ( 'Classic ' + window . siteTitle ) ;
$ ( '#edit-profile-header-link' ) . html ( window . sL . editMyProfile ) ;
// show site body now
$ ( '#user-container' ) . css ( 'display' , 'block' ) ;
$ ( '#feed' ) . css ( 'display' , 'block' ) ;
// login or not
if ( window . loggedIn ) {
doLogin ( getStreamFromUrl ( ) ) ;
}
else {
display _spinner ( ) ;
window . currentStream = '' ; // force reload stream
setNewCurrentStream ( getStreamFromUrl ( ) , function ( ) {
logoutWithoutReload ( false ) ;
remove _spinner ( ) ;
} , true ) ;
}
}
2013-08-19 22:30:57 +09:00
/ * ·
·
· Login action
·
· · · · · · · · · · · · · * /
2014-05-16 11:07:30 +09:00
$ ( '#form_login' ) . submit ( function ( e ) {
if ( typeof window . loginCheckSuccessful == 'undefined' ) {
2014-05-14 16:46:07 +09:00
e . preventDefault ( ) ;
2014-05-16 11:07:30 +09:00
checkLogin ( $ ( 'input#nickname' ) . val ( ) , $ ( 'input#password' ) . val ( ) , function ( data ) {
window . loginCheckSuccessful = true ;
$ ( '#form_login' ) . submit ( ) ;
} ) ;
}
} ) ;
2013-11-23 08:31:04 +09:00
function doLogin ( streamToSet ) {
2013-08-19 22:30:57 +09:00
$ ( '#submit-login' ) . attr ( 'disabled' , 'disabled' ) ;
$ ( '#submit-login' ) . focus ( ) ; // prevents submit on enter to close alert-popup on wrong credentials
display _spinner ( ) ;
2014-01-29 03:42:47 +09:00
2013-08-26 05:34:09 +09:00
// set colors if the api supports it
2014-05-16 11:07:30 +09:00
if ( typeof window . loggedIn . linkcolor != 'undefined' &&
typeof window . loggedIn . backgroundcolor != 'undefined' ) {
window . loggedIn . linkcolor = window . loggedIn . linkcolor || '' ; // no null value
window . loggedIn . backgroundcolor = window . loggedIn . backgroundcolor || '' ; // no null value
window . userLinkColor = window . loggedIn . linkcolor ;
window . userBackgroundColor = window . loggedIn . backgroundcolor ;
2014-11-24 21:47:45 +09:00
window . userBackgroundImage = window . loggedIn . background _image ;
2013-08-26 05:34:09 +09:00
if ( window . userLinkColor . length != 6 ) {
window . userLinkColor = window . defaultLinkColor ;
}
if ( window . userBackgroundColor . length != 6 ) {
window . userBackgroundColor = window . defaultBackgroundColor ;
2014-11-24 21:47:45 +09:00
}
if ( window . userBackgroundImage . length < 1 ) {
window . userBackgroundImage = '' ;
}
2013-08-26 05:34:09 +09:00
}
2013-08-19 22:30:57 +09:00
2014-11-24 21:47:45 +09:00
2013-08-19 22:30:57 +09:00
// add user data to DOM, show search form, remeber user id, show the feed
2013-11-23 08:31:04 +09:00
$ ( '#user-container' ) . css ( 'z-index' , '1000' ) ;
$ ( '#top-compose' ) . removeClass ( 'hidden' ) ;
2014-09-25 06:20:35 +09:00
$ ( '#qvitter-notice' ) . show ( ) ;
2014-05-16 11:07:30 +09:00
$ ( '#user-avatar' ) . attr ( 'src' , window . loggedIn . profile _image _url _profile _size ) ;
2014-11-24 21:47:45 +09:00
$ ( '#settingslink .nav-session' ) . css ( 'background-image' , 'url(\'' + window . loggedIn . profile _image _url _profile _size + '\')' ) ;
$ ( '#user-header' ) . attr ( 'title' , window . sL . viewMyProfilePage ) ;
2014-05-16 11:07:30 +09:00
$ ( '#user-name' ) . append ( window . loggedIn . name ) ;
$ ( '#user-screen-name' ) . append ( window . loggedIn . screen _name ) ;
$ ( '#user-queets strong' ) . html ( window . loggedIn . statuses _count ) ;
$ ( '#user-following strong' ) . html ( window . loggedIn . friends _count ) ;
$ ( '#user-followers strong' ) . html ( window . loggedIn . followers _count ) ;
$ ( '#user-groups strong' ) . html ( window . loggedIn . groups _count ) ;
$ ( '.stream-selection.friends-timeline' ) . attr ( 'href' , window . loggedIn . statusnet _profile _url + '/all' ) ;
$ ( '.stream-selection.mentions' ) . attr ( 'href' , window . loggedIn . statusnet _profile _url + '/replies' ) ;
2014-09-25 06:20:35 +09:00
$ ( '.stream-selection.notifications' ) . attr ( 'href' , window . loggedIn . statusnet _profile _url + '/notifications' ) ;
2014-05-16 11:07:30 +09:00
$ ( '.stream-selection.my-timeline' ) . attr ( 'href' , window . loggedIn . statusnet _profile _url ) ;
$ ( '.stream-selection.favorites' ) . attr ( 'href' , window . loggedIn . statusnet _profile _url + '/favorites' ) ;
2014-11-24 21:47:45 +09:00
window . myUserID = window . loggedIn . id ;
if ( window . loggedIn . cover _photo !== false ) {
$ ( '#user-header' ) . css ( 'background-image' , 'url(\'' + window . loggedIn . cover _photo + '\')' ) ;
}
2014-05-28 03:40:51 +09:00
// get all users i'm following for autosuggestion
window . following = new Array ( ) ;
getFromAPI ( 'qvitter/allfollowing/' + window . loggedIn . screen _name + '.json' , function ( data ) {
if ( data ) {
var i = 0 ;
$ . each ( data , function ( k , v ) {
if ( v [ 2 ] === false ) { var avatar = window . defaultAvatarStreamSize ; }
2014-11-25 12:46:57 +09:00
else { var avatar = v [ 2 ] ; }
2014-06-02 04:51:28 +09:00
v [ 0 ] = v [ 0 ] || v [ 1 ] ; // if name is null we go with username there too
2014-05-28 03:40:51 +09:00
window . following [ i ] = { 'id' : k , 'name' : v [ 0 ] , 'username' : v [ 1 ] , 'avatar' : avatar } ;
i ++ ;
} ) ;
}
} ) ;
2013-08-19 22:30:57 +09:00
// load history
loadHistoryFromLocalStorage ( ) ;
2015-01-27 01:13:34 +09:00
2013-08-19 22:30:57 +09:00
// set stream
window . currentStream = '' ; // always reload stream on login
setNewCurrentStream ( streamToSet , function ( ) {
2013-09-03 01:13:15 +09:00
$ ( '.language-dropdown' ) . css ( 'display' , 'none' ) ;
2013-08-19 22:30:57 +09:00
$ ( '#user-header' ) . animate ( { opacity : '1' } , 800 ) ;
$ ( '#user-body' ) . animate ( { opacity : '1' } , 800 ) ;
$ ( '#user-footer' ) . animate ( { opacity : '1' } , 800 ) ;
$ ( '.menu-container' ) . animate ( { opacity : '1' } , 800 ) ;
2013-08-26 03:11:53 +09:00
$ ( '#page-container' ) . animate ( { opacity : '1' } , 200 ) ;
$ ( '#search' ) . fadeIn ( 'slow' ) ;
2013-08-19 22:30:57 +09:00
$ ( '#login-content' ) . css ( 'display' , 'none' ) ;
2013-09-03 01:13:15 +09:00
$ ( '.front-signup' ) . css ( 'display' , 'none' ) ;
2014-11-24 21:47:45 +09:00
$ ( '#settingslink .dropdown-toggle' ) . fadeIn ( 'slow' ) ;
$ ( '#top-compose' ) . fadeIn ( 'slow' ) ;
$ ( 'input#nickname' ) . blur ( ) ;
2013-08-19 22:30:57 +09:00
remove _spinner ( ) ;
} , true ) ;
2013-11-23 08:31:04 +09:00
}
2013-08-19 22:30:57 +09:00
/ * ·
·
· In the login form , we want to check the remember - me - checkbox when its label is clicked
·
· · · · · · · · · · · · · * /
$ ( '#rememberme_label' ) . click ( function ( ) {
if ( $ ( '#rememberme' ) . prop ( 'checked' ) ) {
$ ( '#rememberme' ) . prop ( 'checked' , false ) ;
}
else {
$ ( '#rememberme' ) . prop ( 'checked' , true ) ;
}
} ) ;
2013-08-26 03:11:53 +09:00
$ ( '#rememberme_label' ) . disableSelection ( ) ;
2013-08-19 22:30:57 +09:00
/ * ·
·
2014-05-16 11:07:30 +09:00
· Logout
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · · · · · * /
$ ( '#logout' ) . click ( function ( ) {
2014-11-27 20:54:56 +09:00
window . location . href = window . siteInstanceURL + 'main/logout' ;
2013-08-19 22:30:57 +09:00
} ) ;
2013-08-26 03:11:53 +09:00
/ * ·
·
2014-11-24 21:47:45 +09:00
· FAQ
2013-08-26 03:11:53 +09:00
·
· · · · · · · · · · · · · * /
2014-11-24 21:47:45 +09:00
$ ( '#faq-link' ) . click ( function ( ) {
2014-11-28 09:16:34 +09:00
popUpAction ( 'popup-faq' , window . siteTitle + ' ' + window . sL . FAQ , '<div id="faq-container"></div>' , false ) ;
2015-01-26 03:05:09 +09:00
getDoc ( 'faq' , function ( faqHtml ) {
$ ( '#faq-container' ) . html ( faqHtml ) ;
} ) ;
2013-11-23 08:31:04 +09:00
} ) ;
2015-01-26 03:05:09 +09:00
2013-11-23 08:31:04 +09:00
2014-11-24 21:47:45 +09:00
/ * ·
·
2014-11-27 20:54:56 +09:00
· Classic Link , toggle setting in api and redirect to / all
2014-11-24 21:47:45 +09:00
·
· · · · · · · · · · · · · * /
$ ( '#classic-link' ) . click ( function ( ) {
getFromAPI ( 'qvitter/toggle_qvitter.json' , function ( data ) {
if ( data . success === true ) {
2014-11-27 20:54:56 +09:00
window . location . href = window . siteInstanceURL + window . loggedIn . screen _name + '/all' ;
2014-11-24 21:47:45 +09:00
}
} ) ;
} ) ;
2013-11-23 08:31:04 +09:00
2013-08-26 03:11:53 +09:00
2013-11-23 08:31:04 +09:00
2013-08-26 03:11:53 +09:00
/ * ·
·
· Do a logout without reloading , i . e . on login errors
·
· · · · · · · · · · · · · * /
function logoutWithoutReload ( doShake ) {
2013-08-26 06:06:06 +09:00
if ( window . currentStream == 'statuses/public_timeline.json' ) {
2015-01-22 05:51:25 +09:00
$ ( 'body' ) . css ( 'background-image' , 'url(' + window . fullUrlToThisQvitterApp + window . siteBackground + ')' ) ;
2013-08-26 06:06:06 +09:00
}
2014-05-16 11:07:30 +09:00
2014-05-14 16:46:07 +09:00
$ ( 'input#nickname' ) . focus ( ) ;
2013-09-03 01:13:15 +09:00
$ ( '.front-signup' ) . animate ( { opacity : '1' } , 200 ) ;
2014-05-14 16:46:07 +09:00
if ( doShake || localStorage . doShake ) {
$ ( 'input#nickname' ) . css ( 'background-color' , 'pink' ) ;
2013-08-26 06:06:06 +09:00
$ ( 'input#password' ) . css ( 'background-color' , 'pink' ) ;
}
$ ( '#login-content' ) . animate ( { opacity : '1' } , 200 , function ( ) {
2014-05-14 16:46:07 +09:00
if ( doShake || localStorage . doShake ) {
2013-08-26 06:06:06 +09:00
$ ( '#login-content' ) . effect ( 'shake' , { distance : 5 , times : 2 } , function ( ) {
2014-05-14 16:46:07 +09:00
$ ( 'input#nickname' ) . animate ( { backgroundColor : '#fff' } , 1000 ) ;
2013-08-26 06:06:06 +09:00
$ ( 'input#password' ) . animate ( { backgroundColor : '#fff' } , 1000 ) ;
2014-05-14 16:46:07 +09:00
delete localStorage . doShake ;
2013-08-26 06:06:06 +09:00
} ) ;
2013-08-26 03:11:53 +09:00
}
2013-09-03 01:13:15 +09:00
$ ( '.front-welcome-text' ) . fadeIn ( 3000 ) ;
2013-08-26 06:06:06 +09:00
} ) ;
$ ( '#page-container' ) . animate ( { opacity : '1' } , 200 ) ;
2013-08-26 03:11:53 +09:00
}
2013-08-19 22:30:57 +09:00
/ * ·
·
· Handling the language dropdown selection
·
· · · · · · · · · · · · · * /
$ ( '.dropdown' ) . click ( function ( ) { $ ( this ) . toggleClass ( 'dropped' ) } ) ;
$ ( '.dropdown' ) . disableSelection ( ) ;
$ ( document ) . bind ( 'click' , function ( e ) {
2013-08-26 03:11:53 +09:00
if ( ! $ ( e . target ) . is ( '#logo' ) && ! $ ( e . target ) . is ( '#settingslink' ) && ! $ ( e . target ) . is ( '.nav-session' ) && ! $ ( e . target ) . is ( '.dropdown-toggle' ) && ! $ ( e . target ) . is ( '.dropdown-toggle small' ) && ! $ ( e . target ) . is ( '.dropdown-toggle span' ) && ! $ ( e . target ) . is ( '.dropdown-toggle b' ) ) {
2013-08-19 22:30:57 +09:00
$ ( '.dropdown' ) . removeClass ( 'dropped' ) ;
$ ( '.quitter-settings.dropdown-menu' ) . removeClass ( 'dropped' ) ;
}
} ) ;
$ ( '.language-link' ) . click ( function ( ) {
2013-08-20 04:15:15 +09:00
if ( localStorageIsEnabled ( ) ) {
localStorage . selectedLanguage = $ ( this ) . attr ( 'data-lang-code' ) ; // save langage selection
}
2013-08-19 22:30:57 +09:00
location . reload ( ) ; // reload
} ) ;
/ * ·
·
· Show the logo menu dropdown on click
·
· · · · · · · · · · · · · * /
2013-08-26 03:11:53 +09:00
$ ( '#settingslink' ) . click ( function ( ) {
2013-08-19 22:30:57 +09:00
if ( ! $ ( '.quitter-settings' ) . hasClass ( 'dropped' ) ) { $ ( '.quitter-settings' ) . addClass ( 'dropped' ) ; }
else { $ ( '.quitter-settings' ) . removeClass ( 'dropped' ) ; }
} ) ;
/ * ·
·
2015-02-25 06:36:36 +09:00
· When clicking an external follow button
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · · · · · * /
2013-11-23 08:31:04 +09:00
$ ( 'body' ) . on ( 'click' , '.external-follow-button' , function ( event ) {
2015-01-19 17:31:43 +09:00
popUpAction ( 'popup-external-follow' , window . sL . userExternalFollow + ' ' + $ ( '.profile-card-inner .screen-name' ) . html ( ) , '<form method="post" action="' + window . siteInstanceURL + 'main/ostatus"><input type="hidden" id="nickname" name="nickname" value="' + $ ( '.profile-card-inner .screen-name' ) . html ( ) . substring ( 1 ) + '"><input type="text" id="profile" name="profile" placeholder="' + window . sL . userExternalFollowHelp + '" /></form>' , '<div class="right"><button class="close">' + window . sL . cancelVerb + '</button><button class="primary">' + window . sL . userExternalFollow + '</button></div>' ) ;
2013-11-23 08:31:04 +09:00
$ ( '#popup-external-follow form input#profile' ) . focus ( ) ;
$ ( '#popup-external-follow button.primary' ) . click ( function ( ) {
$ ( '#popup-external-follow form' ) . submit ( ) ;
} ) ;
} ) ;
2014-01-29 03:42:47 +09:00
/ * ·
·
2015-02-25 06:36:36 +09:00
· When clicking an external join button
2014-01-29 03:42:47 +09:00
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'click' , '.external-member-button' , function ( event ) {
2015-01-19 17:31:43 +09:00
popUpAction ( 'popup-external-join' , window . sL . joinExternalGroup + ' ' + $ ( '.profile-card-inner .screen-name' ) . html ( ) , '<form method="post" action="' + window . siteInstanceURL + 'main/ostatus"><input type="hidden" id="group" name="group" value="' + $ ( '.profile-card-inner .screen-name' ) . html ( ) . substring ( 1 ) + '"><input type="text" id="profile" name="profile" placeholder="' + window . sL . userExternalFollowHelp + '" /></form>' , '<div class="right"><button class="close">' + window . sL . cancelVerb + '</button><button class="primary">' + window . sL . userExternalFollow + '</button></div>' ) ;
2014-01-29 03:42:47 +09:00
$ ( '#popup-external-join form input#profile' ) . focus ( ) ;
$ ( '#popup-external-join button.primary' ) . click ( function ( ) {
$ ( '#popup-external-join form' ) . submit ( ) ;
} ) ;
} ) ;
2013-11-23 08:31:04 +09:00
2014-11-24 21:47:45 +09:00
/ * ·
·
2015-02-25 06:36:36 +09:00
· When clicking an external follow button
2014-11-24 21:47:45 +09:00
·
· · · · · · · · · · · · · * /
2013-11-23 08:31:04 +09:00
2015-01-27 01:35:44 +09:00
$ ( 'body' ) . on ( 'click' , '.qvitter-follow-button' , function ( event ) {
2013-08-19 22:30:57 +09:00
if ( ! $ ( this ) . hasClass ( 'disabled' ) ) {
$ ( this ) . addClass ( 'disabled' ) ;
// get user id
var user _id = $ ( this ) . attr ( 'data-follow-user-id' ) ;
2014-11-24 21:47:45 +09:00
// if there's no local user id, we have to take a detour
if ( typeof user _id == 'undefined' ) {
$ . ajax ( { url : window . siteInstanceURL + 'main/ostatussub' ,
type : "POST" ,
data : {
token : window . commonSessionToken ,
profile : $ ( this ) . attr ( 'data-follow-user' ) ,
submit : 'Confirm'
} ,
error : function ( data ) { console . log ( 'error' ) ; console . log ( data ) ; } ,
success : function ( data ) {
// reload page on success
// since ostatussub doesn't have an api, there's no good way to get the local user id here,
// and change the button to an unsubscribe button.
window . location . replace ( window . siteInstanceURL + window . loggedIn . screen _name + '/subscriptions' ) ;
}
} ) ;
2013-08-19 22:30:57 +09:00
}
2014-11-24 21:47:45 +09:00
// if we have a local id, it's straightforward, but we could be handling an unfollow
2013-08-19 22:30:57 +09:00
else {
2014-11-24 21:47:45 +09:00
// follow or unfollow?
if ( $ ( this ) . hasClass ( 'following' ) ) {
var followOrUnfollow = 'unfollow' ;
}
else {
var followOrUnfollow = 'follow' ;
}
2013-08-19 22:30:57 +09:00
2014-11-24 21:47:45 +09:00
// post to api
display _spinner ( ) ;
APIFollowOrUnfollowUser ( followOrUnfollow , user _id , this , function ( data , this _element ) {
remove _spinner ( ) ;
$ ( this _element ) . removeClass ( 'disabled' ) ;
if ( data ) {
if ( data . following ) {
$ ( this _element ) . addClass ( 'following' ) ;
$ ( '#user-following strong' ) . html ( parseInt ( $ ( '#user-following strong' ) . html ( ) , 10 ) + 1 ) ;
}
else {
$ ( this _element ) . removeClass ( 'following' ) ;
$ ( '#user-following strong' ) . html ( parseInt ( $ ( '#user-following strong' ) . html ( ) , 10 ) - 1 ) ;
}
2013-08-19 22:30:57 +09:00
}
2014-11-24 21:47:45 +09:00
} ) ;
}
2013-08-19 22:30:57 +09:00
}
} ) ;
/ * ·
·
· When clicking a join group button
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'click' , '.member-button' , function ( event ) {
if ( ! $ ( this ) . hasClass ( 'disabled' ) ) {
$ ( this ) . addClass ( 'disabled' ) ;
// get group id
var group _id = $ ( this ) . attr ( 'data-group-id' ) ;
// join or leave?
if ( $ ( this ) . hasClass ( 'member' ) ) {
var joinOrLeave = 'leave' ;
}
else {
var joinOrLeave = 'join' ;
}
// post to api
display _spinner ( ) ;
APIJoinOrLeaveGroup ( joinOrLeave , group _id , this , function ( data , this _element ) {
remove _spinner ( ) ;
$ ( this _element ) . removeClass ( 'disabled' ) ;
if ( data ) {
if ( data . member ) {
$ ( this _element ) . addClass ( 'member' ) ;
$ ( '.profile-card .member-stats strong' ) . html ( parseInt ( $ ( '.profile-card .member-stats strong' ) . html ( ) , 10 ) + 1 ) ;
$ ( '#user-groups strong' ) . html ( parseInt ( $ ( '#user-groups strong' ) . html ( ) , 10 ) + 1 ) ;
}
else if ( data . member === false ) {
$ ( this _element ) . removeClass ( 'member' ) ;
$ ( '.profile-card .member-stats strong' ) . html ( parseInt ( $ ( '.profile-card .member-stats strong' ) . html ( ) , 10 ) - 1 ) ;
$ ( '#user-groups strong' ) . html ( parseInt ( $ ( '#user-groups strong' ) . html ( ) , 10 ) - 1 ) ;
}
}
} ) ;
}
} ) ;
/ * ·
·
· Select a stream when the logged in user clicks their own queets , followers etc
·
· · · · · · · · · · · · · * /
2014-11-24 21:47:45 +09:00
$ ( '#user-header, #user-queets, #user-following, #user-followers, #user-groups' ) . on ( 'click' , function ( e ) {
// not if we're clicking the mini-edit-profile-button
if ( $ ( e . target ) . is ( '#mini-edit-profile-button' ) ) {
return ;
}
2013-08-19 22:30:57 +09:00
if ( $ ( this ) . attr ( 'id' ) == 'user-header' || $ ( this ) . attr ( 'id' ) == 'user-queets' ) {
2014-05-16 11:07:30 +09:00
setNewCurrentStream ( 'statuses/user_timeline.json?screen_name=' + window . loggedIn . screen _name , function ( ) { } , true ) ;
2013-08-19 22:30:57 +09:00
}
else if ( $ ( this ) . attr ( 'id' ) == 'user-following' ) {
2013-08-20 22:26:25 +09:00
setNewCurrentStream ( 'statuses/friends.json?count=20' , function ( ) { } , true ) ;
2013-08-19 22:30:57 +09:00
}
else if ( $ ( this ) . attr ( 'id' ) == 'user-followers' ) {
2013-08-20 22:26:25 +09:00
setNewCurrentStream ( 'statuses/followers.json?count=20' , function ( ) { } , true ) ;
2013-08-19 22:30:57 +09:00
}
else if ( $ ( this ) . attr ( 'id' ) == 'user-groups' ) {
2013-08-20 22:26:25 +09:00
setNewCurrentStream ( 'statusnet/groups/list.json?count=10' , function ( ) { } , true ) ;
2013-08-19 22:30:57 +09:00
}
} ) ;
/ * ·
·
2013-08-20 22:26:25 +09:00
· Select a stream when clicking on queets , followers etc in a profile card or feed header
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · · · · · * /
2013-08-20 22:26:25 +09:00
$ ( 'body' ) . on ( 'click' , '.profile-banner-footer .stats li a, .queet-stream' , function ( ) {
2013-08-19 22:30:57 +09:00
var screenName = $ ( '.profile-card-inner .screen-name' ) . html ( ) . substring ( 1 ) ;
if ( $ ( this ) . hasClass ( 'tweet-stats' ) ) {
setNewCurrentStream ( 'statuses/user_timeline.json?screen_name=' + screenName , function ( ) { } , true ) ;
}
else if ( $ ( this ) . hasClass ( 'following-stats' ) ) {
2013-08-20 22:26:25 +09:00
setNewCurrentStream ( 'statuses/friends.json?count=20&screen_name=' + screenName , function ( ) { } , true ) ;
2013-08-19 22:30:57 +09:00
}
else if ( $ ( this ) . hasClass ( 'follower-stats' ) ) {
2013-08-20 22:26:25 +09:00
setNewCurrentStream ( 'statuses/followers.json?count=20&screen_name=' + screenName , function ( ) { } , true ) ;
2013-08-19 22:30:57 +09:00
}
else if ( $ ( this ) . hasClass ( 'groups-stats' ) ) {
2013-08-20 22:26:25 +09:00
setNewCurrentStream ( 'statusnet/groups/list.json?count=10&screen_name=' + screenName , function ( ) { } , true ) ;
2013-08-19 22:30:57 +09:00
}
else if ( $ ( this ) . hasClass ( 'queets' ) ) {
setNewCurrentStream ( 'statuses/user_timeline.json?screen_name=' + screenName , function ( ) { } , true ) ;
}
else if ( $ ( this ) . hasClass ( 'mentions' ) ) {
2014-10-03 02:24:54 +09:00
setNewCurrentStream ( 'statuses/mentions.json?screen_name=' + screenName , function ( ) { } , true ) ;
2013-08-19 22:30:57 +09:00
}
else if ( $ ( this ) . hasClass ( 'favorites' ) ) {
setNewCurrentStream ( 'favorites.json?screen_name=' + screenName , function ( ) { } , true ) ;
2013-08-20 22:26:25 +09:00
}
2014-09-25 06:20:35 +09:00
else if ( $ ( this ) . hasClass ( 'following' ) ) {
setNewCurrentStream ( 'statuses/friends.json?count=20' , function ( ) { } , true ) ;
}
else if ( $ ( this ) . hasClass ( 'followers' ) ) {
setNewCurrentStream ( 'statuses/followers.json?count=20' , function ( ) { } , true ) ;
}
2013-08-20 22:26:25 +09:00
else if ( $ ( this ) . hasClass ( 'member-stats' ) ) {
setNewCurrentStream ( 'statusnet/groups/membership/' + screenName + '.json?count=20' , function ( ) { } , true ) ;
}
else if ( $ ( this ) . hasClass ( 'admin-stats' ) ) {
setNewCurrentStream ( 'statusnet/groups/admins/' + screenName + '.json?count=20' , function ( ) { } , true ) ;
}
2013-08-19 22:30:57 +09:00
} ) ;
/ * ·
·
· Searching
·
· · · · · · · · · · · · · * /
$ ( '#search-query' ) . on ( 'keyup' , function ( e ) { if ( e . keyCode == 13 ) { showSearchStream ( ) ; } } ) ; // on enter in input field
$ ( 'button.icon.nav-search' ) . on ( 'click' , function ( e ) { showSearchStream ( ) ; } ) ; // on click on magnifying glass
function showSearchStream ( ) {
2015-01-20 23:25:14 +09:00
streamName = 'search.json?q=' + encodeURIComponent ( replaceHtmlSpecialChars ( $ ( '#search-query' ) . val ( ) ) ) ;
2013-08-19 22:30:57 +09:00
setNewCurrentStream ( streamName , function ( ) { } , true ) ;
}
/ * ·
2013-11-23 08:31:04 +09:00
· < o
· Hijack all links and look for local users , tags , searches and groups . ( //
2013-08-19 22:30:57 +09:00
·
· If found , select that stream and prevent links default behaviour
·
· · · · · · · · · · · · · * /
2014-11-24 21:47:45 +09:00
$ ( 'body' ) . on ( 'click' , 'a' , function ( e ) {
2013-11-23 08:31:04 +09:00
2014-11-24 21:47:45 +09:00
// don't hijack if metakeys are pressed!
2013-11-23 08:31:04 +09:00
if ( e . ctrlKey || e . altKey || e . shiftKey || e . metaKey ) {
return ;
}
2014-11-24 21:47:45 +09:00
// don't hijack if this is an external link that has been clicked but failed that time
if ( $ ( this ) . hasClass ( 'external-profile-clicked' ) ) {
return ;
}
// don't hijack if this is an anchor link in the faq
if ( $ ( this ) . closest ( '.modal-container' ) . attr ( 'id' ) == 'popup-faq' && $ ( this ) . attr ( 'href' ) . indexOf ( '#' ) > - 1 ) {
return ;
}
// don't hijack and don't follow link if this is the x remove users from history, prevent link but don't set a new currentstream
2014-01-29 03:42:47 +09:00
if ( $ ( e . target ) . is ( 'i.chev-right' ) ) {
2013-11-23 08:31:04 +09:00
e . preventDefault ( ) ;
return ;
2014-12-09 01:39:47 +09:00
}
2014-11-24 21:47:45 +09:00
2014-12-09 01:39:47 +09:00
// don't hijack links with donthijack attribute
if ( ! ! $ ( this ) . attr ( 'donthijack' ) || $ ( this ) . attr ( 'donthijack' ) == '' ) {
return ;
}
// all links opens in new tab
2013-11-23 08:31:04 +09:00
$ ( this ) . attr ( 'target' , '_blank' ) ;
2013-08-19 22:30:57 +09:00
if ( typeof $ ( this ) . attr ( 'href' ) != 'undefined' ) {
2014-11-24 21:47:45 +09:00
2013-11-23 08:31:04 +09:00
// site root
if ( $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain , '' ) == '/' ) {
e . preventDefault ( ) ;
setNewCurrentStream ( 'statuses/public_timeline.json' , function ( ) { } , true ) ;
}
2014-01-29 03:42:47 +09:00
// whole network feed
else if ( $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain , '' ) == '/main/all' ) {
e . preventDefault ( ) ;
2014-05-16 11:07:30 +09:00
setNewCurrentStream ( 'statuses/public_and_external_timeline.json' , function ( ) { } , true ) ;
2014-01-29 03:42:47 +09:00
}
2013-11-23 08:31:04 +09:00
// logged in users streams
2014-05-16 11:07:30 +09:00
else if ( $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain + '/' + window . loggedIn . screen _name , '' ) == '/all' ) {
2013-11-23 08:31:04 +09:00
e . preventDefault ( ) ;
2014-10-03 02:24:54 +09:00
setNewCurrentStream ( 'statuses/friends_timeline.json' , function ( ) { } , true ) ;
2013-11-23 08:31:04 +09:00
}
2014-05-16 11:07:30 +09:00
else if ( $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain + '/' + window . loggedIn . screen _name , '' ) == '/replies' ) {
2013-11-23 08:31:04 +09:00
e . preventDefault ( ) ;
2014-10-03 02:24:54 +09:00
setNewCurrentStream ( 'statuses/mentions.json' , function ( ) { } , true ) ;
2014-05-23 21:13:38 +09:00
}
2014-09-25 06:20:35 +09:00
else if ( $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain + '/' + window . loggedIn . screen _name , '' ) == '/notifications' ) {
e . preventDefault ( ) ;
setNewCurrentStream ( 'qvitter/statuses/notifications.json' , function ( ) { } , true ) ;
}
2014-05-16 11:07:30 +09:00
else if ( $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain + '/' + window . loggedIn . screen _name , '' ) == '/favorites' ) {
2013-11-23 08:31:04 +09:00
e . preventDefault ( ) ;
setNewCurrentStream ( 'favorites.json' , function ( ) { } , true ) ;
}
2013-08-19 22:30:57 +09:00
// profiles
2013-11-23 08:31:04 +09:00
else if ( ( /^[a-zA-Z0-9]+$/ . test ( $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain + '/' , '' ) ) ) ) {
2014-11-24 21:47:45 +09:00
var linkNickname = $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain + '/' , '' ) ;
// don't hijack /groups-url
if ( linkNickname == 'groups' ) {
return ;
}
2013-08-19 22:30:57 +09:00
e . preventDefault ( ) ;
if ( $ ( this ) . parent ( ) . attr ( 'id' ) == 'user-profile-link' ) { // logged in user
2014-05-16 11:07:30 +09:00
setNewCurrentStream ( 'statuses/user_timeline.json?screen_name=' + window . loggedIn . screen _name , function ( ) { } , true ) ;
2013-08-19 22:30:57 +09:00
}
else { // any user
2014-11-24 21:47:45 +09:00
setNewCurrentStream ( 'statuses/user_timeline.json?screen_name=' + linkNickname , function ( ) { } , true ) ;
2013-08-19 22:30:57 +09:00
}
}
else if ( ( /^[0-9]+$/ . test ( $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain + '/user/' , '' ) ) ) ) {
e . preventDefault ( ) ;
setNewCurrentStream ( 'statuses/user_timeline.json?screen_name=' + $ ( this ) . text ( ) . toLowerCase ( ) , function ( ) { } , true ) ;
}
// tags
else if ( $ ( this ) . attr ( 'href' ) . indexOf ( window . siteRootDomain + '/tag/' ) > - 1 ) {
e . preventDefault ( ) ;
2014-01-29 03:42:47 +09:00
setNewCurrentStream ( 'statusnet/tags/timeline/' + $ ( this ) . text ( ) . toLowerCase ( ) . replace ( '#' , '' ) + '.json' , function ( ) { } , true ) ;
2013-08-19 22:30:57 +09:00
}
2014-09-25 06:20:35 +09:00
// notices
2015-01-27 09:57:08 +09:00
else if ( $ ( this ) . attr ( 'href' ) . indexOf ( window . siteRootDomain + '/notice/' ) > - 1 && $ ( this ) . attr ( 'href' ) . indexOf ( window . siteRootDomain + '/notice/delete/' ) == - 1 ) {
2014-09-25 06:20:35 +09:00
e . preventDefault ( ) ;
setNewCurrentStream ( 'statuses/show/' + $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain + '/notice/' , '' ) + '.json' , function ( ) { } , true ) ;
}
2013-08-19 22:30:57 +09:00
// groups
else if ( /^[0-9]+$/ . test ( $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain + '/group/' , '' ) . replace ( '/id' , '' ) ) ) {
e . preventDefault ( ) ;
if ( $ ( this ) . hasClass ( 'account-group' ) ) {
var groupName = $ ( this ) . find ( '.screen-name' ) . html ( ) . substring ( 1 ) ;
}
else {
var groupName = $ ( this ) . text ( ) . toLowerCase ( ) ;
}
setNewCurrentStream ( 'statusnet/groups/timeline/' + groupName + '.json' , function ( ) { } , true ) ;
}
else if ( $ ( this ) . attr ( 'href' ) . indexOf ( window . siteRootDomain + '/group/' ) > - 1 ) {
e . preventDefault ( ) ;
setNewCurrentStream ( 'statusnet/groups/timeline/' + $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain + '/group/' , '' ) + '.json' , function ( ) { } , true ) ;
2013-11-23 08:31:04 +09:00
}
// search
else if ( $ ( this ) . attr ( 'href' ) . indexOf ( '/search/notice?q=' ) > - 1 ) {
e . preventDefault ( ) ;
var searchToStream = $ ( this ) . attr ( 'href' ) . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain , '' ) . replace ( '/search/notice?q=' , '' ) ;
setNewCurrentStream ( 'search.json?q=' + searchToStream , function ( ) { } , true ) ;
}
2013-08-19 22:30:57 +09:00
// profile picture
else if ( $ ( this ) . hasClass ( 'profile-picture' ) ) {
e . preventDefault ( ) ;
2014-11-24 21:47:45 +09:00
if ( $ ( this ) . closest ( '.modal-container' ) . attr ( 'id' ) != 'edit-profile-popup' ) { // no popup if we're editing our profile
popUpAction ( 'popup-profile-picture' , $ ( '.profile-card-inner .screen-name' ) . html ( ) , '<img style="width:100%;display:block;" src="' + $ ( this ) . attr ( 'href' ) + '" />' , false ) ;
}
2013-08-19 22:30:57 +09:00
}
// external profiles
else if ( ( $ ( this ) . children ( 'span.mention' ) . length > 0 // if it's a mention
2014-10-05 21:07:31 +09:00
|| $ ( this ) . hasClass ( 'h-card mention' ) // if it's a newer gnusocial group mention
2013-08-19 22:30:57 +09:00
|| ( $ ( this ) . hasClass ( 'account-group' ) && $ ( this ) . attr ( 'href' ) . indexOf ( '/group/' ) == - 1 ) // or if this is queet stream item header but not a group
|| ( $ ( this ) . closest ( '.stream-item' ) . hasClass ( 'activity' ) && $ ( this ) . attr ( 'href' ) . indexOf ( '/group/' ) == - 1 ) ) // or if it's a activity notice but not a group link
2014-05-16 11:07:30 +09:00
&& typeof window . loggedIn . screen _name != 'undefined' ) { // if logged in
2013-08-19 22:30:57 +09:00
e . preventDefault ( ) ;
display _spinner ( ) ;
2014-11-24 21:47:45 +09:00
$ ( this ) . addClass ( 'external-profile-clicked' ) ;
getFromAPI ( 'qvitter/external_user_show.json?profileurl=' + encodeURIComponent ( $ ( this ) . attr ( 'href' ) ) , function ( data ) {
2013-08-19 22:30:57 +09:00
if ( data ) {
2013-11-23 08:31:04 +09:00
2014-11-26 07:36:29 +09:00
// local profile id and follow class
2014-11-24 21:47:45 +09:00
var followLocalIdHtml = '' ;
2014-11-26 07:36:29 +09:00
var followingClass = '' ;
2014-11-24 21:47:45 +09:00
if ( typeof data . local != 'undefined' ) {
followLocalIdHtml = ' data-follow-user-id="' + data . local . id + '"' ;
2014-11-26 07:36:29 +09:00
if ( data . local . following ) {
followingClass = 'following' ;
}
2014-11-24 21:47:45 +09:00
}
2013-08-19 22:30:57 +09:00
// empty strings and zeros instead of null
2014-11-24 21:47:45 +09:00
data = cleanUpUserObject ( data . external ) ;
// old statusnet-versions might not have full avatar urls in their api response
if ( typeof data . profile _image _url _original == 'undefined'
|| data . profile _image _url _original === null
|| data . profile _image _url _original . length == 0 ) {
data . profile _image _url _original = data . profile _image _url ;
}
if ( typeof data . profile _image _url _profile _size == 'undefined'
|| data . profile _image _url _profile _size === null
|| data . profile _image _url _profile _size . length == 0 ) {
data . profile _image _url _profile _size = data . profile _image _url ;
}
// we might have a cover photo
if ( typeof data . cover _photo != 'undefined' && data . cover _photo !== false ) {
var cover _photo = data . cover _photo ;
}
else {
var cover _photo = data . profile _image _url _original ;
}
// is webpage empty?
var emptyWebpage = '' ;
if ( data . url . length < 1 ) {
emptyWebpage = ' empty' ;
}
2013-08-19 22:30:57 +09:00
2013-11-23 08:31:04 +09:00
var serverUrl = data . statusnet _profile _url . replace ( '/' + data . screen _name , '' ) ;
var userApiUrl = serverUrl + '/api/statuses/user_timeline.json?screen_name=' + data . screen _name ;
var screenNameWithServer = '@' + data . screen _name + '@' + serverUrl . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) ;
2015-01-27 01:35:44 +09:00
var followButton = '<div class="user-actions"><button' + followLocalIdHtml + ' data-follow-user="' + data . statusnet _profile _url + '" type="button" class="qvitter-follow-button ' + followingClass + '"><span class="button-text follow-text"><i class="follow"></i>' + window . sL . userFollow + '</span><span class="button-text following-text">' + window . sL . userFollowing + '</span><span class="button-text unfollow-text">' + window . sL . userUnfollow + '</span></button></div>' ;
2013-08-19 22:30:57 +09:00
2014-11-24 21:47:45 +09:00
// preview latest notice
2014-11-25 00:17:40 +09:00
var noticeHtml = '' ;
if ( typeof data . status != 'undefined' ) {
data . status . user = data ;
var noticeHtml = buildQueetHtml ( data . status ) ;
}
2014-11-24 21:47:45 +09:00
2014-11-25 18:01:57 +09:00
var profileCard = '<div class="profile-card"><div class="profile-header-inner" style="background-image:url(\'' + cover _photo + '\')"><div class="profile-header-inner-overlay"></div><a class="profile-picture"><img src="' + data . profile _image _url _profile _size + '" /></a><div class="profile-card-inner"><h1 class="fullname">' + data . name + '<span></span></h1><h2 class="username"><span class="screen-name"><a target="_blank" href="' + data . statusnet _profile _url + '">' + screenNameWithServer + '</a></span><span class="follow-status"></span></h2><div class="bio-container"><p>' + data . description + '</p></div><p class="location-and-url"><span class="location">' + data . location + '</span><span class="url' + emptyWebpage + '"><span class="divider"> · </span><a target="_blank" href="' + data . url + '">' + data . url . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) + '</a></span></p></div></div><div class="profile-banner-footer"><ul class="stats"><li><a target="_blank" href="' + data . statusnet _profile _url + '">' + window . sL . notices + '<strong>' + data . statuses _count + '</strong></a></li><li><a target="_blank" href="' + data . statusnet _profile _url + '/subscriptions">' + window . sL . following + '<strong>' + data . friends _count + '</strong></a></li><li><a target="_blank" href="' + data . statusnet _profile _url + '/subscribers">' + window . sL . followers + '<strong>' + data . followers _count + '</strong></a></li></ul>' + followButton + '<div class="clearfix"></div></div></div><div class="clearfix"></div>' ;
2013-11-23 08:31:04 +09:00
2014-11-24 21:47:45 +09:00
popUpAction ( 'popup-external-profile' , screenNameWithServer , profileCard + noticeHtml , '<a class="go-to-external-profile" href="' + data . statusnet _profile _url + '">' + window . sL . goToExternalProfile + '</a>' ) ;
2013-11-23 08:31:04 +09:00
2013-08-19 22:30:57 +09:00
remove _spinner ( ) ;
2014-11-24 21:47:45 +09:00
$ ( 'a' ) . removeClass ( 'external-profile-clicked' ) ;
2013-08-19 22:30:57 +09:00
}
2014-11-24 21:47:45 +09:00
// if external lookup failed, trigger click again.
// it will not be hijacked since we don't remove the external-profile-clicked class here
else {
$ ( '.external-profile-clicked' ) . trigger ( 'click' ) ;
2013-08-19 22:30:57 +09:00
}
2014-11-24 21:47:45 +09:00
2013-08-19 22:30:57 +09:00
} ) ;
}
// external groups
else if ( ( $ ( this ) . children ( 'span.group' ) . length > 0 // if it's a group mention
2014-10-05 21:07:31 +09:00
|| $ ( this ) . hasClass ( 'h-card group' ) // if it's a newer gnusocial group mention
2013-08-19 22:30:57 +09:00
|| ( $ ( this ) . hasClass ( 'account-group' ) && $ ( this ) . attr ( 'href' ) . indexOf ( '/group/' ) > - 1 ) // or if this is group stream item header
|| ( $ ( this ) . closest ( '.stream-item' ) . hasClass ( 'activity' ) && $ ( this ) . attr ( 'href' ) . indexOf ( '/group/' ) > - 1 ) ) // or if it's a activity notice
2014-05-16 11:07:30 +09:00
&& typeof window . loggedIn . screen _name != 'undefined' ) { // if logged in
2013-08-19 22:30:57 +09:00
e . preventDefault ( ) ;
display _spinner ( ) ;
getFromAPI ( 'statusnet/groups/show.json?id=foo&uri=' + encodeURIComponent ( $ ( this ) . attr ( 'href' ) ) , function ( data ) { if ( data ) {
data . nickname = data . nickname || '' ;
data . fullname = data . fullname || '' ;
data . stream _logo = data . stream _logo || 'http://quitter.se/theme/quitter-theme2/default-avatar-stream.png' ;
data . homepage _logo = data . homepage _logo || 'http://quitter.se/theme/quitter-theme2/default-avatar-profile.png' ;
data . original _logo = data . original _logo || 'http://quitter.se/theme/quitter-theme2/default-avatar-profile.png' ;
data . description = data . description || '' ;
data . homepage = data . homepage || '' ;
data . url = data . url || '' ;
data . member _count = data . member _count || 0 ;
data . admin _count = data . admin _count || 0 ;
// show user actions if logged in
var memberClass = '' ;
if ( data . member ) {
memberClass = 'member' ;
}
var groupRoot = data . url . substring ( 0 , data . url . indexOf ( '/group/' ) ) ;
var groupServer = groupRoot . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) ;
var memberButton = '<div class="user-actions"><button data-group-id="' + data . id + '" type="button" class="member-button ' + memberClass + '"><span class="button-text join-text"><i class="join"></i>' + window . sL . joinGroup + '</span><span class="button-text ismember-text">' + window . sL . isMemberOfGroup + '</span><span class="button-text leave-text">' + window . sL . leaveGroup + '</span></button></div>' ;
// get local member avatars
getFromAPI ( 'statusnet/groups/membership.json?id=' + data . id , function ( user _data ) { if ( user _data ) {
var avatars = '' ;
var i = 0 ;
$ . each ( user _data , function ( k , v ) {
if ( i < 7 ) {
avatars = avatars + '<img class="avatar size30" src="' + v . profile _image _url + '" />' ;
}
i ++ ;
} ) ;
2013-09-03 01:13:15 +09:00
var profileCard = '<div class="profile-card"><div class="profile-header-inner" style="background-image:url(' + data . original _logo + ')"><div class="profile-header-inner-overlay"></div><a class="profile-picture"><img src="' + data . homepage _logo + '" /></a><div class="profile-card-inner"><h1 class="fullname">' + data . fullname + '<span></span></h1><h2 class="username"><span class="screen-name"><a target="_blank" href="' + groupRoot + '/group/' + data . nickname + '">!' + data . nickname + '@' + groupServer + '</a></span></span></h2><div class="bio-container"><p>' + data . description + '</p></div><p class="location-and-url"></span><span class="url"><a href="' + data . homepage + '">' + data . homepage . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) + '</a></span></p></div></div><div class="profile-banner-footer"><ul class="stats"><li><a target="_blank" href="' + groupRoot + '/group/' + data . nickname + '/members" class="member-stats">' + avatars + '</a></li></ul>' + memberButton + '<div class="clearfix"></div></div></div>' ;
2013-08-19 22:30:57 +09:00
popUpAction ( 'popup-external-group-profile' , '!' + data . nickname + '@' + groupServer , profileCard , false ) ;
remove _spinner ( ) ;
} } ) ;
} } ) ;
}
}
} ) ;
2015-01-27 09:57:08 +09:00
/ * ·
·
· Open a queet menu when clicking ellipsis button
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'click' , '.sm-ellipsis' , function ( ) {
// hide
if ( $ ( this ) . closest ( '.action-ellipsis-container' ) . children ( '.dropdown-menu' ) . length > 0 ) {
$ ( this ) . closest ( '.action-ellipsis-container' ) . children ( '.dropdown-menu' ) . remove ( ) ;
}
// show
else {
$ ( '.action-ellipsis-container' ) . children ( '.dropdown-menu' ) . remove ( ) ; // remove menu from other queets
var streamItemUsername = $ ( this ) . closest ( '.stream-item' ) . find ( '.stream-item-header' ) . find ( '.screen-name' ) . text ( ) ;
var streamItemUserID = $ ( this ) . closest ( '.stream-item' ) . find ( '.stream-item-header' ) . find ( '.name' ) . attr ( 'data-user-id' ) ;
var streamItemID = $ ( this ) . closest ( '.stream-item' ) . attr ( 'data-quitter-id' ) ;
var blockHtml = '' ;
var deleteHtml = '' ;
if ( streamItemUserID != window . loggedIn . id ) {
blockHtml = '<li><a class="block-user" href="' + window . siteInstanceURL + 'main/block?profileid=' + streamItemUserID + '">' + window . sL . blockUser . replace ( '{username}' , streamItemUsername ) + '</a></li>' ;
}
else {
deleteHtml = '<li><a class="delete-queet" href="' + window . siteInstanceURL + 'notice/delete/' + streamItemID + '">' + window . sL . deleteVerb + '</a></li>' ;
}
$ ( this ) . closest ( '.action-ellipsis-container' ) . append ( ' \
< ul class = "dropdown-menu" > \
< li class = "dropdown-caret left" > < span class = "caret-outer" > < / s p a n > < s p a n c l a s s = " c a r e t - i n n e r " > < / s p a n > < / l i > \
' + blockHtml + ' \
' + deleteHtml + ' \
< / u l > \
' ) ;
}
} ) ;
2013-08-19 22:30:57 +09:00
/ * ·
·
· When user clicks the x to remove a menu history item
·
· · · · · · · · · · · · · * /
2014-01-29 03:42:47 +09:00
$ ( 'body' ) . on ( 'click' , '#history-container .chev-right' , function ( event ) {
2013-08-19 22:30:57 +09:00
$ ( this ) . parent ( '.stream-selection' ) . remove ( ) ;
updateHistoryLocalStorage ( ) ;
} ) ;
/ * ·
·
· When sorting the history menu
·
· · · · · · · · · · · · · * /
2014-01-29 03:42:47 +09:00
2013-08-19 22:30:57 +09:00
$ ( '#history-container' ) . on ( "sortupdate" , function ( ) {
updateHistoryLocalStorage ( ) ;
} ) ;
/ * ·
·
· Load more from the current stream when scroll is 1000 px from bottom
·
· The search API is crap and don ' t do max _id and last _id , so we have to do pages there ...
·
· · · · · · · · · · · · · * /
$ ( window ) . scroll ( function ( ) {
if ( $ ( window ) . scrollTop ( ) + $ ( window ) . height ( ) > $ ( document ) . height ( ) - 1000 ) {
2013-11-29 20:49:54 +09:00
// not if we're already loading or if no stream is set yet
if ( ! $ ( 'body' ) . hasClass ( 'loading-older' ) && typeof window . currentStream != "undefined" ) {
2013-08-20 22:26:25 +09:00
$ ( 'body' ) . addClass ( 'loading-older' ) ;
// remove loading class in 10 seconds, i.e. try again if failed to load within 10 s
if ( window . currentStream . substring ( 0 , 6 ) != 'search' ) {
setTimeout ( function ( ) { $ ( 'body' ) . removeClass ( 'loading-older' ) ; } , 10000 ) ;
}
var lastStreamItemId = $ ( '#feed-body' ) . children ( '.stream-item' ) . last ( ) . attr ( 'id' ) ;
// if this is search or users lists, we need page and rpp vars, we store page number in an attribute
if ( window . currentStream . substring ( 0 , 6 ) == 'search'
|| window . currentStream . substring ( 0 , 23 ) == 'statuses/followers.json'
|| window . currentStream . substring ( 0 , 21 ) == 'statuses/friends.json'
|| window . currentStream . substring ( 0 , 26 ) == 'statusnet/groups/list.json'
|| window . currentStream . substring ( 0 , 28 ) == 'statusnet/groups/membership/'
|| window . currentStream . substring ( 0 , 24 ) == 'statusnet/groups/admins/' ) {
if ( typeof $ ( '#feed-body' ) . attr ( 'data-search-page-number' ) != 'undefined' ) {
var searchPage = parseInt ( $ ( '#feed-body' ) . attr ( 'data-search-page-number' ) , 10 ) ;
2013-08-19 22:30:57 +09:00
}
else {
2013-08-20 22:26:25 +09:00
var searchPage = 2 ;
2013-08-19 22:30:57 +09:00
}
2013-08-20 22:26:25 +09:00
var nextPage = searchPage + 1 ;
var getVars = qOrAmp ( window . currentStream ) + 'rpp=20&page=' + searchPage ; // search uses 'rrp' var and others 'count' for paging, though we can add rrp to others aswell without any problem
}
// normal streams
else {
2015-01-19 23:41:52 +09:00
var getVars = qOrAmp ( window . currentStream ) + 'max_id=' + ( $ ( '#feed-body' ) . children ( '.stream-item' ) . last ( ) . attr ( 'data-quitter-id-in-stream' ) - 1 ) ;
2013-08-20 22:26:25 +09:00
}
2014-11-24 21:47:45 +09:00
display _spinner ( '#footer-spinner-container' ) ;
2013-08-20 22:26:25 +09:00
getFromAPI ( window . currentStream + getVars , function ( data ) {
if ( data ) {
addToFeed ( data , lastStreamItemId , 'visible' ) ;
$ ( 'body' ) . removeClass ( 'loading-older' ) ;
2013-08-19 22:30:57 +09:00
2013-08-20 22:26:25 +09:00
// if this is search our group users lists, we remember page number
if ( window . currentStream . substring ( 0 , 6 ) == 'search'
|| window . currentStream . substring ( 0 , 23 ) == 'statuses/followers.json'
|| window . currentStream . substring ( 0 , 21 ) == 'statuses/friends.json'
|| window . currentStream . substring ( 0 , 26 ) == 'statusnet/groups/list.json'
|| window . currentStream . substring ( 0 , 28 ) == 'statusnet/groups/membership/'
|| window . currentStream . substring ( 0 , 24 ) == 'statusnet/groups/admins/' ) {
$ ( '#feed-body' ) . attr ( 'data-search-page-number' , nextPage ) ;
2013-08-19 22:30:57 +09:00
}
2013-08-20 22:26:25 +09:00
remove _spinner ( ) ;
}
} ) ;
}
}
2013-08-19 22:30:57 +09:00
} ) ;
/ * ·
·
· Updates all queets ' times / dates
·
· · · · · · · · · · · · · * /
var updateTimesInterval = self . setInterval ( function ( ) {
$ ( '.created-at' ) . each ( function ( ) {
$ ( this ) . children ( 'a' ) . html ( parseTwitterDate ( $ ( this ) . attr ( 'data-created-at' ) ) ) ;
} ) ;
} , 10000 ) ;
/ * ·
·
2014-11-24 21:47:45 +09:00
· Check for new queets
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · · · · · * /
var checkForNewQueetsInterval = window . setInterval ( function ( ) { checkForNewQueets ( ) } , window . timeBetweenPolling ) ;
function checkForNewQueets ( ) {
// no new requests if requests are very slow, e.g. searches
if ( ! $ ( 'body' ) . hasClass ( 'loading-newer' ) ) {
$ ( 'body' ) . addClass ( 'loading-newer' ) ;
// only of logged in and not user stream
if ( $ ( '#user-container' ) . css ( 'display' ) == 'block' && $ ( '.stream-item.user' ) . length == 0 ) {
var lastId = $ ( '#feed-body' ) . children ( '.stream-item' ) . not ( '.temp-post' ) . attr ( 'data-quitter-id-in-stream' ) ;
var addThisStream = window . currentStream ;
2014-11-24 21:47:45 +09:00
var timeNow = new Date ( ) . getTime ( ) ;
2013-08-19 22:30:57 +09:00
getFromAPI ( addThisStream + qOrAmp ( window . currentStream ) + 'since_id=' + lastId , function ( data ) {
if ( data ) {
$ ( 'body' ) . removeClass ( 'loading-newer' ) ;
if ( addThisStream == window . currentStream ) {
addToFeed ( data , false , 'hidden' ) ;
}
}
} ) ;
}
// if we have hidden items, show new-queets-bar
if ( $ ( '#feed-body' ) . find ( '.stream-item.hidden' ) . length > 0 ) {
var new _queets _num = $ ( '#feed-body' ) . find ( '.stream-item.hidden' ) . length ;
2014-09-25 06:20:35 +09:00
// if this is notifications page, update site title with hidden notification count
if ( window . currentStream == 'qvitter/statuses/notifications.json' ) {
document . title = window . siteTitle + ' (' + new _queets _num + ')' ;
}
2013-08-19 22:30:57 +09:00
$ ( '#new-queets-bar' ) . parent ( ) . removeClass ( 'hidden' ) ;
// text plural
if ( new _queets _num == 1 ) {
var q _txt = ' ' + window . sL . newQueet ;
}
else {
var q _txt = ' ' + window . sL . newQueets ;
}
$ ( '#new-queets-bar' ) . html ( new _queets _num + q _txt ) ;
2013-08-20 07:16:01 +09:00
}
2013-08-19 22:30:57 +09:00
}
}
/ * ·
·
· Show hidden queets when user clicks on new - queets - bar
·
· · · · · · · · · · · · · * /
2014-01-29 03:42:47 +09:00
$ ( 'body' ) . on ( 'click' , '#new-queets-bar' , function ( ) {
2014-09-25 06:20:35 +09:00
if ( window . currentStream == 'qvitter/statuses/notifications.json' ) {
document . title = window . siteTitle ;
}
2013-08-19 22:30:57 +09:00
$ ( '.stream-item.hidden' ) . css ( 'opacity' , '0' )
$ ( '.stream-item.hidden' ) . animate ( { opacity : '1' } , 200 ) ;
$ ( '.stream-item.hidden' ) . removeClass ( 'hidden' ) ;
$ ( '#new-queets-bar' ) . parent ( ) . addClass ( 'hidden' ) ;
} ) ;
/ * ·
·
· Expand and de - expand queets when clicking anywhere but on a few element types
·
· · · · · · · · · · · · · * /
2014-01-29 03:42:47 +09:00
$ ( 'body' ) . on ( 'click' , '.queet' , function ( event ) {
2013-08-19 22:30:57 +09:00
if ( ! $ ( event . target ) . is ( 'a' )
2013-11-23 08:31:04 +09:00
&& ! $ ( event . target ) . is ( '.cm-mention' )
&& ! $ ( event . target ) . is ( '.cm-tag' )
&& ! $ ( event . target ) . is ( '.cm-group' )
&& ! $ ( event . target ) . is ( '.cm-url' )
&& ! $ ( event . target ) . is ( 'pre' )
2013-08-19 22:30:57 +09:00
&& ! $ ( event . target ) . is ( '.name' )
2014-11-24 21:47:45 +09:00
&& ! $ ( event . target ) . is ( '.queet-box' )
&& ! $ ( event . target ) . is ( '.syntax-two' )
2013-11-23 08:31:04 +09:00
&& ! $ ( event . target ) . is ( 'img' )
2013-08-19 22:30:57 +09:00
&& ! $ ( event . target ) . is ( 'button' )
&& ! $ ( event . target ) . is ( '.show-full-conversation' )
&& ! $ ( event . target ) . is ( 'span.mention' )
&& ! $ ( event . target ) . is ( '.action-reply-container a span' )
&& ! $ ( event . target ) . is ( '.action-reply-container a b' )
&& ! $ ( event . target ) . is ( '.action-rt-container a span' )
&& ! $ ( event . target ) . is ( '.action-rt-container a b' )
&& ! $ ( event . target ) . is ( '.action-del-container a span' )
&& ! $ ( event . target ) . is ( '.action-del-container a b' )
&& ! $ ( event . target ) . is ( '.action-fav-container a span' )
2015-01-22 03:15:22 +09:00
&& ! $ ( event . target ) . is ( '.action-fav-container a b' )
&& ! $ ( event . target ) . is ( '.action-ellipsis-container a span' )
&& ! $ ( event . target ) . is ( '.action-ellipsis-container a b' )
2013-08-19 22:30:57 +09:00
&& ! $ ( event . target ) . is ( 'span.group' )
&& ! $ ( event . target ) . is ( '.longdate' )
&& ! $ ( event . target ) . is ( '.screen-name' )
2013-09-03 01:13:15 +09:00
&& ! $ ( this ) . parent ( '.stream-item' ) . hasClass ( 'user' ) ) { // not if user stream
2013-08-19 22:30:57 +09:00
expand _queet ( $ ( this ) . parent ( ) ) ;
}
} ) ;
2013-11-23 08:31:04 +09:00
/ * ·
·
2015-01-27 09:57:08 +09:00
· Collapse all open conversations and ellipsis menus on esc or when clicking the margin
2013-11-23 08:31:04 +09:00
·
· · · · · · · · · · · · · * /
2013-08-19 22:30:57 +09:00
2013-11-23 08:31:04 +09:00
$ ( 'body' ) . click ( function ( event ) {
if ( $ ( event . target ) . is ( 'body' ) ) {
2015-01-27 09:57:08 +09:00
$ ( '.action-ellipsis-container' ) . children ( '.dropdown-menu' ) . remove ( ) ;
2013-11-23 08:31:04 +09:00
$ . each ( $ ( '.stream-item.expanded' ) , function ( ) {
expand _queet ( $ ( this ) , false ) ;
} ) ;
}
} ) ;
$ ( document ) . keyup ( function ( e ) {
if ( e . keyCode == 27 ) { // esc
2015-01-27 09:57:08 +09:00
$ ( '.action-ellipsis-container' ) . children ( '.dropdown-menu' ) . remove ( ) ;
2013-11-23 08:31:04 +09:00
$ . each ( $ ( '.stream-item.expanded' ) , function ( ) {
expand _queet ( $ ( this ) , false ) ;
} ) ;
}
} ) ;
2013-08-19 22:30:57 +09:00
/ * ·
·
· When clicking the delete - button
·
· · · · · · · · · · · · · * /
2015-01-27 09:57:08 +09:00
$ ( 'body' ) . on ( 'click' , '.action-ellipsis-container .delete-queet' , function ( e ) {
e . preventDefault ( ) ;
var this _stream _item = $ ( this ) . closest ( '.stream-item' ) ;
2014-11-24 21:47:45 +09:00
// don't do anything if this is a queet being posted
if ( this _stream _item . hasClass ( 'temp-post' ) ) {
return ;
}
2013-08-19 22:30:57 +09:00
var this _qid = this _stream _item . attr ( 'data-quitter-id' ) ;
var $queetHtml = $ ( '<div>' ) . append ( this _stream _item . html ( ) ) ;
var $stuffToRemove = $queetHtml . find ( '.stream-item-footer, .expanded-content, .inline-reply-queetbox, .stream-item.conversation, .view-more-container-top, .view-more-container-bottom' ) ;
$stuffToRemove . remove ( ) ;
var queetHtmlWithoutFooterAndConversation = $queetHtml . html ( ) ;
popUpAction ( 'popup-delete-' + this _qid , window . sL . deleteConfirmation , queetHtmlWithoutFooterAndConversation , '<div class="right"><button class="close">' + window . sL . cancelVerb + '</button><button class="primary">' + window . sL . deleteVerb + '</button></div>' ) ;
$ ( '#popup-delete-' + this _qid + ' button.primary' ) . on ( 'click' , function ( ) {
display _spinner ( ) ;
$ ( '.modal-container' ) . remove ( ) ;
// delete
postActionToAPI ( 'statuses/destroy/' + this _qid + '.json' , function ( data ) {
if ( data ) {
remove _spinner ( ) ;
// remove the stream-item clicked and all other displays of this object from dom (e.g. in conversation)
$ ( '.stream-item[data-quitter-id="' + this _qid + '"]' ) . find ( '.queet' ) . animate ( { opacity : '0' } , 700 , function ( ) {
$ ( '.stream-item[data-quitter-id="' + this _qid + '"]' ) . remove ( ) ;
} ) ;
}
else {
remove _spinner ( ) ;
}
} ) ;
} ) ;
} ) ;
/ * ·
·
· When clicking the requeet - button
·
· · · · · · · · · · · · · * /
2015-01-27 09:57:08 +09:00
$ ( 'body' ) . on ( 'click' , '.action-rt-container .icon:not(.is-mine)' , function ( ) {
var this _stream _item = $ ( this ) . closest ( '.stream-item' ) ;
var this _action = $ ( this ) . closest ( 'li' ) ;
2013-08-19 22:30:57 +09:00
// requeet
if ( ! this _action . children ( '.with-icn' ) . hasClass ( 'done' ) ) {
this _action . children ( '.with-icn' ) . addClass ( 'done' ) ;
2014-11-24 21:47:45 +09:00
this _stream _item . addClass ( 'requeeted' ) ;
// requeet animation
this _action . children ( '.with-icn' ) . children ( '.sm-rt' ) . addClass ( 'rotate' ) ;
2013-08-19 22:30:57 +09:00
// post requeet
postActionToAPI ( 'statuses/retweet/' + this _stream _item . attr ( 'data-quitter-id' ) + '.json' , function ( data ) {
if ( data ) {
// success
this _stream _item . attr ( 'data-requeeted-by-me-id' , data . id ) ;
}
else {
// error
this _action . children ( '.with-icn' ) . removeClass ( 'done' ) ;
this _action . find ( '.with-icn b' ) . html ( window . sL . requeetVerb ) ;
this _stream _item . removeClass ( 'requeeted' ) ;
}
} ) ;
}
// un-requeet
else if ( this _action . children ( '.with-icn' ) . hasClass ( 'done' ) ) {
display _spinner ( ) ;
// if we don't have the id od the repeat stored in DOM, we need to look it up
// (might be a problem if there's more than 100 repeats)
if ( typeof this _stream _item . attr ( 'data-requeeted-by-me-id' ) == 'undefined' ) {
getFavsOrRequeetsForQueet ( 'requeets' , this _stream _item . attr ( 'data-quitter-id' ) , function ( data ) {
$ . each ( data , function ( key , obj ) {
if ( window . myUserID == obj . user . id ) {
var my _rq _id = obj . id ;
unRequeet ( this _stream _item , this _action , my _rq _id ) ;
}
} ) ;
} ) ;
}
// if we have the id stored in DOM
else {
var my _rq _id = this _stream _item . attr ( 'data-requeeted-by-me-id' ) ;
unRequeet ( this _stream _item , this _action , my _rq _id ) ;
}
}
} ) ;
/ * ·
·
· When clicking the fav - button
·
· · · · · · · · · · · · · * /
2014-01-29 03:42:47 +09:00
$ ( 'body' ) . on ( 'click' , '.action-fav-container' , function ( ) {
2013-08-19 22:30:57 +09:00
var this _stream _item = $ ( this ) . parent ( ) . parent ( ) . parent ( ) . parent ( ) . parent ( ) ;
2014-11-24 21:47:45 +09:00
// don't do anything if this is a queet being posted
if ( this _stream _item . hasClass ( 'temp-post' ) ) {
return ;
}
2013-08-19 22:30:57 +09:00
var this _action = $ ( this ) ;
// fav
if ( ! this _action . children ( '.with-icn' ) . hasClass ( 'done' ) ) {
2014-11-24 21:47:45 +09:00
2013-08-19 22:30:57 +09:00
this _action . children ( '.with-icn' ) . addClass ( 'done' ) ;
this _stream _item . addClass ( 'favorited' ) ;
2014-11-24 21:47:45 +09:00
// fav animation
this _action . children ( '.with-icn' ) . children ( '.sm-fav' ) . addClass ( 'pulse' ) ;
2013-08-19 22:30:57 +09:00
// post fav
postActionToAPI ( 'favorites/create/' + this _stream _item . attr ( 'data-quitter-id' ) + '.json' , function ( data ) {
if ( data ) {
// success
}
else {
// error
this _action . children ( '.with-icn' ) . removeClass ( 'done' ) ;
this _action . find ( '.with-icn b' ) . html ( window . sL . favoriteVerb ) ;
this _stream _item . removeClass ( 'favorited' ) ;
}
} ) ;
}
// unfav
else {
display _spinner ( ) ;
this _action . children ( '.with-icn' ) . removeClass ( 'done' ) ;
this _action . find ( '.with-icn b' ) . html ( window . sL . favoriteVerb ) ;
this _stream _item . removeClass ( 'favorited' ) ;
// post unfav
postActionToAPI ( 'favorites/destroy/' + this _stream _item . attr ( 'data-quitter-id' ) + '.json' , function ( data ) {
if ( data ) {
// success
remove _spinner ( ) ;
}
else {
// error
remove _spinner ( ) ;
this _action . children ( '.with-icn' ) . addClass ( 'done' ) ;
this _action . find ( '.with-icn b' ) . html ( window . sL . favoritedVerb ) ;
this _stream _item . addClass ( 'favorited' ) ;
}
} ) ;
}
} ) ;
/ * ·
·
· When clicking the reply - button
·
· · · · · · · · · · · · · * /
2014-01-29 03:42:47 +09:00
$ ( 'body' ) . on ( 'click' , '.action-reply-container' , function ( ) {
2014-11-24 21:47:45 +09:00
2013-11-23 08:31:04 +09:00
var this _stream _item = $ ( this ) . closest ( '.stream-item' ) ;
2014-11-24 21:47:45 +09:00
// don't do anything if this is a queet being posted
if ( this _stream _item . hasClass ( 'temp-post' ) ) {
return ;
}
2013-08-19 22:30:57 +09:00
var this _stream _item _id = this _stream _item . attr ( 'data-quitter-id' ) ;
2014-11-24 21:47:45 +09:00
this _stream _item . addClass ( 'replying-to' ) ;
2013-11-23 08:31:04 +09:00
// grabbing the queet and view it in the popup, stripped of footer, reply box and other sruff
var $queetHtml = $ ( '<div>' ) . append ( this _stream _item . children ( '.queet' ) . outerHTML ( ) ) ;
var $queetHtmlFooter = $queetHtml . find ( '.stream-item-footer' ) ;
$queetHtmlFooter . remove ( ) ;
var $queetHtmlQueetBox = $queetHtml . find ( '.inline-reply-queetbox' ) ;
$queetHtmlQueetBox . remove ( ) ;
var $queetHtmlExpandedContent = $queetHtml . find ( '.expanded-content' ) ;
$queetHtmlExpandedContent . remove ( ) ;
var queetHtmlWithoutFooter = $queetHtml . html ( ) ;
popUpAction ( 'popup-reply-' + this _stream _item _id , window . sL . replyTo + ' ' + this _stream _item . find ( '.screen-name' ) . html ( ) , replyFormHtml ( this _stream _item , this _stream _item _id ) , queetHtmlWithoutFooter ) ;
2014-10-03 02:24:54 +09:00
// fix the width of the queet box, otherwise the syntax highlighting break
var queetBoxWidth = $ ( '#popup-reply-' + this _stream _item _id ) . find ( '.modal-body' ) . find ( '.inline-reply-queetbox' ) . width ( ) - 20 ;
$ ( '#popup-reply-' + this _stream _item _id ) . find ( '.modal-body' ) . find ( '.queet-box-syntax' ) . width ( queetBoxWidth ) ;
$ ( '#popup-reply-' + this _stream _item _id ) . find ( '.modal-body' ) . find ( '.syntax-middle' ) . width ( queetBoxWidth ) ;
2014-10-06 18:30:33 +09:00
$ ( '#popup-reply-' + this _stream _item _id ) . find ( '.modal-body' ) . find ( '.syntax-two' ) . width ( queetBoxWidth ) ;
2014-10-03 02:24:54 +09:00
2014-05-28 03:40:51 +09:00
$ ( '#popup-reply-' + this _stream _item _id ) . find ( '.modal-body' ) . find ( '.queet-box' ) . trigger ( 'click' ) ; // expand
2013-11-23 08:31:04 +09:00
} ) ;
2013-08-19 22:30:57 +09:00
2013-11-23 08:31:04 +09:00
/ * ·
·
2014-11-24 21:47:45 +09:00
· When clicking the compose button
2013-11-23 08:31:04 +09:00
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'click' , '#top-compose' , function ( ) {
2014-05-28 03:40:51 +09:00
popUpAction ( 'popup-compose' , window . sL . compose , queetBoxHtml ( ) , false ) ;
$ ( '#popup-compose' ) . find ( '.queet-box' ) . width ( $ ( '#popup-compose' ) . find ( '.inline-reply-queetbox' ) . width ( ) - 20 ) ;
$ ( '#popup-compose' ) . find ( '.queet-box' ) . trigger ( 'click' ) ;
2013-08-19 22:30:57 +09:00
} ) ;
/ * ·
·
· Close popups
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'click' , '.modal-container button.close' , function ( ) {
2014-11-24 21:47:45 +09:00
$ ( '.stream-item' ) . removeClass ( 'replying-to' ) ;
2013-08-19 22:30:57 +09:00
$ ( '.modal-container' ) . remove ( ) ;
} ) ;
$ ( 'body' ) . on ( 'click' , '.modal-close' , function ( ) {
2014-11-24 21:47:45 +09:00
$ ( '.stream-item' ) . removeClass ( 'replying-to' ) ;
2013-08-19 22:30:57 +09:00
$ ( '.modal-container' ) . remove ( ) ;
} ) ;
2014-11-24 21:47:45 +09:00
$ ( 'body' ) . on ( 'click' , '.modal-container' , function ( e ) {
if ( $ ( e . target ) . is ( '.modal-container' ) ) {
$ ( '.stream-item' ) . removeClass ( 'replying-to' ) ;
$ ( '.modal-container' ) . remove ( ) ;
abortEditProfile ( ) ;
}
} ) ;
2013-08-19 22:30:57 +09:00
$ ( document ) . keyup ( function ( e ) {
if ( e . keyCode == 27 ) {
2014-11-24 21:47:45 +09:00
$ ( '.stream-item' ) . removeClass ( 'replying-to' ) ;
2013-08-19 22:30:57 +09:00
$ ( '.modal-container' ) . remove ( ) ;
2014-06-02 04:51:28 +09:00
abortEditProfile ( ) ;
2013-08-19 22:30:57 +09:00
}
} ) ;
/ * ·
·
2014-05-28 03:40:51 +09:00
· Post queets , inline and popup replies
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'click' , '.queet-toolbar button' , function ( ) {
if ( $ ( this ) . hasClass ( 'enabled' ) ) {
// set temp post id
if ( $ ( '.temp-post' ) . length == 0 ) {
var tempPostId = 'stream-item-temp-post-i' ;
}
else {
var tempPostId = $ ( '.temp-post' ) . attr ( 'id' ) + 'i' ;
}
2014-05-28 03:40:51 +09:00
var queetBox = $ ( this ) . parent ( ) . parent ( ) . siblings ( '.queet-box' ) ;
var queetBoxID = queetBox . attr ( 'id' ) ;
2015-01-27 03:22:05 +09:00
// jquery's .text() function is not consistent in converting <br>:s to \n:s,
// so we do this detour to make sure line breaks are preserved
queetBox . html ( queetBox . html ( ) . replace ( /<br>/g , '{{{lb}}}' ) ) ;
var queetText = $ . trim ( queetBox . text ( ) . replace ( /^\s+|\s+$/g , '' ) . replace ( /\n/g , '' ) ) ;
queetText = queetText . replace ( /{{{lb}}}/g , "\n" ) ;
var queetTempText = replaceHtmlSpecialChars ( queetText . replace ( /\n/g , '<br>' ) ) ; // no xss
queetTempText = queetTempText . replace ( /<br>/g , '<br>' ) ; // but preserve line breaks
var queetHtml = '<div id="' + tempPostId + '" class="stream-item conversation temp-post" style="opacity:1"><div class="queet"><span class="dogear"></span><div class="queet-content"><div class="stream-item-header"><a class="account-group"><img class="avatar" src="' + $ ( '#user-avatar' ) . attr ( 'src' ) + '" /><strong class="name">' + $ ( '#user-name' ) . html ( ) + '</strong> <span class="screen-name">@' + $ ( '#user-screen-name' ) . html ( ) + '</span></a><small class="created-at">posting</small></div><div class="queet-text">' + queetTempText + '</div><div class="stream-item-footer"><ul class="queet-actions"><li class="action-reply-container"><a class="with-icn"><span class="icon sm-reply" title="' + window . sL . replyVerb + '"></span></a></li><li class="action-del-container"><a class="with-icn"><span class="icon sm-trash" title="' + window . sL . deleteVerb + '"></span></a></li></i></li><li class="action-fav-container"><a class="with-icn"><span class="icon sm-fav" title="' + window . sL . favoriteVerb + '"></span></a></li></ul></div></div></div></div>' ;
2014-01-29 03:42:47 +09:00
queetHtml = detectRTL ( queetHtml ) ;
2014-05-28 03:40:51 +09:00
// popup reply
if ( $ ( '.modal-container' ) . find ( '.toolbar-reply button' ) . length > 0 ) {
var in _reply _to _status _id = $ ( '.modal-container' ) . attr ( 'id' ) . substring ( 12 ) ;
}
// if this is a inline reply
else if ( queetBox . parent ( ) . hasClass ( 'inline-reply-queetbox' ) ) {
var in _reply _to _status _id = queetBox . closest ( '.stream-item' ) . attr ( 'data-quitter-id' ) ;
}
// not a reply
else {
var in _reply _to _status _id = false ;
}
2013-11-23 08:31:04 +09:00
2014-11-24 21:47:45 +09:00
// remove any popups
$ ( '.modal-container' ) . remove ( ) ;
// try to find a queet to add the temp queet to
if ( $ ( '.stream-item.replying-to' ) . length > 0 ) {
// if the queet is in conversation, add it to parent's conversation
if ( $ ( '.stream-item.replying-to' ) . hasClass ( 'conversation' ) ) {
$ ( '.stream-item.replying-to' ) . parent ( ) . append ( queetHtml ) ;
}
else {
// if the queet is expanded, add it to its conversation
if ( $ ( '.stream-item.replying-to' ) . hasClass ( 'expanded' ) ) {
$ ( '.stream-item.replying-to' ) . append ( queetHtml ) ;
}
// it it's not expanded, add it to top
else {
$ ( '#feed-body' ) . prepend ( queetHtml . replace ( 'class="stream-item conversation' , 'class="stream-item' ) ) ;
}
}
$ ( '.stream-item' ) . removeClass ( 'replying-to' ) ;
}
else if ( $ ( '.stream-item.expanded[data-quitter-id="' + in _reply _to _status _id + '"]' ) . length > 0 ) {
2014-05-28 03:40:51 +09:00
$ ( '.stream-item.expanded[data-quitter-id="' + in _reply _to _status _id + '"]' ) . append ( queetHtml ) ;
2013-08-19 22:30:57 +09:00
}
2014-11-24 21:47:45 +09:00
// if we cant find a proper place, add it to top and remove conversation class
// but only if this is either 1) our home/all feed, 2) our user timeline or 3) whole site or 4) whole network
else if ( window . currentStream . indexOf ( 'statuses/friends_timeline.json' ) > - 1
|| window . currentStream . indexOf ( 'statuses/user_timeline.json?screen_name=' + window . loggedIn . screen _name ) > - 1
|| window . currentStream . indexOf ( 'statuses/public_timeline.json' ) > - 1
|| window . currentStream . indexOf ( 'statuses/public_and_external_timeline.json' ) > - 1
) {
$ ( '#feed-body' ) . prepend ( queetHtml . replace ( 'class="stream-item conversation' , 'class="stream-item' ) ) ;
2014-05-28 03:40:51 +09:00
}
2014-11-24 21:47:45 +09:00
// don't add it to the current stream, open a popup instead, without conversation class
2014-05-28 03:40:51 +09:00
else {
2014-11-24 21:47:45 +09:00
popUpAction ( 'popup-sending' , '' , queetHtml . replace ( 'class="stream-item conversation' , 'class="stream-item' ) , false ) ;
2014-05-28 03:40:51 +09:00
}
2013-08-19 22:30:57 +09:00
// null reply box
2014-05-28 03:40:51 +09:00
collapseQueetBox ( queetBox )
2013-08-19 22:30:57 +09:00
// check for new queets (one second from) NOW
setTimeout ( 'checkForNewQueets()' , 1000 ) ;
// post queet
2014-05-28 03:40:51 +09:00
postQueetToAPI ( queetText , in _reply _to _status _id , function ( data ) { if ( data ) {
2013-08-19 22:30:57 +09:00
// show real queet
var new _queet = Array ( ) ;
new _queet [ 0 ] = data ;
2014-10-17 23:06:39 +09:00
addToFeed ( new _queet , tempPostId , 'visible' , true ) ;
2014-11-24 21:47:45 +09:00
2013-08-19 22:30:57 +09:00
// remove temp queet
$ ( '#' + tempPostId ) . remove ( ) ;
2013-11-23 08:31:04 +09:00
// queet count
$ ( '#user-queets strong' ) . html ( parseInt ( $ ( '#user-queets strong' ) . html ( ) , 10 ) + 1 ) ;
2013-08-19 22:30:57 +09:00
} } ) ;
}
} ) ;
2013-11-23 08:31:04 +09:00
2013-08-19 22:30:57 +09:00
/ * ·
·
2014-11-24 21:47:45 +09:00
· Count chars in queet box on keyup , also check for any attachments to show / hide
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · · · · · * /
2014-05-28 03:40:51 +09:00
$ ( 'body' ) . on ( 'keyup input paste' , '.queet-box-syntax' , function ( ) {
2014-11-24 21:47:45 +09:00
2014-05-28 03:40:51 +09:00
countCharsInQueetBox ( $ ( this ) , $ ( this ) . siblings ( '.queet-toolbar' ) . find ( '.queet-counter' ) , $ ( this ) . siblings ( '.queet-toolbar' ) . find ( '.queet-button button' ) ) ;
2014-11-24 21:47:45 +09:00
var attachments = $ ( this ) . siblings ( '.upload-image-container' ) ;
$ . each ( attachments , function ( k , attachment ) {
var attachmentShorturl = $ ( attachment ) . children ( 'img' ) . attr ( 'data-shorturl' ) ;
if ( $ ( attachment ) . siblings ( '.queet-box-syntax' ) . text ( ) . indexOf ( attachmentShorturl ) > - 1 ) {
$ ( attachment ) . show ( ) ;
}
else {
$ ( attachment ) . hide ( ) ;
}
} ) ;
2014-05-28 03:40:51 +09:00
} ) ;
2015-01-27 04:09:42 +09:00
/ * ·
·
· Middle button expands queet box
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'mousedown' , '.queet-box-syntax' , function ( e ) {
if ( e . which == 2 ) {
e . preventDefault ( ) ;
$ ( this ) . trigger ( 'click' ) ;
}
} ) ;
2014-09-20 09:53:10 +09:00
/ * ·
·
· Shorten URL ' s
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'click' , 'button.shorten' , function ( ) {
shortenUrlsInBox ( $ ( this ) ) ;
} ) ;
/ * ·
·
· Reload current stream
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'click' , '.reload-stream' , function ( ) {
$ ( '.reload-stream' ) . hide ( ) ;
setNewCurrentStream ( window . currentStream , function ( ) {
$ ( '.reload-stream' ) . show ( ) ;
} , false ) ;
} ) ;
2014-05-28 03:40:51 +09:00
/ * ·
·
· Expand / collapse queet box on click and blur
·
· · · · · · · · · · · · · * /
2013-08-19 22:30:57 +09:00
2014-11-24 21:47:45 +09:00
$ ( 'body' ) . on ( 'click contextmenu' , '.queet-box-syntax' , function ( ) {
2014-05-28 03:40:51 +09:00
if ( $ ( this ) . html ( ) == decodeURIComponent ( $ ( this ) . attr ( 'data-start-text' ) ) ) {
$ ( this ) . attr ( 'contenteditable' , 'true' ) ;
$ ( this ) . focus ( ) ;
$ ( this ) . siblings ( '.syntax-middle' ) . html ( ' ' ) ;
$ ( this ) . siblings ( '.syntax-two' ) . html ( ' ' ) ;
$ ( this ) . siblings ( '.queet-toolbar' ) . css ( 'display' , 'block' ) ;
$ ( this ) . siblings ( '.syntax-middle' ) . css ( 'display' , 'block' ) ;
$ ( this ) . siblings ( '.mentions-suggestions' ) . css ( 'display' , 'block' ) ;
$ ( this ) . siblings ( '.syntax-two' ) . css ( 'display' , 'block' ) ;
$ ( this ) . siblings ( '.queet-toolbar' ) . find ( '.queet-button button' ) . addClass ( 'disabled' ) ;
countCharsInQueetBox ( $ ( this ) , $ ( this ) . siblings ( '.queet-toolbar .queet-counter' ) , $ ( this ) . siblings ( '.queet-toolbar button' ) ) ;
$ ( this ) [ 0 ] . addEventListener ( "paste" , stripHtmlFromPaste ) ;
if ( typeof $ ( this ) . attr ( 'data-replies-text' ) != 'undefined' ) {
$ ( this ) . html ( decodeURIComponent ( $ ( this ) . attr ( 'data-replies-text' ) ) ) ;
2014-11-29 12:29:18 +09:00
var repliesLen = decodeURIComponent ( $ ( this ) . attr ( 'data-replies-text' ) ) . length - 5 ;
2014-05-28 03:40:51 +09:00
setSelectionRange ( $ ( this ) [ 0 ] , repliesLen , repliesLen ) ;
2013-08-19 22:30:57 +09:00
}
else {
2014-11-29 12:29:18 +09:00
$ ( this ) . html ( '' ) ;
2013-08-19 22:30:57 +09:00
}
2014-05-28 03:40:51 +09:00
$ ( this ) . trigger ( 'input' ) ;
}
} ) ;
2014-11-24 21:47:45 +09:00
$ ( 'body' ) . on ( 'mousedown' , '.syntax-two' , function ( ) {
$ ( this ) . addClass ( 'clicked' ) ;
} ) ;
$ ( 'body' ) . on ( 'blur' , '.queet-box-syntax' , function ( e ) {
// don't collapse if upload-image-button has been clicked
var uploadImageButton = $ ( this ) . siblings ( '.queet-toolbar' ) . find ( 'button.upload-image' ) ;
if ( uploadImageButton . hasClass ( 'clicked' ) ) {
uploadImageButton . removeClass ( 'clicked' ) ;
return true ;
}
// don't collapse if we're clicking around inside queet-box
var syntaxTwoBox = $ ( this ) . siblings ( '.syntax-two' ) ;
if ( syntaxTwoBox . hasClass ( 'clicked' ) ) {
syntaxTwoBox . removeClass ( 'clicked' ) ;
return true ;
}
// don't collapse if we're in a modal
2014-05-28 03:40:51 +09:00
if ( $ ( this ) . parent ( ) . parent ( ) . hasClass ( 'modal-body' ) ) {
2014-11-24 21:47:45 +09:00
return true ;
2014-05-28 03:40:51 +09:00
}
2014-11-24 21:47:45 +09:00
// collapse if nothing is change
if ( $ ( this ) . attr ( 'data-replies-text' ) != 'undefined' ) {
2014-05-28 03:40:51 +09:00
var $startText = $ ( '<div/>' ) . append ( decodeURIComponent ( $ ( this ) . attr ( 'data-replies-text' ) ) ) ;
if ( $ . trim ( $startText . text ( ) ) == $ . trim ( $ ( this ) . text ( ) ) || $ ( this ) . html ( ) . length == 0 || $ ( this ) . html ( ) == '<br>' || $ ( this ) . html ( ) == '<br />' || $ ( this ) . html ( ) == ' ' || $ ( this ) . html ( ) == ' <br>' ) {
collapseQueetBox ( $ ( this ) ) ;
}
}
2014-11-24 21:47:45 +09:00
// collapse if empty
2014-05-28 03:40:51 +09:00
else if ( $ ( this ) . html ( ) . length == 0 || $ ( this ) . html ( ) == '<br>' || $ ( this ) . html ( ) == '<br />' || $ ( this ) . html ( ) == ' ' || $ ( this ) . html ( ) == ' <br>' ) {
collapseQueetBox ( $ ( this ) ) ;
}
} ) ;
function collapseQueetBox ( qB ) {
2014-11-24 21:47:45 +09:00
qB . siblings ( '.upload-image-container' ) . remove ( ) ;
2014-05-28 03:40:51 +09:00
qB . siblings ( '.syntax-middle' ) . css ( 'display' , 'none' ) ;
qB . siblings ( '.syntax-two' ) . css ( 'display' , 'none' ) ;
qB . siblings ( '.mentions-suggestions' ) . css ( 'display' , 'none' ) ;
qB . attr ( 'contenteditable' , 'false' ) ;
qB . html ( decodeURIComponent ( qB . attr ( 'data-start-text' ) ) ) ;
qB . siblings ( '.queet-toolbar' ) . find ( 'button' ) . removeClass ( 'enabled' ) ;
qB . siblings ( '.queet-toolbar' ) . css ( 'display' , 'none' ) ;
qB . removeAttr ( 'style' ) ;
2014-11-24 21:47:45 +09:00
qB [ 0 ] . removeEventListener ( "paste" , stripHtmlFromPaste ) ;
2014-05-28 03:40:51 +09:00
}
2013-08-19 22:30:57 +09:00
2014-05-28 03:40:51 +09:00
2013-08-19 22:30:57 +09:00
2014-05-28 03:40:51 +09:00
/ * ·
·
· Syntax highlighting in queetbox
·
· · · · · · · · · · · · · * /
// transfer focus and position/selection to background div
$ ( 'body' ) . on ( 'mouseup' , 'div.syntax-two' , function ( e ) {
2015-01-28 08:43:24 +09:00
// don't transfer rightclicks, instead wait for oninput and transfer after
// this makes spell checker work
if ( e . which == 3 ) {
$ ( this ) [ 0 ] . oninput = function ( ) {
$ ( this ) . siblings ( 'div.queet-box-syntax' ) . html ( $ ( this ) . html ( ) ) ;
$ ( this ) . trigger ( 'mouseup' ) ; // transfer focus
}
2014-05-28 03:40:51 +09:00
}
2013-08-19 22:30:57 +09:00
2015-01-28 08:43:24 +09:00
else {
$ ( this ) . removeClass ( 'clicked' ) ;
var caretPos = getSelectionInElement ( $ ( this ) [ 0 ] ) ;
var thisQueetBox = $ ( this ) . siblings ( 'div.queet-box-syntax' ) ;
thisQueetBox . focus ( ) ;
setSelectionRange ( thisQueetBox [ 0 ] , caretPos [ 0 ] , caretPos [ 1 ] ) ;
// fixes problem with caret not showing after delete, unfocus and refocus
if ( thisQueetBox . html ( ) == '<br>' ) {
thisQueetBox . html ( ' ' ) ;
}
}
} ) ;
2013-08-19 22:30:57 +09:00
2014-05-28 03:40:51 +09:00
// strip html from paste
function stripHtmlFromPaste ( e ) {
e . preventDefault ( ) ;
2015-01-22 04:45:58 +09:00
var text = replaceHtmlSpecialChars ( e . clipboardData . getData ( "text/plain" ) ) ;
2015-01-27 03:22:05 +09:00
text = text . replace ( /\n/g , '<br>' ) . replace ( /\t/g , ' ' ) ; // keep line-breaks and tabs
2014-05-28 03:40:51 +09:00
document . execCommand ( "insertHTML" , false , text ) ;
}
// sync divs
$ ( 'body' ) . on ( 'keyup paste input' , 'div.queet-box-syntax' , function ( ) {
var currentVal = $ ( this ) . html ( ) ;
currentVal = currentVal . replace ( /<br>$/ , '' ) . replace ( / $/ , '' ) . replace ( / $/ , '' ) ; // fix
$ ( this ) . siblings ( '.syntax-two' ) . html ( currentVal ) ;
// regexps
var regexps = Object ( ) ;
2015-01-16 09:55:17 +09:00
regexps . externalMention = /(^|\s|\.|<br>)(@)[a-zA-Z0-9]+(@)[\wåäö\-\.]+(\.)((ac|ad|aero|af|ag|ai|al|am|an|ao|aq|arpa|asia|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|biz|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cat|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|com|coop|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|edu|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|info|int|io|iq|ir|is|it|je|jm|jobs|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mil|mk|ml|mm|mn|mobi|mp|mq|mr|ms|mt|museum|mv|mw|mx|my|mz|name|nc|net|nf|ng|ni|nl|no|np|nr|nu|nz|om|org|pa|pe|pf|pg|ph|pk|pl|pm|pn|post|pro|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tel|tf|tg|th|tj|tk|tl|tm|tn|to|tp|travel|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|xxx|ye|yt|za|zm|zw|zone)|(ae|ar|as|bi|co|in|jo|mo|mu|na|ne|pr|tr))($|\s|\.|\,|\:|\-|\<|\!|\?|\&)/ ;
2014-05-28 03:40:51 +09:00
regexps . mention = /(^|\s|\.|<br>)(@)[a-zA-Z0-9]+($|\s|\.|\,|\:|\-|\<|\!|\?|\&)/ ;
regexps . tag = /(^|\s|\.|<br>)(\#)[\wåäöÅÄÖ\-]+($|\s|\.|\,|\:|\-|\<|\!|\?|\&)/ ;
regexps . group = /(^|\s|\.|<br>)(\!)[a-zA-Z0-9]+($|\s|\.|\,|\:|\-|\<|\!|\?|\&)/ ;
2015-01-16 09:55:17 +09:00
regexps . url = /(^|\s|\.|<br>)(http\:\/\/|https\:\/\/)([\wåäö\-\.]+)?(\.)((ac|ad|aero|af|ag|ai|al|am|an|ao|aq|arpa|asia|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|biz|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cat|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|com|coop|cr|cu|cv|cw|cx|cy|cz|dev|dj|dk|dm|do|dz|ec|edu|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|info|int|io|iq|ir|is|it|je|jm|jobs|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mil|mk|ml|mm|mn|mobi|mp|mq|mr|ms|mt|museum|mv|mw|mx|my|mz|name|nc|net|nf|ng|ni|nl|no|np|nr|nu|nz|om|org|pa|pe|pf|pg|ph|pk|pl|pm|pn|post|pro|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tel|tf|tg|th|tj|tk|tl|tm|tn|to|tp|travel|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|xxx|ye|yt|za|zm|zw|zone)|(ae|ar|as|bi|co|de|in|jo|mo|mu|na|ne|pr|tr))(\/[\wåäö\%\!\*\'\(\)\;\:\@\&\=\+\$\,\/\?\#\[\]\-\_\.\~]+)?(\/)?($|\s|\,|\:|\-|\<|\!|\?|\&)/ ;
regexps . urlWithoutProtocol = /(^|\s|\.|<br>)[\wåäö\-\.]+(\.)((ac|ad|aero|af|ag|ai|al|am|an|ao|aq|arpa|asia|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|biz|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cat|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|com|coop|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|edu|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|info|int|io|iq|ir|is|it|je|jm|jobs|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mil|mk|ml|mm|mn|mobi|mp|mq|mr|ms|mt|museum|mv|mw|mx|my|mz|name|nc|net|nf|ng|ni|nl|no|np|nr|nu|nz|om|org|pa|pe|pf|pg|ph|pk|pl|pm|pn|post|pro|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tel|tf|tg|th|tj|tk|tl|tm|tn|to|tp|travel|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|xxx|ye|yt|za|zm|zw|zone)|(ae|ar|as|bi|co|in|jo|mo|mu|na|ne|pr|tr))(\/[\wåäö\%\!\*\'\(\)\;\:\@\&\=\+\$\,\/\?\#\[\]\-\_\.\~]+)?(\/)?($|\s|\.|\,|\:|\-|\<|\!|\?|\&)/ ;
regexps . email = /(^|\s|\.|<br>)([a-zA-Z0-9\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~\.]+)?(@)[\wåäö\-\.]+(\.)((ac|ad|aero|af|ag|ai|al|am|an|ao|aq|arpa|asia|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|biz|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cat|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|com|coop|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|edu|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|info|int|io|iq|ir|is|it|je|jm|jobs|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mil|mk|ml|mm|mn|mobi|mp|mq|mr|ms|mt|museum|mv|mw|mx|my|mz|name|nc|net|nf|ng|ni|nl|no|np|nr|nu|nz|om|org|pa|pe|pf|pg|ph|pk|pl|pm|pn|post|pro|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tel|tf|tg|th|tj|tk|tl|tm|tn|to|tp|travel|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|xxx|ye|yt|za|zm|zw|zone)|(ae|ar|as|bi|co|in|jo|mo|mu|na|ne|pr|tr))($|\s|\.|\,|\:|\-|\<|\!|\?|\&)/ ;
2014-05-28 03:40:51 +09:00
$ . each ( regexps , function ( k , v ) {
while ( currentVal . match ( v ) ) {
var currentMatch = currentVal . match ( v ) ;
if ( currentMatch [ 0 ] . slice ( - 1 ) == '<'
|| currentMatch [ 0 ] . slice ( - 1 ) == '&'
|| currentMatch [ 0 ] . slice ( - 1 ) == '?'
|| currentMatch [ 0 ] . slice ( - 1 ) == '!'
|| currentMatch [ 0 ] . slice ( - 1 ) == ' '
|| currentMatch [ 0 ] . slice ( - 1 ) == '-'
|| currentMatch [ 0 ] . slice ( - 1 ) == ':'
|| currentMatch [ 0 ] . slice ( - 1 ) == '.'
|| currentMatch [ 0 ] . slice ( - 1 ) == ',' ) {
currentMatch [ 0 ] = currentMatch [ 0 ] . slice ( 0 , - 1 ) ;
}
currentVal = currentVal . replace ( currentMatch [ 0 ] , '<span class="' + k + '">' + currentMatch [ 0 ] . replace ( '#' , '#' ) . replace ( '@' , '@' ) . replace ( '.' , '.' ) . replace ( '!' , '!' ) + '</span>' )
}
} ) ;
$ ( this ) . siblings ( '.syntax-middle' ) . html ( currentVal ) ;
} ) ;
2013-08-19 22:30:57 +09:00
2013-11-23 08:31:04 +09:00
/ * ·
·
2014-05-28 03:40:51 +09:00
· Auto suggest mentions in queet - box
2013-11-23 08:31:04 +09:00
·
2014-05-28 03:40:51 +09:00
· · · · · · · · · · · · · * /
// navigate in mentions with mouse
$ ( 'body' ) . on ( 'mouseenter' , '.mentions-suggestions > div' , function ( ) {
$ ( '.mentions-suggestions > div' ) . removeClass ( 'selected' ) ;
$ ( this ) . addClass ( 'selected' ) ;
} ) . on ( 'mouseleave' , '.mentions-suggestions > div' , function ( ) {
$ ( this ) . removeClass ( 'selected' ) ;
} ) ;
$ ( 'body' ) . on ( 'click' , '.mentions-suggestions > div' , function ( ) {
$ ( this ) . parent ( ) . siblings ( '.queet-box-syntax' ) . focus ( ) ;
$ ( this ) . siblings ( ) . removeClass ( 'selected' ) ;
$ ( this ) . addClass ( 'selected' ) ;
useSelectedMention ( $ ( this ) . parent ( ) . siblings ( '.queet-box-syntax' ) ) ;
} ) ;
2013-11-23 08:31:04 +09:00
2014-05-28 03:40:51 +09:00
// navigate in mentions with keyboard
$ ( 'body' ) . on ( 'keydown' , '.queet-box-syntax' , function ( e ) {
if ( $ ( this ) . siblings ( '.mentions-suggestions' ) . children ( 'div' ) . length > 0 ) {
// enter or tab
if ( e . keyCode == '13' || e . keyCode == '9' ) {
e . preventDefault ( ) ;
useSelectedMention ( $ ( this ) ) ;
2013-11-23 08:31:04 +09:00
}
2014-05-28 03:40:51 +09:00
// downkey
else if ( e . keyCode == '40' ) {
e . preventDefault ( ) ;
if ( $ ( this ) . siblings ( '.mentions-suggestions' ) . children ( 'div.selected' ) . length > 0 ) {
var selected = $ ( this ) . siblings ( '.mentions-suggestions' ) . children ( 'div.selected' ) ;
selected . removeClass ( 'selected' ) ;
selected . next ( ) . addClass ( 'selected' ) ;
}
else {
$ ( this ) . siblings ( '.mentions-suggestions' ) . children ( 'div' ) . first ( ) . addClass ( 'selected' ) ;
}
2013-11-23 08:31:04 +09:00
}
2013-11-29 20:49:54 +09:00
2014-05-28 03:40:51 +09:00
// upkey
else if ( e . keyCode == '38' ) {
e . preventDefault ( ) ;
if ( $ ( this ) . siblings ( '.mentions-suggestions' ) . children ( 'div.selected' ) . length > 0 ) {
var selected = $ ( this ) . siblings ( '.mentions-suggestions' ) . children ( 'div.selected' ) ;
selected . removeClass ( 'selected' ) ;
selected . prev ( ) . addClass ( 'selected' ) ;
}
else {
$ ( this ) . siblings ( '.mentions-suggestions' ) . children ( 'div' ) . last ( ) . addClass ( 'selected' ) ;
}
}
2013-11-23 08:31:04 +09:00
}
2014-05-28 03:40:51 +09:00
} ) ;
2013-11-29 20:49:54 +09:00
2014-05-28 03:40:51 +09:00
function useSelectedMention ( queetBox ) {
// use selected
if ( queetBox . siblings ( '.mentions-suggestions' ) . children ( 'div.selected' ) . length > 0 ) {
var username = queetBox . siblings ( '.mentions-suggestions' ) . children ( 'div.selected' ) . children ( 'span' ) . html ( ) ;
}
// if none selected, take top suggestion
else {
var username = queetBox . siblings ( '.mentions-suggestions' ) . children ( 'div' ) . first ( ) . children ( 'span' ) . html ( ) ;
}
2013-11-23 08:31:04 +09:00
2014-05-28 03:40:51 +09:00
// replace the halfwritten username with the one we want
deleteBetweenCharacterIndices ( queetBox [ 0 ] , window . lastMention . mentionPos + 1 , window . lastMention . cursorPos ) ;
var range = createRangeFromCharacterIndices ( queetBox [ 0 ] , window . lastMention . mentionPos + 1 , window . lastMention . mentionPos + 1 ) ;
range . insertNode ( document . createTextNode ( username + ' ' ) ) ;
// put caret after
setSelectionRange ( queetBox [ 0 ] , window . lastMention . mentionPos + username . length + 2 , window . lastMention . mentionPos + username . length + 2 ) ;
queetBox . siblings ( '.mentions-suggestions' ) . empty ( ) ;
queetBox . trigger ( 'input' ) ; // avoid some flickering
}
2013-08-19 22:30:57 +09:00
2014-05-28 03:40:51 +09:00
// check for mentions
window . lastMention = new Object ( ) ;
$ ( 'body' ) . on ( 'keyup' , 'div.queet-box-syntax' , function ( e ) {
2013-08-19 22:30:57 +09:00
2014-05-28 03:40:51 +09:00
var queetBox = $ ( this ) ;
var cursorPosArray = getSelectionInElement ( queetBox [ 0 ] ) ;
var cursorPos = cursorPosArray [ 0 ] ;
2013-08-19 22:30:57 +09:00
2014-05-28 03:40:51 +09:00
// add space before linebreaks (to separate mentions in beginning of new lines when .text():ing later)
if ( e . keyCode == '13' ) {
e . preventDefault ( ) ;
var range = createRangeFromCharacterIndices ( queetBox [ 0 ] , cursorPos , cursorPos ) ;
range . insertNode ( document . createTextNode ( " \n" ) ) ;
}
else if ( e . keyCode != '40' && e . keyCode != '38' && e . keyCode != '13' && e . keyCode != '9' ) {
var contents = queetBox . text ( ) . substring ( 0 , cursorPos ) ;
var mentionPos = contents . lastIndexOf ( '@' ) ;
var check _contents = contents . substring ( mentionPos - 1 , cursorPos ) ;
var regex = /(^|\s|\.|\n)(@)[a-zA-Z0-9]+/ ;
var match = check _contents . match ( regex ) ;
if ( contents . indexOf ( '@' ) >= 0 && match ) {
2013-11-23 08:31:04 +09:00
2014-05-28 03:40:51 +09:00
if ( contents . lastIndexOf ( '@' ) > 1 ) {
match [ 0 ] = match [ 0 ] . substring ( 1 , match [ 0 ] . length ) ;
}
if ( ( contents . lastIndexOf ( '@' ) + match [ 0 ] . length ) == cursorPos ) {
queetBox . siblings ( '.mentions-suggestions' ) . empty ( ) ;
queetBox . siblings ( '.mentions-suggestions' ) . css ( 'top' , ( queetBox . height ( ) + 20 ) + 'px' ) ;
var term = match [ 0 ] . substring ( match [ 0 ] . lastIndexOf ( '@' ) + 1 , match [ 0 ] . length ) . toLowerCase ( ) ;
window . lastMention . mentionPos = mentionPos ;
window . lastMention . cursorPos = cursorPos ;
$ . each ( window . following , function ( ) {
var userregex = new RegExp ( term ) ;
if ( this . username . toLowerCase ( ) . match ( userregex ) || this . name . toLowerCase ( ) . match ( userregex ) ) {
queetBox . siblings ( '.mentions-suggestions' ) . append ( '<div><img height="24" width="24" src="' + this . avatar + '" /><strong>' + this . name + '</strong> @<span>' + this . username + '</span></div>' )
}
} ) ;
2013-08-19 22:30:57 +09:00
2014-05-28 03:40:51 +09:00
}
else {
queetBox . siblings ( '.mentions-suggestions' ) . empty ( ) ;
}
}
else {
queetBox . siblings ( '.mentions-suggestions' ) . empty ( ) ;
}
2013-08-19 22:30:57 +09:00
}
2014-05-28 03:40:51 +09:00
} ) ;
2013-08-19 22:30:57 +09:00
/ * ·
·
· When clicking show more links , walk upwards or downwards
·
· · · · · · · · · · · · · * /
2014-01-29 03:42:47 +09:00
$ ( 'body' ) . on ( 'click' , '.view-more-container-bottom' , function ( ) {
2014-11-26 08:58:56 +09:00
var thisParentStreamItem = $ ( this ) . parent ( '.stream-item' ) ;
2013-08-19 22:30:57 +09:00
findReplyToStatusAndShow ( $ ( this ) . parent ( '.stream-item' ) . attr ( 'data-quitter-id' ) , $ ( this ) . attr ( 'data-replies-after' ) ) ;
$ ( this ) . remove ( ) ;
2014-11-26 08:58:56 +09:00
findAndMarkLastVisibleInConversation ( thisParentStreamItem ) ;
2013-08-19 22:30:57 +09:00
} ) ;
2014-01-29 03:42:47 +09:00
$ ( 'body' ) . on ( 'click' , '.view-more-container-top' , function ( ) {
2013-08-19 22:30:57 +09:00
var this _qid = $ ( this ) . closest ( '.stream-item:not(.conversation)' ) . attr ( 'data-quitter-id' ) ;
var queet = $ ( this ) . siblings ( '.queet' ) ;
2014-11-26 08:58:56 +09:00
var thisParentStreamItem = $ ( this ) . parent ( '.stream-item' ) ;
2013-08-19 22:30:57 +09:00
rememberMyScrollPos ( queet , 'moretop' + this _qid ) ;
findInReplyToStatusAndShow ( $ ( this ) . parent ( '.stream-item' ) . attr ( 'data-quitter-id' ) , $ ( this ) . attr ( 'data-trace-from' ) , false , true ) ;
$ ( this ) . remove ( ) ;
backToMyScrollPos ( queet , 'moretop' + this _qid , false ) ;
// remove the "show full conversation" link if nothing more to show
2014-11-26 08:58:56 +09:00
if ( $ ( this ) . parent ( '.stream-item' ) . find ( '.hidden-conversation' ) . length == 0 ) {
$ ( this ) . parent ( '.stream-item' ) . children ( '.queet' ) . find ( '.show-full-conversation' ) . remove ( ) ;
2013-08-19 22:30:57 +09:00
}
2014-11-26 08:58:56 +09:00
findAndMarkLastVisibleInConversation ( thisParentStreamItem ) ;
2013-08-19 22:30:57 +09:00
} ) ;
/ * ·
·
· When clicking "show full conversation" , show all hidden queets in conversation
·
· · · · · · · · · · · · · * /
2014-01-29 03:42:47 +09:00
$ ( 'body' ) . on ( 'click' , '.show-full-conversation' , function ( ) {
2013-08-19 22:30:57 +09:00
var this _q = $ ( this ) . closest ( '.queet' ) ;
var this _qid = $ ( this ) . closest ( '.stream-item:not(.conversation)' ) . attr ( 'data-quitter-id' ) ;
2014-11-26 08:58:56 +09:00
var thisStreamItem = $ ( '#stream-item-' + $ ( this ) . attr ( 'data-stream-item-id' ) ) ;
2013-08-19 22:30:57 +09:00
rememberMyScrollPos ( this _q , this _qid ) ;
2014-11-26 08:58:56 +09:00
thisStreamItem . find ( '.view-more-container-top' ) . remove ( ) ;
thisStreamItem . find ( '.view-more-container-bottom' ) . remove ( ) ;
$ . each ( thisStreamItem . find ( '.hidden-conversation' ) , function ( key , obj ) {
2013-08-19 22:30:57 +09:00
$ ( obj ) . removeClass ( 'hidden-conversation' ) ;
$ ( obj ) . animate ( { opacity : '1' } , 400 , function ( ) {
$ ( obj ) . css ( 'background-color' , 'pink' ) . animate ( { backgroundColor : '#F6F6F6' } , 1000 ) ;
} ) ;
} ) ;
$ ( this ) . remove ( ) ;
backToMyScrollPos ( this _q , this _qid , false ) ;
2014-11-26 08:58:56 +09:00
findAndMarkLastVisibleInConversation ( thisStreamItem ) ;
2014-01-29 03:42:47 +09:00
} ) ;
2014-06-02 04:51:28 +09:00
/ * ·
·
· Edit profile
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'click' , '.edit-profile-button' , function ( ) {
if ( ! $ ( this ) . hasClass ( 'disabled' ) ) {
$ ( this ) . addClass ( 'disabled' ) ;
$ ( 'html' ) . scrollTop ( 0 ) ;
$ ( 'html' ) . addClass ( 'fixed' ) ;
$ ( 'body' ) . prepend ( '<div id="edit-profile-popup" class="modal-container"></div>' ) ;
display _spinner ( ) ;
getFromAPI ( 'users/show/' + window . loggedIn . screen _name + '.json' , function ( data ) {
remove _spinner ( ) ;
if ( data ) {
data = cleanUpUserObject ( data ) ;
// use avatar if no cover photo
2014-11-24 21:47:45 +09:00
var coverPhotoHtml = '' ;
if ( data . cover _photo !== false ) {
coverPhotoHtml = 'background-image:url(\'' + data . cover _photo + '\')' ;
2014-06-02 04:51:28 +09:00
}
$ ( '#edit-profile-popup' ) . prepend ( ' \
< div class = "edit-profile-container" > \
2014-11-24 21:47:45 +09:00
< div class = "upload-background-image" > < / d i v > \
< input type = "file" name = "background-image-input" id = "background-image-input" / > \
2014-06-02 04:51:28 +09:00
< div class = "profile-card" > \
2014-11-24 21:47:45 +09:00
< div class = "profile-header-inner" style = "' + coverPhotoHtml + '" > \
2014-06-02 04:51:28 +09:00
< input type = "file" name = "cover-photo-input" id = "cover-photo-input" / > \
2014-11-24 21:47:45 +09:00
< div class = "close-edit-profile-window" > < / d i v > \
2014-06-02 04:51:28 +09:00
< div class = "upload-cover-photo" > < / d i v > \
2014-11-24 21:47:45 +09:00
< input type = "file" name = "avatar-input" id = "avatar-input" / > \
< div class = "upload-avatar" > < / d i v > \
2014-06-02 04:51:28 +09:00
< div class = "profile-header-inner-overlay" > < / d i v > \
< a class = "profile-picture" href = "' + data.profile_image_url_original + '" > < img src = "' + data.profile_image_url_profile_size + '" / > < / a > \
< div class = "profile-card-inner" > \
2014-11-24 21:47:45 +09:00
< input class = "fullname" id = "edit-profile-fullname" placeholder = "' + window.sL.signUpFullName + '" data - start - value = "' + data.name + '" value = "' + data.name + '" / > \
2014-06-02 04:51:28 +09:00
< h2 class = "username" > < span class = "screen-name" > @ ' + data.screen_name + ' < / s p a n > < s p a n c l a s s = " f o l l o w - s t a t u s " > < / s p a n > < / h 2 > \
< div class = "bio-container" > \
2014-11-24 21:47:45 +09:00
< textarea class = "bio" id = "edit-profile-bio" data - start - value = "' + data.description + '" placeholder = "' + window.sL.registerBio + '" > ' + data.description + ' < / t e x t a r e a > \
2014-06-02 04:51:28 +09:00
< / d i v > \
< p class = "location-and-url" > \
2014-11-24 21:47:45 +09:00
< input class = "location" id = "edit-profile-location" placeholder = "' + window.sL.registerLocation + '" data - start - value = "' + data.location + '" value = "' + data.location + '" / > \
2014-06-02 04:51:28 +09:00
< span class = "divider" > · < / s p a n > \
2014-11-24 21:47:45 +09:00
< input class = "url" id = "edit-profile-url" placeholder = "' + window.sL.registerHomepage + '" data - start - value = "' + data.url + '" value = "' + data.url + '" / > \
2014-06-02 04:51:28 +09:00
< / p > \
< / d i v > \
< / d i v > \
< div class = "profile-banner-footer" > \
2014-11-24 21:47:45 +09:00
< div class = "color-selection" > \
< label for = "link-color-selection" > ' + window.sL.linkColor + ' < / l a b e l > \
< input id = "link-color-selection" type = "text" value = "#' + window.userLinkColor + '" / > \
< / d i v > \
< div class = "color-selection" > \
< label for = "link-color-selection" > ' + window.sL.backgroundColor + ' < / l a b e l > \
< input id = "background-color-selection" type = "text" value = "#' + window.userBackgroundColor + '" / > \
< / d i v > \
2014-06-02 04:51:28 +09:00
< div class = "user-actions" > \
< button type = "button" class = "abort-edit-profile-button" > < span class = "button-text edit-profile-text" > ' + window.sL.cancelVerb + ' < / s p a n > \
< button type = "button" class = "save-profile-button" > < span class = "button-text edit-profile-text" > ' + window.sL.saveChanges + ' < / s p a n > \
2014-11-24 21:47:45 +09:00
< button type = "button" class = "crop-and-save-button" > < span class = "button-text edit-profile-text" > ' + window.sL.cropAndSave + ' < / s p a n > \
2014-06-02 04:51:28 +09:00
< / d i v > \
< div class = "clearfix" > < / d i v > \
< / d i v > \
< / d i v > \
< / d i v > ' ) ;
2014-09-25 06:20:35 +09:00
$ ( '#edit-profile-popup .profile-card' ) . css ( 'top' , $ ( '#page-container .profile-card' ) . offset ( ) . top - 53 + 'px' ) ; // position exactly over
2014-11-24 21:47:45 +09:00
// save colors on change
$ ( '#link-color-selection' ) . minicolors ( {
change : function ( hex ) {
changeLinkColor ( hex ) ;
postNewLinkColor ( hex . substring ( 1 ) ) ;
}
} ) ;
$ ( '#background-color-selection' ) . minicolors ( {
change : function ( hex ) {
$ ( 'body' ) . css ( 'background-color' , hex ) ;
postNewBackgroundColor ( hex . substring ( 1 ) ) ;
}
} ) ;
// also on keyup in input (minicolors 'change' event does not do this, apparently)
$ ( '#link-color-selection' ) . on ( 'keyup' , function ( ) {
keyupSetLinkColor ( $ ( this ) . val ( ) ) ;
} ) ;
$ ( '#background-color-selection' ) . on ( 'keyup' , function ( ) {
keyupSetBGColor ( $ ( this ) . val ( ) ) ;
} ) ;
// check if profile info is change and show/hide buttons
$ ( 'input.fullname,textarea.bio,input.location,input.url' ) . on ( 'keyup paste input' , function ( ) {
showHideSaveProfileButtons ( ) ;
} ) ;
2014-06-02 04:51:28 +09:00
}
else {
abortEditProfile ( ) ;
}
} ) ;
}
} ) ;
2014-11-24 21:47:45 +09:00
// function to see if anything in profile is changed and show/hide buttons accordingly
function showHideSaveProfileButtons ( ) {
if ( $ ( 'input.fullname' ) . val ( ) != $ ( 'input.fullname' ) . attr ( 'data-start-value' )
|| $ ( 'textarea.bio' ) . val ( ) != $ ( 'textarea.bio' ) . attr ( 'data-start-value' )
|| $ ( 'input.location' ) . val ( ) != $ ( 'input.location' ) . attr ( 'data-start-value' )
|| $ ( 'input.url' ) . val ( ) != $ ( 'input.url' ) . attr ( 'data-start-value' ) ) {
$ ( '.abort-edit-profile-button, .save-profile-button' ) . show ( ) ;
}
else {
$ ( '.abort-edit-profile-button, .save-profile-button' ) . hide ( ) ;
}
}
// idle function for linkcolor selection by keyboard input
var keyupLinkColorTimer ;
function keyupSetLinkColor ( hex ) {
clearTimeout ( keyupLinkColorTimer ) ;
keyupLinkColorTimer = setTimeout ( function ( ) {
$ ( '#link-color-selection' ) . minicolors ( 'value' , hex ) ;
changeLinkColor ( $ ( '#link-color-selection' ) . val ( ) ) ;
postNewLinkColor ( $ ( '#link-color-selection' ) . val ( ) . substring ( 1 ) ) ;
} , 500 ) ;
}
// idle function for bgcolor selection by keyboard input
var keyupBGColorTimer ;
function keyupSetBGColor ( hex ) {
clearTimeout ( keyupBGColorTimer ) ;
keyupBGColorTimer = setTimeout ( function ( ) {
$ ( '#background-color-selection' ) . minicolors ( 'value' , hex ) ;
$ ( 'body' ) . css ( 'background-color' , $ ( '#background-color-selection' ) . val ( ) ) ;
postNewBackgroundColor ( $ ( '#background-color-selection' ) . val ( ) . substring ( 1 ) ) ;
} , 500 ) ;
}
2014-06-02 04:51:28 +09:00
// cancel
2014-11-24 21:47:45 +09:00
$ ( 'body' ) . on ( 'click' , '.close-edit-profile-window' , function ( ) {
abortEditProfile ( ) ;
} ) ;
2014-06-02 04:51:28 +09:00
$ ( 'body' ) . on ( 'click' , '.abort-edit-profile-button' , function ( ) {
2014-11-24 21:47:45 +09:00
// if this is the avatar or cover photo
2014-06-02 04:51:28 +09:00
if ( $ ( '#edit-profile-popup .jwc_frame' ) . length > 0 ) {
cleanUpAfterCropping ( ) ;
}
// if profile info
else {
abortEditProfile ( ) ;
}
} ) ;
function abortEditProfile ( ) {
$ ( '#edit-profile-popup' ) . remove ( ) ;
$ ( '.edit-profile-button' ) . removeClass ( 'disabled' ) ;
$ ( 'html' ) . removeClass ( 'fixed' ) ;
}
// validate
$ ( 'body' ) . on ( 'keyup paste input' , '#edit-profile-popup input,#edit-profile-popup textarea' , function ( ) {
if ( validateEditProfileForm ( $ ( '#edit-profile-popup' ) ) ) {
$ ( '.save-profile-button' ) . removeAttr ( 'disabled' ) ;
$ ( '.save-profile-button' ) . removeClass ( 'disabled' ) ;
}
else {
$ ( '.save-profile-button' ) . attr ( 'disabled' , 'disabled' ) ;
$ ( '.save-profile-button' ) . addClass ( 'disabled' ) ;
}
} ) ;
2014-11-24 21:47:45 +09:00
// submit cover photo or avatar
$ ( 'body' ) . on ( 'click' , '.crop-and-save-button' , function ( ) {
if ( $ ( '.crop-and-save-button' ) . attr ( 'disabled' ) != 'disabled' ) {
$ ( '.crop-and-save-button' ) . attr ( 'disabled' , 'disabled' ) ;
$ ( '.crop-and-save-button' ) . addClass ( 'disabled' ) ;
display _spinner ( ) ;
// if this is the cover photo
if ( $ ( '#edit-profile-popup .jwc_frame.cover-photo-to-crop' ) . length > 0 ) {
$ . ajax ( { url : window . apiRoot + 'qvitter/update_cover_photo.json' ,
type : "POST" ,
data : {
cropH : window . jwc . result . cropH ,
cropW : window . jwc . result . cropW ,
cropX : window . jwc . result . cropX ,
cropY : window . jwc . result . cropY ,
img : $ ( '#cover-photo-to-crop' ) . attr ( 'src' )
} ,
dataType : "json" ,
error : function ( data ) { console . log ( 'error' ) ; console . log ( data ) ; } ,
success : function ( data ) {
remove _spinner ( ) ;
if ( typeof data . error == 'undefined' ) {
$ ( '.crop-and-save-button' ) . removeAttr ( 'disabled' ) ;
$ ( '.crop-and-save-button' ) . removeClass ( 'disabled' ) ;
cleanUpAfterCropping ( ) ;
$ ( '.profile-header-inner' ) . css ( 'background-image' , 'url(' + data . url + ')' ) ;
$ ( '#user-header' ) . css ( 'background-image' , 'url(' + data . url + ')' ) ;
}
else {
alert ( 'Try again! ' + data . error ) ;
$ ( '.crop-and-save-button' ) . removeAttr ( 'disabled' ) ;
$ ( '.crop-and-save-button' ) . removeClass ( 'disabled' ) ;
}
}
} ) ;
}
// if this is the avatar
else if ( $ ( '#edit-profile-popup .jwc_frame.avatar-to-crop' ) . length > 0 ) {
$ . ajax ( { url : window . apiRoot + 'qvitter/update_avatar.json' ,
type : "POST" ,
data : {
cropH : window . jwc . result . cropH ,
cropW : window . jwc . result . cropW ,
cropX : window . jwc . result . cropX ,
cropY : window . jwc . result . cropY ,
img : $ ( '#avatar-to-crop' ) . attr ( 'src' )
} ,
dataType : "json" ,
error : function ( data ) { console . log ( 'error' ) ; console . log ( data ) ; } ,
success : function ( data ) {
remove _spinner ( ) ;
if ( typeof data . error == 'undefined' ) {
$ ( '.crop-and-save-button' ) . removeAttr ( 'disabled' ) ;
$ ( '.crop-and-save-button' ) . removeClass ( 'disabled' ) ;
cleanUpAfterCropping ( ) ;
$ ( '.profile-picture' ) . attr ( 'href' , data . profile _image _url _original ) ;
$ ( '.profile-picture img, #user-avatar' ) . attr ( 'src' , data . profile _image _url _profile _size ) ;
$ ( '#settingslink .nav-session' ) . css ( 'background-image' , 'url(\'' + data . profile _image _url _profile _size + '\')' ) ;
$ ( '.account-group .name[data-user-id="' + window . myUserID + '"]' ) . siblings ( '.avatar' ) . attr ( 'src' , data . profile _image _url _profile _size ) ;
}
else {
alert ( 'Try again! ' + data . error ) ;
$ ( '.crop-and-save-button' ) . removeAttr ( 'disabled' ) ;
$ ( '.crop-and-save-button' ) . removeClass ( 'disabled' ) ;
}
}
} ) ;
}
// if this is the background-image
else if ( $ ( '#edit-profile-popup .jwc_frame.background-to-crop' ) . length > 0 ) {
$ . ajax ( { url : window . apiRoot + 'qvitter/update_background_image.json' ,
type : "POST" ,
data : {
cropH : window . jwc . result . cropH ,
cropW : window . jwc . result . cropW ,
cropX : window . jwc . result . cropX ,
cropY : window . jwc . result . cropY ,
img : $ ( '#background-to-crop' ) . attr ( 'src' )
} ,
dataType : "json" ,
error : function ( data ) { console . log ( 'error' ) ; console . log ( data ) ; } ,
success : function ( data ) {
remove _spinner ( ) ;
if ( typeof data . error == 'undefined' ) {
$ ( '.crop-and-save-button' ) . removeAttr ( 'disabled' ) ;
$ ( '.crop-and-save-button' ) . removeClass ( 'disabled' ) ;
cleanUpAfterCropping ( ) ;
$ ( 'body' ) . css ( 'background-image' , 'url(\'' + data . url + '\')' ) ;
window . userBackgroundImage = data . url ;
}
else {
alert ( 'Try again! ' + data . error ) ;
$ ( '.crop-and-save-button' ) . removeAttr ( 'disabled' ) ;
$ ( '.crop-and-save-button' ) . removeClass ( 'disabled' ) ;
}
}
} ) ;
}
2014-06-02 04:51:28 +09:00
}
2014-11-24 21:47:45 +09:00
} ) ;
// submit new profile info
$ ( 'body' ) . on ( 'click' , '.save-profile-button' , function ( ) {
if ( $ ( '.save-profile-button' ) . attr ( 'disabled' ) != 'disabled' ) {
$ ( '.save-profile-button' ) . attr ( 'disabled' , 'disabled' ) ;
$ ( '.save-profile-button' ) . addClass ( 'disabled' ) ;
display _spinner ( ) ;
2014-06-02 04:51:28 +09:00
if ( validateEditProfileForm ( $ ( '#edit-profile-popup' ) ) ) {
$ . ajax ( { url : window . apiRoot + 'account/update_profile.json' ,
type : "POST" ,
data : {
name : $ ( '#edit-profile-popup input.fullname' ) . val ( ) ,
url : $ ( '#edit-profile-popup input.url' ) . val ( ) ,
location : $ ( '#edit-profile-popup input.location' ) . val ( ) ,
description : $ ( '#edit-profile-popup textarea.bio' ) . val ( ) ,
} ,
dataType : "json" ,
error : function ( data ) { console . log ( 'error' ) ; console . log ( data ) ; } ,
success : function ( data ) {
remove _spinner ( ) ;
if ( typeof data . error == 'undefined' ) {
location . reload ( ) ; // reload, hopefully the new profile is saved
}
else {
alert ( 'Try again! ' + data . error ) ;
$ ( '.save-profile-button' ) . removeAttr ( 'disabled' ) ;
$ ( '.save-profile-button' ) . removeClass ( 'disabled' ) ;
}
}
} ) ;
}
}
} ) ;
2014-11-24 21:47:45 +09:00
// cover photo, avatar and background image select and crop
$ ( 'body' ) . on ( 'click' , '.upload-cover-photo, .upload-avatar, .upload-background-image' , function ( ) {
var coverOrAvatar = $ ( this ) . attr ( 'class' ) ;
if ( coverOrAvatar == 'upload-cover-photo' ) {
var inputId = 'cover-photo-input'
}
else if ( coverOrAvatar == 'upload-avatar' ) {
var inputId = 'avatar-input'
}
else if ( coverOrAvatar == 'upload-background-image' ) {
var inputId = 'background-image-input'
}
$ ( '#' + inputId ) . click ( function ( ) { $ ( this ) . one ( 'change' , function ( e ) { // trick to make the change event only fire once when selecting a file
coverPhotoAndAvatarSelectAndCrop ( e , coverOrAvatar ) ;
2014-06-02 04:51:28 +09:00
} ) } ) ;
// trigger click for firefox
if ( navigator . userAgent . toLowerCase ( ) . indexOf ( 'firefox' ) > - 1 ) {
2014-11-24 21:47:45 +09:00
$ ( '#' + inputId ) . trigger ( 'click' ) ;
2014-06-02 04:51:28 +09:00
}
// other browsers
else {
var evt = document . createEvent ( "HTMLEvents" ) ;
evt . initEvent ( "click" , true , true ) ;
2014-11-24 21:47:45 +09:00
$ ( '#' + inputId ) [ 0 ] . dispatchEvent ( evt ) ;
}
2014-06-02 04:51:28 +09:00
} ) ;
// load image from file input
2014-11-24 21:47:45 +09:00
function coverPhotoAndAvatarSelectAndCrop ( e , coverOrAvatar ) {
if ( coverOrAvatar == 'upload-cover-photo' ) {
var targetWidth = 588 ;
var targetHeight = 260 ;
var maxWidth = 1040 ;
var minWidth = 1040 ;
var cropId = 'cover-photo-to-crop' ;
}
else if ( coverOrAvatar == 'upload-avatar' ) {
var targetWidth = 220 ;
var targetHeight = 220 ;
var maxWidth = 1040 ;
var minWidth = 1040 ;
var cropId = 'avatar-to-crop' ;
}
else if ( coverOrAvatar == 'upload-background-image' ) {
var targetWidth = $ ( window ) . width ( ) ;
var targetHeight = $ ( window ) . height ( ) - 46 ;
var maxWidth = 3000 ;
var minWidth = 3000 ;
var cropId = 'background-to-crop' ;
}
2014-06-02 04:51:28 +09:00
// get orientation
loadImage . parseMetaData ( e . target . files [ 0 ] , function ( data ) {
if ( data . exif ) {
var orientation = data . exif . get ( 'Orientation' ) ;
}
else {
var orientation = 1 ;
}
display _spinner ( ) ;
// clean up
cleanUpAfterCropping ( ) ;
// create image
loadImage ( e . target . files [ 0 ] ,
function ( img ) {
if ( typeof img . target == 'undefined' ) {
2014-11-24 21:47:45 +09:00
var appendedImg = $ ( '#edit-profile-popup .profile-card' ) . prepend ( '<img id="' + cropId + '" src="' + img . toDataURL ( 'image/jpeg' ) + '" />' ) ;
2014-06-02 04:51:28 +09:00
// enable cropping
2014-11-24 21:47:45 +09:00
$ ( '#' + cropId ) . jWindowCrop ( {
targetWidth : targetWidth ,
targetHeight : targetHeight ,
2014-06-02 04:51:28 +09:00
onChange : function ( result ) {
remove _spinner ( ) ;
}
} ) ;
2014-11-24 21:47:45 +09:00
// align centered, fade out background
$ ( '#' + cropId ) . parent ( ) . addClass ( cropId ) ;
$ ( '#' + cropId ) . parent ( ) . css ( 'position' , 'absolute' )
$ ( '#' + cropId ) . parent ( ) . css ( 'left' , '50%' )
$ ( '#' + cropId ) . parent ( ) . css ( 'margin-left' , '-' + ( targetWidth / 2 ) + 'px' )
$ ( '#' + cropId ) . parent ( ) . siblings ( '.profile-header-inner' ) . children ( 'div,input,a' ) . css ( 'display' , 'none' ) ;
window . jwc = $ ( '#' + cropId ) . getjWindowCrop ( ) ;
$ ( '.save-profile-button' ) . hide ( ) ;
$ ( '.abort-edit-profile-button, .crop-and-save-button' ) . show ( ) ;
2014-06-02 04:51:28 +09:00
}
else {
2014-11-24 21:47:45 +09:00
remove _spinner ( ) ;
$ ( '.queet-box-loading-cover' ) . remove ( ) ;
2014-06-02 04:51:28 +09:00
alert ( 'could not read image' ) ;
}
} ,
2014-11-24 21:47:45 +09:00
{ maxWidth : maxWidth ,
minWidth : minWidth ,
2014-09-20 09:53:10 +09:00
canvas : true ,
2014-06-02 04:51:28 +09:00
orientation : orientation } // Options
) ;
} ) ;
}
function cleanUpAfterCropping ( ) {
2014-11-24 21:47:45 +09:00
$ ( '.jwc_frame' ) . siblings ( '.profile-header-inner' ) . children ( 'div,input,a' ) . css ( 'display' , 'block' ) ;
2014-06-02 04:51:28 +09:00
if ( typeof window . jwc != 'undefined' ) {
window . jwc . destroy ( ) ;
}
$ ( '.jwc_frame' ) . remove ( ) ;
$ ( '#cover-photo-to-crop' ) . remove ( ) ;
2014-11-24 21:47:45 +09:00
$ ( '#avatar-to-crop' ) . remove ( ) ;
$ ( '#background-to-crop' ) . remove ( ) ;
$ ( 'input:file' ) . unbind ( 'click' ) ;
$ ( '.crop-and-save-button' ) . removeClass ( 'disabled' ) ;
$ ( '.crop-and-save-button' ) . removeAttr ( 'disabled' ) ;
$ ( '.crop-and-save-button, .abort-edit-profile-button' ) . hide ( ) ;
showHideSaveProfileButtons ( ) ;
}
/ * ·
·
· Upload image
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'mousedown' , '.upload-image' , function ( ) {
// remember caret position
var caretPos = getSelectionInElement ( $ ( this ) . closest ( '.queet-toolbar' ) . siblings ( '.queet-box-syntax' ) [ 0 ] ) ;
$ ( this ) . attr ( 'data-caret-pos' , caretPos ) ;
// prevent queet-box collapse
$ ( this ) . addClass ( 'clicked' ) ;
} ) ;
$ ( 'body' ) . on ( 'click' , '.upload-image' , function ( ) {
var thisUploadButton = $ ( this ) ;
$ ( '#upload-image-input' ) . one ( 'click' , function ( ) { // trick to make the change event only fire once when selecting a file
$ ( this ) . one ( 'change' , function ( e ) {
uploadImage ( e , thisUploadButton ) ;
} )
} ) ;
// trigger click for firefox
if ( navigator . userAgent . toLowerCase ( ) . indexOf ( 'firefox' ) > - 1 ) {
$ ( '#upload-image-input' ) . trigger ( 'click' ) ;
}
// other browsers
else {
var evt = document . createEvent ( "HTMLEvents" ) ;
evt . initEvent ( "click" , true , true ) ;
$ ( '#upload-image-input' ) [ 0 ] . dispatchEvent ( evt ) ;
}
} ) ;
function uploadImage ( e , thisUploadButton ) {
// get orientation
loadImage . parseMetaData ( e . target . files [ 0 ] , function ( data ) {
if ( data . exif ) {
var orientation = data . exif . get ( 'Orientation' ) ;
}
else {
var orientation = 1 ;
}
// loader cover stuff
thisUploadButton . closest ( '.queet-toolbar' ) . parent ( ) . append ( '<div class="queet-box-loading-cover"></div>' ) ;
thisUploadButton . closest ( '.queet-toolbar' ) . siblings ( '.queet-box-loading-cover' ) . width ( thisUploadButton . closest ( '.queet-toolbar' ) . parent ( ) . outerWidth ( ) ) ;
display _spinner ( thisUploadButton . closest ( '.queet-toolbar' ) . siblings ( '.queet-box-loading-cover' ) [ 0 ] ) ;
thisUploadButton . closest ( '.queet-toolbar' ) . siblings ( '.queet-box-loading-cover' ) . find ( '.loader' ) . css ( 'top' , ( thisUploadButton . closest ( '.queet-toolbar' ) . parent ( ) . outerHeight ( ) / 2 - 20 ) + 'px' ) ;
// clean up
cleanUpAfterCropping ( ) ;
2015-01-24 00:28:41 +09:00
2014-11-24 21:47:45 +09:00
// create image
loadImage ( e . target . files [ 0 ] ,
function ( img ) {
if ( typeof img . target == 'undefined' ) {
2015-01-24 00:28:41 +09:00
// The preview image below queet box.
2014-11-24 21:47:45 +09:00
var appendedImg = thisUploadButton . closest ( '.queet-toolbar' ) . before ( '<span class="upload-image-container"><img class="to-upload" src="' + img . toDataURL ( 'image/jpeg' ) + '" /></span>' ) ;
2015-01-24 00:28:41 +09:00
var imgFormData = new FormData ( ) ;
imgFormData . append ( 'media' , $ ( '#upload-image-input' ) [ 0 ] . files [ 0 ] ) ;
2014-11-24 21:47:45 +09:00
// upload
2015-01-24 00:28:41 +09:00
$ . ajax ( { url : window . apiRoot + 'statusnet/media/upload' ,
2014-11-24 21:47:45 +09:00
type : "POST" ,
2015-01-24 00:28:41 +09:00
data : imgFormData ,
contentType : false ,
processData : false ,
dataType : "xml" ,
2014-11-24 21:47:45 +09:00
error : function ( data ) { console . log ( 'error' ) ; console . log ( data ) ; $ ( '.queet-box-loading-cover' ) . remove ( ) ; } ,
success : function ( data ) {
2015-01-24 00:28:41 +09:00
var rsp = $ ( data ) . find ( 'rsp' ) ;
if ( rsp . attr ( 'stat' ) == 'ok' ) {
2014-11-24 21:47:45 +09:00
cleanUpAfterCropping ( ) ;
2015-01-24 00:28:41 +09:00
// If doing 'multiple' input element, maybe reply with many mediaurl elements
// and then rsp.find('mediaurl').each(...)?
var mediaurl = rsp . find ( 'mediaurl' ) . text ( ) ;
2014-11-24 21:47:45 +09:00
var uploadButton = $ ( 'img.to-upload' ) . parent ( ) . siblings ( '.queet-toolbar' ) . find ( '.upload-image' ) ;
var queetBox = $ ( 'img.to-upload' ) . parent ( ) . siblings ( '.queet-box-syntax' ) ;
var caretPos = uploadButton . attr ( 'data-caret-pos' ) . split ( ',' ) ;
2014-11-28 07:29:58 +09:00
// if this site is like quitter.se, we have to do this, otherwise
// gnusocial will not recognize the link to the image as a local attachment
if ( window . thisSiteThinksItIsHttpButIsActuallyHttps ) {
2015-01-24 00:28:41 +09:00
mediaurl = mediaurl . replace ( 'https://' , 'http://' ) ;
2014-11-28 07:29:58 +09:00
}
2014-11-26 08:58:56 +09:00
2015-01-24 00:28:41 +09:00
$ ( 'img.to-upload' ) . attr ( 'data-shorturl' , mediaurl ) ;
2014-11-24 21:47:45 +09:00
$ ( 'img.to-upload' ) . addClass ( 'uploaded' ) ;
$ ( 'img.to-upload' ) . removeClass ( 'to-upload' ) ;
// insert shorturl in queet box
deleteBetweenCharacterIndices ( queetBox [ 0 ] , caretPos [ 0 ] , caretPos [ 1 ] ) ;
var range = createRangeFromCharacterIndices ( queetBox [ 0 ] , caretPos [ 0 ] , caretPos [ 0 ] ) ;
2015-01-22 03:15:22 +09:00
if ( typeof range == 'undefined' ) {
// if queetbox is empty no range is returned, and inserting will fail,
// so we insert a space and try to get range again...
2015-01-24 00:28:41 +09:00
queetBox . html ( ' ' ) ;
2015-01-22 03:15:22 +09:00
range = createRangeFromCharacterIndices ( queetBox [ 0 ] , caretPos [ 0 ] , caretPos [ 0 ] ) ;
}
2015-01-24 00:28:41 +09:00
range . insertNode ( document . createTextNode ( ' ' + mediaurl + ' ' ) ) ;
2014-11-24 21:47:45 +09:00
// put caret after
queetBox . focus ( ) ;
2015-01-24 00:28:41 +09:00
var putCaretAt = parseInt ( caretPos [ 0 ] , 10 ) + mediaurl . length + 2 ;
2014-11-24 21:47:45 +09:00
setSelectionRange ( queetBox [ 0 ] , putCaretAt , putCaretAt ) ;
queetBox . trigger ( 'input' ) ; // avoid some flickering
setTimeout ( function ( ) { queetBox . trigger ( 'input' ) ; } , 1 ) ; // make sure chars are counted and shorten-button activated
$ ( '.queet-box-loading-cover' ) . remove ( ) ;
}
else {
2015-01-24 00:28:41 +09:00
alert ( 'Try again! ' + rsp . find ( 'err' ) . attr ( 'msg' ) ) ;
2014-11-24 21:47:45 +09:00
$ ( '.save-profile-button' ) . removeAttr ( 'disabled' ) ;
$ ( '.save-profile-button' ) . removeClass ( 'disabled' ) ;
$ ( 'img.to-upload' ) . parent ( ) . remove ( ) ;
$ ( '.queet-box-loading-cover' ) . remove ( ) ;
}
}
} ) ;
}
else {
remove _spinner ( ) ;
$ ( '.queet-box-loading-cover' ) . remove ( ) ;
alert ( 'could not read image' ) ;
}
} ,
{ canvas : true ,
orientation : orientation } // Options
) ;
} ) ;
}
/ * ·
·
· Small edit profile button on mini - card . Go - to user stream and hit edit button
·
· · · · · · · · · · · · · * /
$ ( 'body' ) . on ( 'click' , '#mini-edit-profile-button, #edit-profile-header-link' , function ( ) {
if ( window . currentStream == 'statuses/user_timeline.json?screen_name=' + window . loggedIn . screen _name ) {
$ ( '.edit-profile-button' ) . trigger ( 'click' ) ;
}
else {
setNewCurrentStream ( 'statuses/user_timeline.json?screen_name=' + window . loggedIn . screen _name , function ( ) {
$ ( '.edit-profile-button' ) . trigger ( 'click' ) ;
} , true ) ;
}
2014-11-29 12:29:18 +09:00
} ) ;