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 ,
2017-01-12 00:17:43 +01:00
type : "stream" ,
2013-06-27 22:18:03 +02:00
} ,
{
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 ,
2017-01-12 00:17:43 +01:00
type : "stream" ,
2013-06-27 22:18:03 +02:00
} ,
{
id : 3 ,
2017-06-09 10:30:24 +02:00
content : "<p>Looks good to me! <img alt=':+1:' class='emoji' src='/static/generated/emoji/images/emoji/+1.png' title='+1'></p>" ,
2014-01-14 23:05:35 +01:00
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 ,
2017-01-12 00:17:43 +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 ,
2017-01-12 00:17:43 +01:00
type : "stream" ,
2013-06-27 22:18:03 +02:00
} ,
{
id : 5 ,
2017-06-09 10:30:24 +02:00
content : "<p>Yay, Twitter integration. <img alt=':heart_eyes:' class='emoji' src='/static/generated/emoji/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 ,
2017-01-12 00:17:43 +01:00
type : "stream" ,
2013-06-27 22:18:03 +02:00
} ,
{
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 ,
2017-01-12 00:17:43 +01:00
type : "stream" ,
2013-06-27 22:18:03 +02:00
} ,
{
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 ,
2017-01-12 00:17:43 +01:00
type : "stream" ,
2013-06-27 22:18:03 +02:00
} ,
{
id : 8 ,
2017-06-09 10:30:24 +02:00
content : "<p><img alt=':clock1130:' class='emoji' src='/static/generated/emoji/images/emoji/clock1130.png' title='clock1130'> Reminder: engineering meeting in 1 hour. <img alt=':clock1130:' class='emoji' src='/static/generated/emoji/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 ,
2017-01-12 00:17:43 +01:00
type : "stream" ,
2014-01-14 23:05:35 +01:00
} ,
{
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 ,
2017-01-12 00:17:43 +01:00
type : "stream" ,
2014-01-14 23:05:35 +01:00
} ,
{
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 ,
2017-01-12 00:17:43 +01:00
type : "stream" ,
2014-01-14 23:05:35 +01:00
} ,
{
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 ,
2017-01-12 00:17:43 +01:00
type : "stream" ,
2014-01-14 23:05:35 +01:00
} ,
{
id : 12 ,
2017-06-09 10:30:24 +02:00
content : "<p>No problem, less work for me. <img alt=':smile:' class='emoji' src='/static/generated/emoji/images/emoji/smile.png' title='smile'></p>" ,
2014-01-14 23:05:35 +01:00
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 ,
2017-01-12 00:17:43 +01:00
type : "stream" ,
} ,
2013-06-27 22:18:03 +02:00
] ;
2014-01-14 23:53:35 +01:00
function send _delayed _stream _message ( stream , topic , content , delay ) {
2016-12-03 03:08:47 +01:00
var data = { type : JSON . stringify ( 'stream' ) ,
recipient : JSON . stringify ( stream ) ,
topic : JSON . stringify ( topic ) ,
content : JSON . stringify ( content ) } ;
2014-01-14 23:53:35 +01:00
setTimeout ( function ( ) {
$ . ajax ( {
dataType : 'json' ,
url : '/json/tutorial_send_message' ,
type : 'POST' ,
2017-01-12 00:17:43 +01:00
data : data ,
2014-01-14 23:53:35 +01:00
} ) ;
} , delay * 1000 ) ; // delay is in seconds.
}
2013-07-02 19:58:44 +02:00
function disable _event _handlers ( ) {
2016-12-03 03:39:03 +01:00
$ ( 'body' ) . css ( { overflow : 'hidden' } ) ; // prevents scrolling the feed
2013-07-30 00:35:44 +02:00
_ . each ( [ "keydown" , "keyup" , "keypress" , "scroll" ] , function ( event _name ) {
2016-06-23 15:19:47 +02:00
var existing _events = $ . _data ( document , "events" ) [ event _name ] ;
2013-07-02 19:58:44 +02:00
if ( existing _events === undefined ) {
existing _events = [ ] ;
}
event _handlers [ event _name ] = existing _events ;
2016-06-23 15:19:47 +02:00
$ . _data ( document , "events" ) [ event _name ] = [ ] ;
2013-07-02 19:58:44 +02:00
} ) ;
}
function enable _event _handlers ( ) {
2016-12-03 03:39:03 +01:00
$ ( 'body' ) . css ( { overflow : 'auto' } ) ; // enables scrolling the feed
2013-07-30 00:35:44 +02:00
_ . each ( [ "keydown" , "keyup" , "keypress" , "scroll" ] , function ( event _name ) {
2016-06-23 15:19:47 +02:00
$ . _data ( document , "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' ,
2015-11-25 07:39:30 +01:00
data : { status : JSON . stringify ( status ) } ,
2017-01-12 00:17:43 +01:00
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 } ) ;
}
2014-02-05 16:55:24 +01:00
function message _groups _in _viewport ( ) {
2017-03-10 23:48:51 +01:00
var vp = message _viewport . message _viewport _info ( ) ;
2013-06-27 22:18:28 +02:00
var top = vp . visible _top ;
var height = vp . visible _height ;
2014-02-05 16:55:24 +01:00
var last _group = rows . get _message _recipient _row ( rows . last _visible ( ) ) ;
2013-06-27 22:18:28 +02:00
2014-02-05 16:55:24 +01:00
return $ . merge ( last _group , last _group . prevAll ( ) ) . filter ( function ( idx , row ) {
2013-06-27 22:18:28 +02:00
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 } ) ,
2014-07-16 22:43:14 +02:00
content : templates . render ( content _template , { placement : placement ,
page _params : page _params } ) ,
2017-01-12 00:17:43 +01:00
trigger : "manual" ,
2013-06-27 22:18:28 +02:00
} ) ;
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 ) ;
} ;
2014-03-14 16:37:33 +01:00
function update _popover _info ( popover _func ) {
current _popover _info = popover _func ;
}
2016-06-04 01:12:24 +02:00
function finale ( skip ) {
2013-06-27 22:18:28 +02:00
var finale _modal = $ ( "#tutorial-finale" ) ;
2016-06-04 01:12:24 +02:00
if ( skip ) {
2013-06-27 22:18:28 +02:00
finale _modal . modal ( "hide" ) ;
$ ( ".screen" ) . css ( { opacity : 0.0 , width : 0 , height : 0 } ) ;
2016-06-04 01:12:24 +02:00
} else {
$ ( ".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 } ) ;
} ) . 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 ( ) ;
2014-03-14 16:37:33 +01:00
update _popover _info ( undefined ) ;
2013-06-27 22:18:28 +02:00
// 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 ;
2014-03-13 16:47:25 +01:00
$ ( '#first_run_message' ) . show ( ) ;
2013-06-27 22:18:28 +02:00
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
2017-06-14 19:55:28 +02:00
var sender _bot = "welcome-bot@zulip.com" ;
narrow . by ( 'pm-with' , sender _bot , { select _first _unread : true , trigger : 'sidebar' } ) ;
compose _actions . cancel ( ) ;
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 ;
2017-05-13 20:54:53 +02:00
if ( stream _data . name _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 ) ;
} ) ;
}
2017-05-13 20:54:53 +02:00
if ( stream _data . notifications _in _home _view ( ) ) {
2014-01-22 22:42:13 +01:00
send _delayed _stream _message ( page _params . notifications _stream , "welcome" , "Practice sending sending some messages here, or starting a new topic." , 15 ) ;
2017-02-21 20:44:43 +01:00
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-22 22:42:13 +01:00
}
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
}
2017-05-13 20:54:53 +02:00
if ( stream _data . name _in _home _view ( "social" ) ) {
2015-12-28 22:35:16 +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](/static/images/cute/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 box _first _message ( ) {
var spotlight _message = rows . first _visible ( ) ;
2014-02-05 16:55:24 +01:00
var bar = rows . get _message _recipient _row ( spotlight _message ) ;
var header = bar . find ( '.message_header' ) ;
2014-02-04 20:37:37 +01:00
var x = bar . offset ( ) . left ;
var y = bar . offset ( ) . top ;
2014-02-05 16:55:24 +01:00
var message _height = header . height ( ) + spotlight _message . height ( ) ;
2014-02-04 20:37:37 +01:00
var message _width = bar . width ( ) ;
box ( x , y , message _width , message _height ) ;
}
function box _messagelist ( ) {
2014-02-05 16:55:24 +01:00
var spotlight _message _row = rows . get _message _recipient _row ( rows . first _visible ( ) ) ;
var x = spotlight _message _row . offset ( ) . left ;
var y = spotlight _message _row . offset ( ) . top ;
2014-02-04 20:37:37 +01:00
var height = 0 ;
2014-02-05 16:55:24 +01:00
_ . each ( message _groups _in _viewport ( ) , function ( row ) {
2014-02-04 20:37:37 +01:00
height += $ ( row ) . height ( ) ;
} ) ;
2014-02-05 16:55:24 +01:00
box ( x , y , spotlight _message _row . width ( ) , height ) ;
2014-02-04 20:37:37 +01:00
}
2013-06-27 22:18:28 +02:00
function reply ( ) {
2014-02-05 16:55:24 +01:00
var spotlight _message = rows . get _message _recipient _row ( rows . first _visible ( ) ) ;
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" ) ;
2016-06-04 01:12:24 +02:00
finale ( false ) ;
2014-01-07 21:07:15 +01:00
} ) . focus ( ) ;
2013-06-27 22:18:28 +02:00
}
function home ( ) {
2014-02-05 16:55:24 +01:00
var spotlight _message = rows . get _message _recipient _header ( rows . first _visible ( ) ) ;
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 ( ) ;
2014-02-05 16:55:24 +01:00
var bar = rows . get _message _recipient _header ( spotlight _message ) ;
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 ( ) {
2014-02-05 16:55:24 +01:00
var bar = rows . get _message _recipient _header ( rows . first _visible ( ) ) ;
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 ( ) ;
2014-02-05 16:55:24 +01:00
var bar = rows . get _message _recipient _header ( spotlight _message ) ;
2014-02-04 20:37:37 +01:00
box _first _message ( ) ;
2017-02-21 20:44:43 +01:00
create _and _show _popover ( bar , maybe _tweak _placement ( "left" ) , "Welcome to Zulip" ,
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 ( ) ;
2016-06-04 01:12:24 +02:00
$ ( "#tutorial-message-skip" ) . click ( function ( ) {
bar . popover ( "destroy" ) ;
finale ( true ) ;
} ) ;
2013-06-27 22:18:28 +02:00
}
2013-06-20 18:06:31 +02:00
exports . start = function ( ) {
2017-05-27 15:40:54 +02:00
if ( overlays . is _active ( ) ) {
2017-03-18 21:35:35 +01:00
ui _util . change _tab _to ( '#home' ) ;
2013-07-02 22:13:52 +02:00
}
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 ;
}