2013-02-13 22:04:35 +01:00
var tutorial = ( function ( ) {
var exports = { } ;
2013-06-20 18:06:31 +02:00
var is _running = false ;
2013-07-02 19:58:44 +02:00
var event _handlers = { } ;
2013-08-09 23:02:43 +02:00
var deferred _work = [ ] ;
2013-02-13 22:15:13 +01:00
2014-02-04 20:37:37 +01:00
// Keep track of where we are for handling resizing.
var current _popover _info ;
2013-06-27 22:18:03 +02:00
// We'll temporarily set stream colors for the streams we use in the demo
// tutorial messages.
2014-02-05 21:43:11 +01:00
var real _default _color ;
var tutorial _default _color = '#76ce90' ;
2013-06-27 22:18:03 +02:00
// Each message object contains the minimal information necessary for it to be
// processed by our system for adding messages to your feed.
2013-07-02 21:35:51 +02:00
var today = new Date ( ) . getTime ( ) / 1000 ;
2013-06-27 22:18:03 +02:00
var fake _messages = [
{
id : 1 ,
2014-01-14 23:05:35 +01:00
content : "<p>We're working on some new screenshots for our landing page!</p>" ,
2013-06-27 22:18:03 +02:00
is _stream : true ,
2014-01-14 23:05:35 +01:00
sender _full _name : "Abbie Patel" ,
sender _email : "abbie@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/5a8d2b3836d546d523f460924a8a9973" ,
display _recipient : "engineering" ,
stream : "engineering" ,
2013-06-27 22:18:03 +02:00
subject : "screenshots" ,
timestr : "12:11" ,
2013-07-02 21:35:51 +02:00
timestamp : today ,
2013-06-27 22:18:03 +02:00
type : "stream"
} ,
{
id : 2 ,
2014-01-14 23:05:35 +01:00
content : "<p>Here's the <a href='https://zulip.com/static/images/app-screenshots/zulip-desktop-windows.png' target='_blank' title='https://zulip.com/static/images/app-screenshots/zulip-desktop-windows.png'>latest version</a>:<div class='message_inline_image'><a href='https://zulip.com/static/images/app-screenshots/zulip-desktop-windows.png' target='_blank' title='https://zulip.com/static/images/app-screenshots/zulip-desktop-windows.png'><img src='https://zulip.com/static/images/app-screenshots/zulip-desktop-windows.png'></a></div> for the Windows app -- thoughts? I'm particularly wondering whether people think the screenshot should be from Windows 7 or some other version.</p>" ,
is _stream : true ,
sender _full _name : "Abbie Patel" ,
sender _email : "abbie@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/5a8d2b3836d546d523f460924a8a9973" ,
display _recipient : "engineering" ,
stream : "engineering" ,
subject : "screenshots" ,
timestr : "12:11" ,
2013-07-02 21:35:51 +02:00
timestamp : today ,
2014-01-14 23:05:35 +01:00
type : "stream"
2013-06-27 22:18:03 +02:00
} ,
{
id : 3 ,
2014-01-14 23:05:35 +01:00
content : "<p>Looks good to me! <img alt=':+1:' class='emoji' src='static/third/gemoji/images/emoji/+1.png' title=':+1:'></p>" ,
is _stream : true ,
sender _full _name : "Jeff Arnold" ,
sender _email : "jeff@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/dd0cf69d6d1989aa0b0d8c722f7d5840" ,
display _recipient : "engineering" ,
stream : "engineering" ,
subject : "screenshots" ,
timestr : "12:16" ,
2013-07-02 21:35:51 +02:00
timestamp : today ,
2014-01-14 23:05:35 +01:00
type : "stream"
2013-06-27 22:18:03 +02:00
} ,
{
id : 4 ,
2014-01-14 23:05:35 +01:00
content : "<p>Adam and I just finished a brainstorming session for the next set of integrations we want to support.</p><p><a href=''>Here</a> are our notes. I'll open tickets for the action items.</p>" ,
2013-06-27 22:18:03 +02:00
is _stream : true ,
2014-01-14 23:05:35 +01:00
sender _full _name : "Jessica McKellar" ,
sender _email : "jessica@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/2a1ffb4ef0b4a20c04d540a35f430cf6" ,
display _recipient : "engineering" ,
stream : "engineering" ,
subject : "integrations" ,
timestr : "12:25" ,
2013-07-02 21:35:51 +02:00
timestamp : today ,
2013-06-27 22:18:03 +02:00
type : "stream"
} ,
{
id : 5 ,
2014-01-14 23:05:35 +01:00
content : "<p>Yay, Twitter integration. <img alt=':heart_eyes:' class='emoji' src='static/third/gemoji/images/emoji/heart_eyes.png' title=':heart_eyes:'></p>" ,
2013-06-27 22:18:03 +02:00
is _stream : true ,
2014-01-14 23:05:35 +01:00
sender _full _name : "Leo Franchi" ,
sender _email : "leo@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/4309007c980e1e8b9a2453488586482a" ,
display _recipient : "engineering" ,
stream : "engineering" ,
subject : "integrations" ,
timestr : "12:25" ,
2013-07-02 21:35:51 +02:00
timestamp : today ,
2013-06-27 22:18:03 +02:00
type : "stream"
} ,
{
id : 6 ,
2014-01-14 23:05:35 +01:00
content : "<p>We need to add support for a few more markdown features before we can do GitHub integration.</p>" ,
2013-06-27 22:18:03 +02:00
is _stream : true ,
2014-01-14 23:05:35 +01:00
sender _full _name : "Li Jing" ,
sender _email : "li@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/2950c2c87fe7daaa56fd6a403ecc2ee0" ,
display _recipient : "engineering" ,
stream : "engineering" ,
subject : "integrations" ,
timestr : "12:26" ,
2013-07-02 21:35:51 +02:00
timestamp : today ,
2013-06-27 22:18:03 +02:00
type : "stream"
} ,
{
id : 7 ,
2014-01-14 23:05:35 +01:00
content : "<p>Good point, I'll add that to the ticket.</p>" ,
2013-06-27 22:18:03 +02:00
is _stream : true ,
2014-01-14 23:05:35 +01:00
sender _full _name : "Jessica McKellar" ,
sender _email : "jessica@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/2a1ffb4ef0b4a20c04d540a35f430cf6" ,
display _recipient : "engineering" ,
stream : "engineering" ,
subject : "integrations" ,
timestr : "12:26" ,
2013-07-02 21:35:51 +02:00
timestamp : today ,
2013-06-27 22:18:03 +02:00
type : "stream"
} ,
{
id : 8 ,
2014-01-14 23:05:35 +01:00
content : "<p><img alt=':clock1130:' class='emoji' src='static/third/gemoji/images/emoji/clock1130.png' title=':clock1130:'> Reminder: engineering meeting in 1 hour. <img alt=':clock1130:' class='emoji' src='static/third/gemoji/images/emoji/clock1130.png' title=':clock1130:'></p>" ,
2013-06-27 22:18:03 +02:00
is _stream : true ,
2014-01-14 23:05:35 +01:00
sender _full _name : "Reminder Bot" ,
sender _email : "reminder-bot@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/78873d7213d102dc36773046560d403a" ,
display _recipient : "engineering" ,
stream : "engineering" ,
subject : "weekly meeting" ,
timestr : "12:30" ,
timestamp : today ,
type : "stream"
} ,
{
id : 9 ,
content : "<p>Quickly brainstorming my remaining TODO list out loud for you all:</p>" ,
is _stream : true ,
sender _full _name : "Abbie Patel" ,
sender _email : "abbie@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/5a8d2b3836d546d523f460924a8a9973" ,
display _recipient : "engineering" ,
stream : "engineering" ,
subject : "screenshots" ,
timestr : "12:32" ,
timestamp : today ,
type : "stream"
} ,
{
id : 10 ,
content : "<p><ul><li>Redo iPhone shot</li><li>Double-check layout on iPad</li><li>Update copy for new iOS app version</li><li>Check with Android team on timeline for login redesign</li></ul></p>" ,
is _stream : true ,
sender _full _name : "Abbie Patel" ,
sender _email : "abbie@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/5a8d2b3836d546d523f460924a8a9973" ,
display _recipient : "engineering" ,
stream : "engineering" ,
subject : "screenshots" ,
timestr : "12:32" ,
timestamp : today ,
type : "stream"
} ,
{
id : 11 ,
content : "<p>Oops, I actually took care of the text for iOS and forgot to update the ticket -- I'll do that now.</p>" ,
is _stream : true ,
sender _full _name : "Jeff Arnold" ,
sender _email : "jeff@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/dd0cf69d6d1989aa0b0d8c722f7d5840" ,
display _recipient : "engineering" ,
stream : "engineering" ,
subject : "screenshots" ,
timestr : "12:16" ,
timestamp : today ,
type : "stream"
} ,
{
id : 12 ,
content : "<p>No problem, less work for me. <img alt=':smile:' class='emoji' src='static/third/gemoji/images/emoji/smile.png' title=':smile:'></p>" ,
is _stream : true ,
sender _full _name : "Abbie Patel" ,
sender _email : "abbie@zulip.com" ,
avatar _url : "https://secure.gravatar.com/avatar/5a8d2b3836d546d523f460924a8a9973" ,
display _recipient : "engineering" ,
stream : "engineering" ,
subject : "screenshots" ,
timestr : "12:32" ,
2013-07-02 21:35:51 +02:00
timestamp : today ,
2013-06-27 22:18:03 +02:00
type : "stream"
}
] ;
2014-01-14 23:53:35 +01:00
function send _delayed _stream _message ( stream , topic , content , delay ) {
setTimeout ( function ( ) {
$ . ajax ( {
dataType : 'json' ,
url : '/json/tutorial_send_message' ,
type : 'POST' ,
data : { 'type' : 'stream' ,
'recipient' : stream ,
'topic' : topic ,
'content' : content }
} ) ;
} , delay * 1000 ) ; // delay is in seconds.
}
2014-01-09 21:00:01 +01:00
function hide _app _alert ( ) {
2013-09-19 16:30:08 +02:00
$ ( '#alert-bar-container' ) . slideUp ( 100 ) ;
}
2014-01-09 21:00:01 +01:00
function show _app _alert ( contents ) {
$ ( '#custom-alert-bar-content' ) . html ( contents ) ;
2013-09-19 16:30:08 +02:00
$ ( '#alert-bar-container' ) . show ( ) ;
2014-01-09 21:00:01 +01:00
$ ( '#alert-bar-container .close-alert-icon' ) . expectOne ( ) . click ( hide _app _alert ) ;
2013-09-19 16:30:08 +02:00
}
2013-07-02 19:58:44 +02:00
function disable _event _handlers ( ) {
$ ( 'body' ) . css ( { 'overflow' : 'hidden' } ) ; // prevents scrolling the feed
2013-07-30 00:35:44 +02:00
_ . each ( [ "keydown" , "keyup" , "keypress" , "scroll" ] , function ( event _name ) {
2013-07-02 19:58:44 +02:00
var existing _events = $ ( document ) . data ( "events" ) [ event _name ] ;
if ( existing _events === undefined ) {
existing _events = [ ] ;
}
event _handlers [ event _name ] = existing _events ;
$ ( document ) . data ( "events" ) [ event _name ] = [ ] ;
} ) ;
}
function enable _event _handlers ( ) {
$ ( 'body' ) . css ( { 'overflow' : 'auto' } ) ; // enables scrolling the feed
2013-07-30 00:35:44 +02:00
_ . each ( [ "keydown" , "keyup" , "keypress" , "scroll" ] , function ( event _name ) {
2013-07-03 22:58:15 +02:00
$ ( document ) . data ( "events" ) [ event _name ] = event _handlers [ event _name ] ;
2013-07-02 19:58:44 +02:00
} ) ;
}
2013-04-12 21:33:00 +02:00
function set _tutorial _status ( status , callback ) {
2013-12-18 19:55:18 +01:00
return channel . post ( {
2013-06-20 18:06:31 +02:00
url : '/json/tutorial_status' ,
data : { status : status } ,
success : callback
2013-04-12 21:33:00 +02:00
} ) ;
}
2013-07-05 17:43:56 +02:00
exports . is _running = function ( ) {
2013-06-20 18:06:31 +02:00
return is _running ;
2013-02-13 22:15:13 +01:00
} ;
2013-06-27 22:18:28 +02:00
function box ( x , y , width , height ) {
// Blanket everything ouside the box defined by the parameters in a
// translucent black screen, and cover the box itself with a clear screen so
// nothing in it is clickable.
//
// x and y are the coordinates for hte upper-left corner of the box.
var doc _width = $ ( document ) . width ( ) ;
var doc _height = $ ( document ) . height ( ) ;
$ ( "#top-screen" ) . css ( { opacity : 0.7 , width : doc _width , height : y } ) ;
$ ( "#bottom-screen" ) . offset ( { top : y + height , left : 0 } ) ;
$ ( "#bottom-screen" ) . css ( { opacity : 0.7 , width : doc _width , height : doc _height } ) ;
$ ( "#left-screen" ) . offset ( { top : y , left : 0 } ) ;
$ ( "#left-screen" ) . css ( { opacity : 0.7 , width : x , height : height } ) ;
$ ( "#right-screen" ) . offset ( { top : y , left : x + width } ) ;
$ ( "#right-screen" ) . css ( { opacity : 0.7 , width : x , height : height } ) ;
$ ( "#clear-screen" ) . css ( { opacity : 0.0 , width : doc _width , height : doc _height } ) ;
}
function messages _in _viewport ( ) {
var vp = viewport . message _viewport _info ( ) ;
var top = vp . visible _top ;
var height = vp . visible _height ;
var last _row = rows . last _visible ( ) ;
return $ . merge ( last _row , last _row . prevAll ( ) ) . filter ( function ( idx , row ) {
var row _offset = $ ( row ) . offset ( ) ;
return ( row _offset . top > top && row _offset . top < top + height ) ;
} ) ;
}
2013-07-10 16:42:54 +02:00
function small _window ( ) {
2013-08-27 20:31:12 +02:00
return ! $ ( "#left-sidebar" ) . is ( ":visible" ) ;
2013-07-10 16:42:54 +02:00
}
function maybe _tweak _placement ( placement ) {
// If viewed on a small screen, move popovers on the left to the center so
// they won't be cut off.
if ( ! small _window ( ) ) {
return placement ;
}
if ( placement === "left" ) {
return "bottom" ;
}
if ( placement === "bottom" ) {
return "right" ;
}
}
2013-06-27 22:18:28 +02:00
function create _and _show _popover ( target _div , placement , title , content _template ) {
2014-02-04 20:37:37 +01:00
$ ( ".popover" ) . remove ( ) ;
target _div . popover ( "destroy" ) ;
2013-06-27 22:18:28 +02:00
target _div . popover ( {
placement : placement ,
2013-08-27 20:31:12 +02:00
title : templates . render ( "tutorial_title" , { title : title ,
placement : placement } ) ,
content : templates . render ( content _template , { placement : placement } ) ,
2013-06-27 22:18:28 +02:00
trigger : "manual"
} ) ;
target _div . popover ( "show" ) ;
$ ( ".popover" ) . css ( "z-index" , 20001 ) ;
2013-08-27 20:31:12 +02:00
$ ( ".popover-title" ) . addClass ( "popover-" + placement ) ;
2013-06-27 22:18:28 +02:00
}
2013-08-09 23:02:43 +02:00
exports . defer = function ( callback ) {
deferred _work . push ( callback ) ;
} ;
2013-06-27 22:18:28 +02:00
function finale ( ) {
var finale _modal = $ ( "#tutorial-finale" ) ;
$ ( ".screen" ) . css ( { opacity : 0.0 } ) ;
finale _modal . css ( "z-index" , 20001 ) ;
finale _modal . modal ( "show" ) ;
$ ( "#tutorial-get-started" ) . click ( function ( ) {
finale _modal . modal ( "hide" ) ;
$ ( ".screen" ) . css ( { opacity : 0.0 , width : 0 , height : 0 } ) ;
2014-01-07 21:07:15 +01:00
} ) . focus ( ) ;
2013-06-27 22:18:28 +02:00
// Restore your actual stream colors and rerender to display any
// messages received during the tutorial.
set _tutorial _status ( "finished" ) ;
is _running = false ;
current _msg _list . clear ( ) ;
// Force a check on new events before we re-render the message list.
2014-01-30 20:29:00 +01:00
server _events . force _get _events ( ) ;
2014-02-05 21:43:11 +01:00
stream _color . default _color = real _default _color ;
2013-06-27 22:18:28 +02:00
util . show _first _run _message ( ) ;
current _msg _list . rerender ( ) ;
2013-07-02 19:58:44 +02:00
enable _event _handlers ( ) ;
2013-08-09 23:02:43 +02:00
_ . each ( deferred _work , function ( callback ) {
callback ( ) ;
} ) ;
deferred _work = [ ] ;
2014-01-09 22:53:18 +01:00
var alert _contents ;
if ( page _params . prompt _for _invites ) {
alert _contents = "<i class='icon-vector-heart alert-icon'></i>It's lonely in here! <a href='#invite-user' data-toggle='modal'>Invite some coworkers</a>." ;
} else {
2014-01-13 18:47:48 +01:00
alert _contents = "<i class='icon-vector-desktop alert-icon'></i>What's better than Zulip in your browser? The <a href='/apps' target='_blank'>Zulip desktop app</a>!" ;
2014-01-09 22:53:18 +01:00
}
2014-01-09 21:00:01 +01:00
show _app _alert ( alert _contents ) ;
2014-01-13 19:37:21 +01:00
// We start you in a narrow so it's not overwhelming.
if ( stream _data . in _home _view ( page _params . notifications _stream ) ) {
narrow . activate ( [ [ "stream" , page _params . notifications _stream ] ] ) ;
}
2014-01-14 23:53:35 +01:00
if ( page _params . first _in _realm ) {
2014-01-15 20:59:31 +01:00
// 'engineering' is the best possible stream since we used it in the
// tutorial, but fall back to something else if we have to.
var work _stream ;
2014-01-14 23:53:35 +01:00
if ( stream _data . in _home _view ( "engineering" ) ) {
2014-01-15 20:59:31 +01:00
work _stream = "engineering" ;
} else {
work _stream = _ . find ( stream _data . home _view _stream _names ( ) ,
function ( stream _name ) {
return ( stream _name !== "social" ) && ( stream _name !== page _params . notifications _stream ) ;
} ) ;
}
2014-01-22 22:42:13 +01:00
if ( stream _data . in _home _view ( page _params . notifications _stream ) ) {
send _delayed _stream _message ( page _params . notifications _stream , "welcome" , "Practice sending sending some messages here, or starting a new topic." , 15 ) ;
send _delayed _stream _message ( page _params . notifications _stream , "Zulip tips" , "Here's a message on a new topic: `Zulip tips`.\n\nAs you settle into Zulip, customize your account and notifications on your [Settings page](#settings)." , 30 ) ;
send _delayed _stream _message ( page _params . notifications _stream , "Zulip tips" , "You might also enjoy:\n\n* Our lightweight !modal_link(#markdown-help, message formatting) (including emoji! :thumbsup:)\n* !modal_link(#keyboard-shortcuts, Keyboard shortcuts)\n* [Desktop and mobile apps](/apps)" , 40 ) ;
}
2014-01-15 20:59:31 +01:00
if ( work _stream !== undefined ) {
2014-01-22 22:42:13 +01:00
send _delayed _stream _message ( work _stream , "projects" , "This is a message on stream `" + work _stream + "` with the topic `projects`." , 60 ) ;
send _delayed _stream _message ( work _stream , "projects" , "Take a peek at our [integrations](/integrations). Now's a great time to set one up!" , 65 ) ;
2014-01-14 23:53:35 +01:00
}
if ( stream _data . in _home _view ( "social" ) ) {
2014-01-22 22:42:13 +01:00
send _delayed _stream _message ( "social" , "cute animals" , "This is a message on stream `social` with the topic `cute animals`. Try uploading or pasting in some pictures. Here's a [guinea pig](https://humbug-user-uploads.s3.amazonaws.com/byqgM1qjol1mzje_KzeNRT5F/guinea.jpg) to get you started:" , 75 ) ;
2014-01-14 23:53:35 +01:00
}
}
2013-06-27 22:18:28 +02:00
}
2014-02-04 20:37:37 +01:00
function update _popover _info ( popover _func ) {
current _popover _info = popover _func ;
}
function box _first _message ( ) {
var spotlight _message = rows . first _visible ( ) ;
var bar = spotlight _message . prev ( ".recipient_row" ) ;
var x = bar . offset ( ) . left ;
var y = bar . offset ( ) . top ;
var message _height = bar . height ( ) + spotlight _message . height ( ) ;
var message _width = bar . width ( ) ;
box ( x , y , message _width , message _height ) ;
}
function box _messagelist ( ) {
var spotlight _message = rows . first _visible ( ) . prev ( ".recipient_row" ) ;
var x = spotlight _message . offset ( ) . left ;
var y = spotlight _message . offset ( ) . top ;
var height = 0 ;
_ . each ( messages _in _viewport ( ) , function ( row ) {
height += $ ( row ) . height ( ) ;
} ) ;
box ( x , y , spotlight _message . width ( ) , height ) ;
}
2013-06-27 22:18:28 +02:00
function reply ( ) {
var spotlight _message = rows . first _visible ( ) . prev ( ".recipient_row" ) ;
2014-02-04 20:37:37 +01:00
box _messagelist ( ) ;
2013-07-10 16:42:54 +02:00
create _and _show _popover ( spotlight _message , maybe _tweak _placement ( "left" ) ,
"Replying" , "tutorial_reply" ) ;
2013-06-27 22:18:28 +02:00
var my _popover = $ ( "#tutorial-reply" ) . closest ( ".popover" ) ;
my _popover . offset ( { left : my _popover . offset ( ) . left - 10 } ) ;
2014-02-04 20:37:37 +01:00
update _popover _info ( reply , spotlight _message ) ;
2013-06-27 22:18:28 +02:00
$ ( "#tutorial-reply-next" ) . click ( function ( ) {
spotlight _message . popover ( "destroy" ) ;
finale ( ) ;
2014-01-07 21:07:15 +01:00
} ) . focus ( ) ;
2013-06-27 22:18:28 +02:00
}
function home ( ) {
var spotlight _message = rows . first _visible ( ) . prev ( ".recipient_row" ) ;
2014-02-04 20:37:37 +01:00
box _messagelist ( ) ;
2013-07-10 16:42:54 +02:00
create _and _show _popover ( spotlight _message , maybe _tweak _placement ( "left" ) ,
2014-01-14 17:42:46 +01:00
"Narrowing" , "tutorial_home" ) ;
2013-06-27 22:18:28 +02:00
var my _popover = $ ( "#tutorial-home" ) . closest ( ".popover" ) ;
my _popover . offset ( { left : my _popover . offset ( ) . left - 10 } ) ;
2014-02-04 20:37:37 +01:00
update _popover _info ( home , spotlight _message ) ;
2013-06-27 22:18:28 +02:00
$ ( "#tutorial-home-next" ) . click ( function ( ) {
spotlight _message . popover ( "destroy" ) ;
reply ( ) ;
2014-01-07 21:07:15 +01:00
} ) . focus ( ) ;
2013-06-27 22:18:28 +02:00
}
function subject ( ) {
var spotlight _message = rows . first _visible ( ) ;
var bar = spotlight _message . prev ( ".recipient_row" ) ;
2013-07-10 16:42:54 +02:00
var placement = maybe _tweak _placement ( "bottom" ) ;
2014-02-04 20:37:37 +01:00
box _first _message ( ) ;
2013-07-16 21:00:52 +02:00
create _and _show _popover ( bar , placement , "Topics" , "tutorial_subject" ) ;
2013-06-27 22:18:28 +02:00
var my _popover = $ ( "#tutorial-subject" ) . closest ( ".popover" ) ;
2013-07-10 16:42:54 +02:00
if ( placement === "bottom" ) { // Wider screen, popover is on bottom.
2014-01-14 23:05:35 +01:00
my _popover . offset ( { left : bar . offset ( ) . left + 140 - my _popover . width ( ) / 2 } ) ;
2013-07-10 16:42:54 +02:00
} else {
2014-01-14 23:05:35 +01:00
my _popover . offset ( { left : bar . offset ( ) . left + 194 } ) ;
2013-07-10 16:42:54 +02:00
}
2014-02-04 20:37:37 +01:00
update _popover _info ( subject , bar ) ;
2013-06-27 22:18:28 +02:00
$ ( "#tutorial-subject-next" ) . click ( function ( ) {
bar . popover ( "destroy" ) ;
2014-01-14 17:42:46 +01:00
home ( ) ;
2014-01-07 21:07:15 +01:00
} ) . focus ( ) ;
2013-06-27 22:18:28 +02:00
}
function stream ( ) {
var bar = rows . first _visible ( ) . prev ( ".recipient_row" ) ;
2013-07-10 16:42:54 +02:00
var placement = maybe _tweak _placement ( "bottom" ) ;
2014-02-04 20:37:37 +01:00
box _first _message ( ) ;
2013-07-10 16:42:54 +02:00
create _and _show _popover ( bar , placement , "Streams" , "tutorial_stream" ) ;
2013-06-27 22:18:28 +02:00
var my _popover = $ ( "#tutorial-stream" ) . closest ( ".popover" ) ;
2013-07-10 16:42:54 +02:00
if ( placement === "bottom" ) { // Wider screen, popover is on bottom.
2014-01-14 23:05:35 +01:00
my _popover . offset ( { left : bar . offset ( ) . left + 50 - my _popover . width ( ) / 2 } ) ;
2013-07-10 16:42:54 +02:00
} else { // Smaller screen, popover is to the right of the stream label.
2014-01-14 23:05:35 +01:00
my _popover . offset ( { left : bar . offset ( ) . left + 98 } ) ;
2013-07-10 16:42:54 +02:00
}
2014-02-04 20:37:37 +01:00
update _popover _info ( stream , bar ) ;
2013-06-27 22:18:28 +02:00
$ ( "#tutorial-stream-next" ) . click ( function ( ) {
bar . popover ( "destroy" ) ;
subject ( ) ;
2014-01-07 21:07:15 +01:00
} ) . focus ( ) ;
2013-06-27 22:18:28 +02:00
}
2014-01-14 17:42:46 +01:00
function welcome ( ) {
// Grey out everything.
$ ( '#top-screen' ) . css ( { opacity : 0.7 , width : $ ( document ) . width ( ) ,
height : $ ( document ) . height ( ) } ) ;
2013-06-27 22:18:28 +02:00
var spotlight _message = rows . first _visible ( ) ;
var bar = spotlight _message . prev ( ".recipient_row" ) ;
2014-02-04 20:37:37 +01:00
box _first _message ( ) ;
2014-01-14 17:42:46 +01:00
create _and _show _popover ( bar , maybe _tweak _placement ( "left" ) , "Welcome" ,
2013-07-10 16:42:54 +02:00
"tutorial_message" ) ;
2013-06-27 22:18:28 +02:00
var my _popover = $ ( "#tutorial-message" ) . closest ( ".popover" ) ;
my _popover . offset ( { left : my _popover . offset ( ) . left - 10 } ) ;
2014-02-04 20:37:37 +01:00
update _popover _info ( welcome , bar ) ;
2013-06-27 22:18:28 +02:00
$ ( "#tutorial-message-next" ) . click ( function ( ) {
bar . popover ( "destroy" ) ;
stream ( ) ;
2014-01-07 21:07:15 +01:00
} ) . focus ( ) ;
2013-06-27 22:18:28 +02:00
}
2013-06-20 18:06:31 +02:00
exports . start = function ( ) {
2013-07-02 22:13:52 +02:00
if ( ui . home _tab _obscured ( ) ) {
ui . change _tab _to ( '#home' ) ;
}
narrow . deactivate ( ) ;
2013-06-27 22:18:03 +02:00
// Set temporarly colors for the streams used in the tutorial.
2014-02-05 21:43:11 +01:00
real _default _color = stream _color . default _color ;
stream _color . default _color = tutorial _default _color ;
2013-06-27 22:18:03 +02:00
// Add the fake messages to the feed and get started.
current _msg _list . add _and _rerender ( fake _messages ) ;
2013-07-02 19:58:44 +02:00
disable _event _handlers ( ) ;
2013-06-20 18:06:31 +02:00
is _running = true ;
set _tutorial _status ( "started" ) ;
2013-06-27 22:18:28 +02:00
welcome ( ) ;
2013-02-13 22:15:13 +01:00
} ;
exports . initialize = function ( ) {
2013-03-25 23:26:14 +01:00
if ( page _params . needs _tutorial ) {
2013-03-07 21:14:44 +01:00
exports . start ( ) ;
2013-02-13 22:15:13 +01:00
}
2014-02-04 20:37:37 +01:00
$ ( window ) . resize ( $ . debounce ( 100 , function ( ) {
if ( current _popover _info !== undefined ) {
current _popover _info ( ) ;
}
} ) ) ;
2013-02-13 22:15:13 +01:00
} ;
2013-02-13 22:04:35 +01:00
return exports ;
} ( ) ) ;
2014-01-31 06:24:15 +01:00
if ( typeof module !== 'undefined' ) {
module . exports = tutorial ;
}