2009-11-04 18:24:14 +09:00
/ *
* StatusNet - a distributed open - source microblogging tool
* Copyright ( C ) 2008 , StatusNet , Inc .
*
* Add a notice encoded as JSON into the current timeline
*
* This program 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 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY 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 this program . If not , see < http : //www.gnu.org/licenses/>.
*
* @ category Plugin
* @ package StatusNet
* @ author Evan Prodromou < evan @ status . net >
* @ author Sarven Capadisli < csarven @ status . net >
* @ copyright 2009 StatusNet , Inc .
* @ license http : //www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @ link http : //status.net/
* /
2010-12-01 09:35:47 +09:00
/ * *
* This is the UI portion of the Realtime plugin base class , handling
* queueing up and displaying of notices that have been received through
* other code in one of the subclassed plugin implementations such as
* Meteor or Orbited .
*
* Notices are passed in as JSON objects formatted per the Twitter - compatible
* API .
*
* @ todo Currently we duplicate a lot of formatting and layout code from
* the PHP side of StatusNet , which makes it very difficult to maintain
* this package . Internationalization as well as newer features such
* as location data , customized source links for OStatus profiles ,
* and image thumbnails are not yet supported in Realtime yet because
* they have not been implemented here .
* /
2009-09-24 06:07:20 +09:00
RealtimeUpdate = {
_userid : 0 ,
_replyurl : '' ,
_favorurl : '' ,
2009-12-16 04:44:20 +09:00
_repeaturl : '' ,
2009-09-24 06:07:20 +09:00
_deleteurl : '' ,
2009-11-04 18:12:34 +09:00
_updatecounter : 0 ,
2009-11-18 19:54:57 +09:00
_maxnotices : 50 ,
2009-11-18 21:46:36 +09:00
_windowhasfocus : true ,
2009-11-18 22:34:06 +09:00
_documenttitle : '' ,
2009-11-19 00:41:07 +09:00
_paused : false ,
_queuedNotices : [ ] ,
2009-09-24 06:07:20 +09:00
2010-12-01 09:35:47 +09:00
/ * *
* Initialize the Realtime plugin UI on a page with a timeline view .
*
* This function is called from a JS fragment inserted by the PHP side
* of the Realtime plugin , and provides us with base information
* needed to build a near - replica of StatusNet ' s NoticeListItem output .
*
* Once the UI is initialized , a plugin subclass will need to actually
* feed data into the RealtimeUpdate object !
*
* @ param { int } userid : local profile ID of the currently logged - in user
* @ param { String } replyurl : URL for newnotice action , used when generating reply buttons
* @ param { String } favorurl : URL for favor action , used when generating fave buttons
* @ param { String } repeaturl : URL for repeat action , used when generating repeat buttons
* @ param { String } deleteurl : URL template for deletenotice action , used when generating delete buttons .
* This URL contains a stub value of 0000000000 which will be replaced with the notice ID .
*
* @ access public
* /
2009-12-16 04:44:20 +09:00
init : function ( userid , replyurl , favorurl , repeaturl , deleteurl )
2009-09-24 06:07:20 +09:00
{
RealtimeUpdate . _userid = userid ;
RealtimeUpdate . _replyurl = replyurl ;
RealtimeUpdate . _favorurl = favorurl ;
2009-12-16 04:44:20 +09:00
RealtimeUpdate . _repeaturl = repeaturl ;
2009-09-24 06:07:20 +09:00
RealtimeUpdate . _deleteurl = deleteurl ;
2009-09-27 23:06:39 +09:00
2009-11-18 22:34:06 +09:00
RealtimeUpdate . _documenttitle = document . title ;
2009-11-04 18:12:34 +09:00
2010-12-01 10:09:14 +09:00
$ ( window ) . bind ( 'focus' , function ( ) {
RealtimeUpdate . _windowhasfocus = true ;
// Clear the counter on the window title when we focus in.
RealtimeUpdate . _updatecounter = 0 ;
RealtimeUpdate . removeWindowCounter ( ) ;
} ) ;
2009-11-18 19:53:48 +09:00
2009-11-18 21:46:36 +09:00
$ ( window ) . bind ( 'blur' , function ( ) {
2009-11-11 21:21:27 +09:00
$ ( '#notices_primary .notice' ) . removeClass ( 'mark-top' ) ;
2009-09-27 23:06:39 +09:00
2009-11-11 21:21:27 +09:00
$ ( '#notices_primary .notice:first' ) . addClass ( 'mark-top' ) ;
2009-11-04 18:12:34 +09:00
2010-12-01 10:09:14 +09:00
// While we're in the background, received messages will increment
// a counter that we put on the window title. This will cause some
// browsers to also flash or mark the tab or window title bar until
// you seek attention (eg Firefox 4 pinned app tabs).
2009-11-18 19:53:48 +09:00
RealtimeUpdate . _windowhasfocus = false ;
2009-11-04 18:12:34 +09:00
return false ;
2009-09-27 23:06:39 +09:00
} ) ;
2009-09-24 06:07:20 +09:00
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Accept a notice in a Twitter - API JSON style and either show it
* or queue it up , depending on whether the realtime display is
* active .
*
* The meat of a Realtime plugin subclass is to provide a substrate
* transport to receive data and shove it into this function . : )
*
* Note that the JSON data is extended from the standard API return
* with additional fields added by RealtimePlugin ' s PHP code .
*
* @ param { Object } data : extended JSON API - formatted notice
*
* @ access public
* /
2009-09-24 06:07:20 +09:00
receive : function ( data )
{
2010-12-01 09:46:11 +09:00
if ( RealtimeUpdate . isNoticeVisible ( data . id ) ) {
// Probably posted by the user in this window, and so already
// shown by the AJAX form handler. Ignore it.
return ;
}
2009-11-19 00:41:07 +09:00
if ( RealtimeUpdate . _paused === false ) {
RealtimeUpdate . purgeLastNoticeItem ( ) ;
2009-11-18 19:54:57 +09:00
2009-11-19 00:41:07 +09:00
RealtimeUpdate . insertNoticeItem ( data ) ;
}
else {
RealtimeUpdate . _queuedNotices . push ( data ) ;
2009-11-19 02:23:04 +09:00
RealtimeUpdate . updateQueuedCounter ( ) ;
2009-11-19 00:41:07 +09:00
}
2009-11-19 02:23:04 +09:00
RealtimeUpdate . updateWindowCounter ( ) ;
2009-11-18 22:34:06 +09:00
} ,
2009-11-18 19:54:57 +09:00
2010-12-01 09:35:47 +09:00
/ * *
* Add a visible representation of the given notice at the top of
* the current timeline .
*
* If the notice is already in the timeline , nothing will be added .
*
* @ param { Object } data : extended JSON API - formatted notice
*
* @ fixme while core UI JS code is used to activate the AJAX UI controls ,
* the actual production of HTML ( in makeNoticeItem and its subs )
* duplicates core code without plugin hook points or i18n support .
*
* @ access private
* /
2009-11-18 22:34:06 +09:00
insertNoticeItem : function ( data ) {
2009-11-19 04:15:55 +09:00
// Don't add it if it already exists
2010-12-01 09:46:11 +09:00
if ( RealtimeUpdate . isNoticeVisible ( data . id ) ) {
2009-11-19 04:15:55 +09:00
return ;
}
2009-11-18 22:34:06 +09:00
var noticeItem = RealtimeUpdate . makeNoticeItem ( data ) ;
2009-11-28 23:29:25 +09:00
var noticeItemID = $ ( noticeItem ) . attr ( 'id' ) ;
2011-03-02 08:45:44 +09:00
var list = $ ( "#notices_primary .notices:first" )
var prepend = true ;
2011-03-02 09:08:37 +09:00
var threaded = list . hasClass ( 'threaded-notices' ) ;
2011-03-02 08:45:44 +09:00
if ( threaded && data . in _reply _to _status _id ) {
// aho!
var parent = $ ( '#notice-' + data . in _reply _to _status _id ) ;
2011-03-02 09:04:11 +09:00
if ( parent . length == 0 ) {
// @todo fetch the original, insert it, and finish the rest
} else {
// Check the parent notice to make sure it's not a reply itself.
// If so, use it's parent as the parent.
var parentList = parent . closest ( '.notices' ) ;
2011-03-02 09:08:37 +09:00
if ( parentList . hasClass ( 'threaded-replies' ) ) {
2011-03-02 09:04:11 +09:00
parent = parentList . closest ( '.notice' ) ;
}
2011-03-02 09:08:37 +09:00
list = parent . find ( '.threaded-replies' ) ;
2011-03-02 08:45:44 +09:00
if ( list . length == 0 ) {
2011-03-02 09:08:37 +09:00
list = $ ( '<ul class="notices threaded-replies xoxo"></ul>' ) ;
2011-03-02 08:45:44 +09:00
parent . append ( list ) ;
}
prepend = false ;
}
}
var newNotice = $ ( noticeItem ) ;
if ( prepend ) {
list . prepend ( newNotice ) ;
} else {
var placeholder = list . find ( 'li.notice-reply-placeholder' )
2011-03-02 09:04:11 +09:00
if ( placeholder . length > 0 ) {
2011-03-02 08:45:44 +09:00
newNotice . insertBefore ( placeholder )
} else {
newNotice . appendTo ( list ) ;
2011-03-02 09:04:11 +09:00
SN . U . NoticeInlineReplyPlaceholder ( parent ) ;
2011-03-02 08:45:44 +09:00
}
}
newNotice . css ( { display : "none" } ) . fadeIn ( 1000 ) ;
2009-11-18 22:34:06 +09:00
2009-11-29 00:46:24 +09:00
SN . U . NoticeReplyTo ( $ ( '#' + noticeItemID ) ) ;
2009-11-30 04:27:33 +09:00
SN . U . NoticeWithAttachment ( $ ( '#' + noticeItemID ) ) ;
2009-11-18 22:34:06 +09:00
} ,
2010-12-01 09:46:11 +09:00
/ * *
* Check if the given notice is visible in the timeline currently .
* Used to avoid duplicate processing of notices that have been
* displayed by other means .
*
* @ param { number } id : notice ID to check
*
* @ return boolean
*
* @ access private
* /
isNoticeVisible : function ( id ) {
return ( $ ( "#notice-" + id ) . length > 0 ) ;
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Trims a notice off the end of the timeline if we have more than the
* maximum number of notices visible .
*
* @ access private
* /
2009-11-18 22:34:06 +09:00
purgeLastNoticeItem : function ( ) {
if ( $ ( '#notices_primary .notice' ) . length > RealtimeUpdate . _maxnotices ) {
$ ( "#notices_primary .notice:last" ) . remove ( ) ;
}
} ,
2009-11-04 18:12:34 +09:00
2010-12-01 09:35:47 +09:00
/ * *
* If the window / tab is in background , increment the counter of newly
* received notices and append it onto the window title .
*
* Has no effect if the window is in foreground .
*
* @ access private
* /
2009-11-18 22:34:06 +09:00
updateWindowCounter : function ( ) {
2009-11-18 19:53:48 +09:00
if ( RealtimeUpdate . _windowhasfocus === false ) {
RealtimeUpdate . _updatecounter += 1 ;
2009-11-18 22:34:06 +09:00
document . title = '(' + RealtimeUpdate . _updatecounter + ') ' + RealtimeUpdate . _documenttitle ;
2009-11-18 19:53:48 +09:00
}
2009-09-24 06:07:20 +09:00
} ,
2010-12-01 10:09:14 +09:00
/ * *
* Clear the background update counter from the window title .
*
* @ access private
*
* @ fixme could interfere with anything else trying similar tricks
* /
removeWindowCounter : function ( ) {
document . title = RealtimeUpdate . _documenttitle ;
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Builds a notice HTML block from JSON API - style data .
*
* @ param { Object } data : extended JSON API - formatted notice
* @ return { String } HTML fragment
*
* @ fixme this replicates core StatusNet code , making maintenance harder
* @ fixme sloppy HTML building ( raw concat without escaping )
* @ fixme no i18n support
* @ fixme local variables pollute global namespace
*
* @ access private
* /
2009-09-24 06:07:20 +09:00
makeNoticeItem : function ( data )
{
2009-12-16 05:47:37 +09:00
if ( data . hasOwnProperty ( 'retweeted_status' ) ) {
original = data [ 'retweeted_status' ] ;
repeat = data ;
data = original ;
unique = repeat [ 'id' ] ;
responsible = repeat [ 'user' ] ;
} else {
original = null ;
repeat = null ;
unique = data [ 'id' ] ;
responsible = data [ 'user' ] ;
}
2009-09-24 06:07:20 +09:00
user = data [ 'user' ] ;
2009-12-22 08:19:34 +09:00
html = data [ 'html' ] . replace ( /</g , '<' ) . replace ( />/g , '>' ) . replace ( /"/g , '"' ) . replace ( /&/g , '&' ) ;
source = data [ 'source' ] . replace ( /</g , '<' ) . replace ( />/g , '>' ) . replace ( /"/g , '"' ) . replace ( /&/g , '&' ) ;
2010-03-29 06:41:31 +09:00
2009-12-16 05:47:37 +09:00
ni = "<li class=\"hentry notice\" id=\"notice-" + unique + "\">" +
2009-09-24 06:07:20 +09:00
"<div class=\"entry-title\">" +
"<span class=\"vcard author\">" +
2010-01-30 00:43:37 +09:00
"<a href=\"" + user [ 'profile_url' ] + "\" class=\"url\" title=\"" + user [ 'name' ] + "\">" +
2009-09-24 06:07:20 +09:00
"<img src=\"" + user [ 'profile_image_url' ] + "\" class=\"avatar photo\" width=\"48\" height=\"48\" alt=\"" + user [ 'screen_name' ] + "\"/>" +
"<span class=\"nickname fn\">" + user [ 'screen_name' ] + "</span>" +
"</a>" +
"</span>" +
"<p class=\"entry-content\">" + html + "</p>" +
"</div>" +
"<div class=\"entry-content\">" +
"<a class=\"timestamp\" rel=\"bookmark\" href=\"" + data [ 'url' ] + "\" >" +
"<abbr class=\"published\" title=\"" + data [ 'created_at' ] + "\">a few seconds ago</abbr>" +
"</a> " +
"<span class=\"source\">" +
"from " +
2009-09-22 04:17:37 +09:00
"<span class=\"device\">" + source + "</span>" + // may have a link
2009-09-24 06:07:20 +09:00
"</span>" ;
2010-05-18 04:37:47 +09:00
if ( data [ 'conversation_url' ] ) {
ni = ni + " <a class=\"response\" href=\"" + data [ 'conversation_url' ] + "\">in context</a>" ;
2009-09-24 06:07:20 +09:00
}
2009-09-22 04:17:37 +09:00
2009-12-16 05:47:37 +09:00
if ( repeat ) {
ru = repeat [ 'user' ] ;
ni = ni + "<span class=\"repeat vcard\">Repeated by " +
"<a href=\"" + ru [ 'profile_url' ] + "\" class=\"url\">" +
"<span class=\"nickname\">" + ru [ 'screen_name' ] + "</span></a></span>" ;
}
ni = ni + "</div>" ;
ni = ni + "<div class=\"notice-options\">" ;
2009-09-22 04:17:37 +09:00
2009-09-24 06:07:20 +09:00
if ( RealtimeUpdate . _userid != 0 ) {
var input = $ ( "form#form_notice fieldset input#token" ) ;
var session _key = input . val ( ) ;
ni = ni + RealtimeUpdate . makeFavoriteForm ( data [ 'id' ] , session _key ) ;
ni = ni + RealtimeUpdate . makeReplyLink ( data [ 'id' ] , data [ 'user' ] [ 'screen_name' ] ) ;
2009-12-16 05:47:37 +09:00
if ( RealtimeUpdate . _userid == responsible [ 'id' ] ) {
2009-07-15 04:26:39 +09:00
ni = ni + RealtimeUpdate . makeDeleteLink ( data [ 'id' ] ) ;
2009-12-16 06:19:11 +09:00
} else if ( RealtimeUpdate . _userid != user [ 'id' ] ) {
2009-12-16 04:44:20 +09:00
ni = ni + RealtimeUpdate . makeRepeatForm ( data [ 'id' ] , session _key ) ;
}
2009-09-24 06:07:20 +09:00
}
2009-09-22 04:17:37 +09:00
2009-12-16 05:47:37 +09:00
ni = ni + "</div>" ;
2010-02-01 07:57:35 +09:00
ni = ni + "</li>" ;
2009-09-24 06:07:20 +09:00
return ni ;
} ,
2009-09-22 04:17:37 +09:00
2010-12-01 09:35:47 +09:00
/ * *
* Creates a favorite button .
*
* @ param { number } id : notice ID to work with
* @ param { String } session _key : session token for form CSRF protection
* @ return { String } HTML fragment
*
* @ fixme this replicates core StatusNet code , making maintenance harder
* @ fixme sloppy HTML building ( raw concat without escaping )
* @ fixme no i18n support
*
* @ access private
* /
2009-09-24 06:07:20 +09:00
makeFavoriteForm : function ( id , session _key )
{
var ff ;
2009-09-22 04:17:37 +09:00
2009-09-24 06:07:20 +09:00
ff = "<form id=\"favor-" + id + "\" class=\"form_favor\" method=\"post\" action=\"" + RealtimeUpdate . _favorurl + "\">" +
2009-09-22 04:17:37 +09:00
"<fieldset>" +
2009-09-24 06:07:20 +09:00
"<legend>Favor this notice</legend>" +
"<input name=\"token-" + id + "\" type=\"hidden\" id=\"token-" + id + "\" value=\"" + session _key + "\"/>" +
"<input name=\"notice\" type=\"hidden\" id=\"notice-n" + id + "\" value=\"" + id + "\"/>" +
"<input type=\"submit\" id=\"favor-submit-" + id + "\" name=\"favor-submit-" + id + "\" class=\"submit\" value=\"Favor\" title=\"Favor this notice\"/>" +
2009-09-22 04:17:37 +09:00
"</fieldset>" +
2009-09-24 06:07:20 +09:00
"</form>" ;
return ff ;
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Creates a reply button .
*
* @ param { number } id : notice ID to work with
* @ param { String } nickname : nick of the user to whom we are replying
* @ return { String } HTML fragment
*
* @ fixme this replicates core StatusNet code , making maintenance harder
* @ fixme sloppy HTML building ( raw concat without escaping )
* @ fixme no i18n support
*
* @ access private
* /
2009-09-24 06:07:20 +09:00
makeReplyLink : function ( id , nickname )
{
var rl ;
rl = "<a class=\"notice_reply\" href=\"" + RealtimeUpdate . _replyurl + "?replyto=" + nickname + "\" title=\"Reply to this notice\">Reply <span class=\"notice_id\">" + id + "</span></a>" ;
return rl ;
2009-12-16 04:44:20 +09:00
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Creates a repeat button .
*
* @ param { number } id : notice ID to work with
* @ param { String } session _key : session token for form CSRF protection
* @ return { String } HTML fragment
*
* @ fixme this replicates core StatusNet code , making maintenance harder
* @ fixme sloppy HTML building ( raw concat without escaping )
* @ fixme no i18n support
*
* @ access private
* /
2009-12-16 04:44:20 +09:00
makeRepeatForm : function ( id , session _key )
{
var rf ;
rf = "<form id=\"repeat-" + id + "\" class=\"form_repeat\" method=\"post\" action=\"" + RealtimeUpdate . _repeaturl + "\">" +
"<fieldset>" +
2010-02-10 19:47:46 +09:00
"<legend>Repeat this notice?</legend>" +
2009-12-16 04:44:20 +09:00
"<input name=\"token-" + id + "\" type=\"hidden\" id=\"token-" + id + "\" value=\"" + session _key + "\"/>" +
2010-02-10 19:47:46 +09:00
"<input name=\"notice\" type=\"hidden\" id=\"notice-" + id + "\" value=\"" + id + "\"/>" +
"<input type=\"submit\" id=\"repeat-submit-" + id + "\" name=\"repeat-submit-" + id + "\" class=\"submit\" value=\"Yes\" title=\"Repeat this notice\"/>" +
2009-12-16 04:44:20 +09:00
"</fieldset>" +
"</form>" ;
return rf ;
} ,
2009-09-22 04:17:37 +09:00
2010-12-01 09:35:47 +09:00
/ * *
* Creates a delete button .
*
* @ param { number } id : notice ID to create a delete link for
* @ return { String } HTML fragment
*
* @ fixme this replicates core StatusNet code , making maintenance harder
* @ fixme sloppy HTML building ( raw concat without escaping )
* @ fixme no i18n support
*
* @ access private
* /
2009-09-24 06:07:20 +09:00
makeDeleteLink : function ( id )
{
var dl , delurl ;
delurl = RealtimeUpdate . _deleteurl . replace ( "0000000000" , id ) ;
2009-09-22 04:17:37 +09:00
2009-09-24 06:07:20 +09:00
dl = "<a class=\"notice_delete\" href=\"" + delurl + "\" title=\"Delete this notice\">Delete</a>" ;
2009-09-22 04:17:37 +09:00
2009-09-24 06:07:20 +09:00
return dl ;
2009-09-24 04:24:12 +09:00
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Adds a control widget at the top of the timeline view , containing
* pause / play and popup buttons .
*
* @ param { String } url : full URL to the popup window variant of this timeline page
* @ param { String } timeline : string key for the timeline ( eg 'public' or 'evan-all' )
* @ param { String } path : URL to the base directory containing the Realtime plugin ,
* used to fetch resources if needed .
*
* @ todo timeline and path parameters are unused and probably should be removed .
*
* @ access private
* /
2009-11-19 00:41:07 +09:00
initActions : function ( url , timeline , path )
{
2009-12-06 08:12:56 +09:00
$ ( '#notices_primary' ) . prepend ( '<ul id="realtime_actions"><li id="realtime_playpause"></li><li id="realtime_timeline"></li></ul>' ) ;
2009-11-19 00:41:07 +09:00
RealtimeUpdate . _pluginPath = path ;
RealtimeUpdate . initPlayPause ( ) ;
RealtimeUpdate . initAddPopup ( url , timeline , RealtimeUpdate . _pluginPath ) ;
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Initialize the state of the play / pause controls .
*
* If the browser supports the localStorage interface , we ' ll attempt
* to retrieve a pause state from there ; otherwise we default to paused .
*
* @ access private
* /
2009-11-19 00:41:07 +09:00
initPlayPause : function ( )
{
2009-12-07 21:12:32 +09:00
if ( typeof ( localStorage ) == 'undefined' ) {
RealtimeUpdate . showPause ( ) ;
}
else {
2009-12-07 20:44:43 +09:00
if ( localStorage . getItem ( 'RealtimeUpdate_paused' ) === 'true' ) {
RealtimeUpdate . showPlay ( ) ;
}
else {
RealtimeUpdate . showPause ( ) ;
}
}
2009-11-19 00:41:07 +09:00
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Switch the realtime UI into paused state .
* Uses SN . msg i18n system for the button label and tooltip .
*
* State will be saved and re - used next time if the browser supports
* the localStorage interface ( via setPause ) .
*
* @ access private
* /
2009-11-19 00:41:07 +09:00
showPause : function ( )
{
2009-12-07 20:44:43 +09:00
RealtimeUpdate . setPause ( false ) ;
2009-12-06 08:12:56 +09:00
RealtimeUpdate . showQueuedNotices ( ) ;
2009-12-07 07:07:49 +09:00
RealtimeUpdate . addNoticesHover ( ) ;
2009-11-19 00:41:07 +09:00
2009-12-06 08:12:56 +09:00
$ ( '#realtime_playpause' ) . remove ( ) ;
2010-11-03 03:39:38 +09:00
$ ( '#realtime_actions' ) . prepend ( '<li id="realtime_playpause"><button id="realtime_pause" class="pause"></button></li>' ) ;
2010-11-03 05:12:58 +09:00
$ ( '#realtime_pause' ) . text ( SN . msg ( 'realtime_pause' ) )
. attr ( 'title' , SN . msg ( 'realtime_pause_tooltip' ) )
2010-11-03 03:39:38 +09:00
. bind ( 'click' , function ( ) {
2009-12-06 08:12:56 +09:00
RealtimeUpdate . removeNoticesHover ( ) ;
2009-11-19 00:41:07 +09:00
RealtimeUpdate . showPlay ( ) ;
return false ;
} ) ;
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Switch the realtime UI into play state .
* Uses SN . msg i18n system for the button label and tooltip .
*
* State will be saved and re - used next time if the browser supports
* the localStorage interface ( via setPause ) .
*
* @ access private
* /
2009-11-19 00:41:07 +09:00
showPlay : function ( )
{
2009-12-07 20:44:43 +09:00
RealtimeUpdate . setPause ( true ) ;
2009-12-06 08:12:56 +09:00
$ ( '#realtime_playpause' ) . remove ( ) ;
2010-11-03 03:39:38 +09:00
$ ( '#realtime_actions' ) . prepend ( '<li id="realtime_playpause"><span id="queued_counter"></span> <button id="realtime_play" class="play"></button></li>' ) ;
2010-11-03 05:12:58 +09:00
$ ( '#realtime_play' ) . text ( SN . msg ( 'realtime_play' ) )
. attr ( 'title' , SN . msg ( 'realtime_play_tooltip' ) )
2010-11-03 03:39:38 +09:00
. bind ( 'click' , function ( ) {
2009-11-19 00:41:07 +09:00
RealtimeUpdate . showPause ( ) ;
return false ;
} ) ;
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Update the internal pause / play state .
* Do not call directly ; use showPause ( ) and showPlay ( ) .
*
* State will be saved and re - used next time if the browser supports
* the localStorage interface .
*
* @ param { boolean } state : true = paused , false = not paused
*
* @ access private
* /
2009-12-07 20:44:43 +09:00
setPause : function ( state )
{
RealtimeUpdate . _paused = state ;
if ( typeof ( localStorage ) != 'undefined' ) {
localStorage . setItem ( 'RealtimeUpdate_paused' , RealtimeUpdate . _paused ) ;
}
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Go through notices we have previously received while paused ,
* dumping them into the timeline view .
*
* @ fixme long timelines are not trimmed here as they are for things received while not paused
*
* @ access private
* /
2009-11-19 02:23:04 +09:00
showQueuedNotices : function ( )
{
2009-11-19 00:41:07 +09:00
$ . each ( RealtimeUpdate . _queuedNotices , function ( i , n ) {
RealtimeUpdate . insertNoticeItem ( n ) ;
} ) ;
RealtimeUpdate . _queuedNotices = [ ] ;
2009-11-19 02:23:04 +09:00
RealtimeUpdate . removeQueuedCounter ( ) ;
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Update the Realtime widget control ' s counter of queued notices to show
* the current count . This will be called after receiving and queueing
* a notice while paused .
*
* @ access private
* /
2009-11-19 02:23:04 +09:00
updateQueuedCounter : function ( )
{
2009-11-19 04:15:55 +09:00
$ ( '#realtime_playpause #queued_counter' ) . html ( '(' + RealtimeUpdate . _queuedNotices . length + ')' ) ;
2009-11-19 02:23:04 +09:00
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Clear the Realtime widget control ' s counter of queued notices .
*
* @ access private
* /
2009-11-19 02:23:04 +09:00
removeQueuedCounter : function ( )
{
$ ( '#realtime_playpause #queued_counter' ) . empty ( ) ;
2009-11-19 00:41:07 +09:00
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Set up event handlers on the timeline view to automatically pause
* when the mouse is over the timeline , as this indicates the user ' s
* desire to interact with the UI . ( Which is hard to do when it ' s moving ! )
*
* @ access private
* /
2009-12-06 08:12:56 +09:00
addNoticesHover : function ( )
{
$ ( '#notices_primary .notices' ) . hover (
function ( ) {
if ( RealtimeUpdate . _paused === false ) {
RealtimeUpdate . showPlay ( ) ;
}
} ,
function ( ) {
if ( RealtimeUpdate . _paused === true ) {
RealtimeUpdate . showPause ( ) ;
}
}
) ;
} ,
2010-12-01 09:35:47 +09:00
/ * *
* Tear down event handlers on the timeline view to automatically pause
* when the mouse is over the timeline .
*
* @ fixme this appears to remove * ALL * event handlers from the timeline ,
* which assumes that nobody else is adding any event handlers .
* Sloppy -- we should only remove the ones we add .
*
* @ access private
* /
2009-12-06 08:12:56 +09:00
removeNoticesHover : function ( )
{
2009-12-07 07:07:49 +09:00
$ ( '#notices_primary .notices' ) . unbind ( ) ;
2009-12-06 08:12:56 +09:00
} ,
2010-12-01 09:35:47 +09:00
/ * *
* UI initialization , to be called from Realtime plugin code on regular
* timeline pages .
*
* Adds a button to the control widget at the top of the timeline view ,
* allowing creation of a popup window with a more compact real - time
* view of the current timeline .
*
* @ param { String } url : full URL to the popup window variant of this timeline page
* @ param { String } timeline : string key for the timeline ( eg 'public' or 'evan-all' )
* @ param { String } path : URL to the base directory containing the Realtime plugin ,
* used to fetch resources if needed .
*
* @ todo timeline and path parameters are unused and probably should be removed .
*
* @ access public
* /
2009-11-19 00:41:07 +09:00
initAddPopup : function ( url , timeline , path )
2009-09-24 04:24:12 +09:00
{
2010-11-03 03:39:38 +09:00
$ ( '#realtime_timeline' ) . append ( '<button id="realtime_popup"></button>' ) ;
2010-11-03 05:12:58 +09:00
$ ( '#realtime_popup' ) . text ( SN . msg ( 'realtime_popup' ) )
. attr ( 'title' , SN . msg ( 'realtime_popup_tooltip' ) )
2010-11-03 03:39:38 +09:00
. bind ( 'click' , function ( ) {
window . open ( url ,
2009-11-18 19:43:55 +09:00
'' ,
2009-11-26 06:32:51 +09:00
'toolbar=no,resizable=yes,scrollbars=yes,status=no,menubar=no,personalbar=no,location=no,width=500,height=550' ) ;
2009-09-27 20:49:18 +09:00
2009-09-24 06:58:35 +09:00
return false ;
} ) ;
2009-09-24 07:02:42 +09:00
} ,
2010-12-01 09:35:47 +09:00
/ * *
* UI initialization , to be called from Realtime plugin code on popup
* compact timeline pages .
*
* Sets up links in notices to open in a new window .
*
* @ fixme fails to do the same for UI links like context view which will
* look bad in the tiny chromeless window .
*
* @ access public
* /
2009-09-24 07:02:42 +09:00
initPopupWindow : function ( )
{
2009-11-18 19:42:43 +09:00
$ ( '.notices .entry-title a, .notices .entry-content a' ) . bind ( 'click' , function ( ) {
window . open ( this . href , '' ) ;
2009-12-16 05:47:37 +09:00
2009-11-18 19:42:43 +09:00
return false ;
} ) ;
2009-11-20 13:09:40 +09:00
$ ( '#showstream .entity_profile' ) . css ( { 'width' : '69%' } ) ;
2009-09-24 06:07:20 +09:00
}
}
2009-09-22 04:17:37 +09:00