2011-12-04 16:33:56 +01:00
/ * *
* This code is mostly from the old Etherpad . Please help us to comment this code .
* This helps other people to understand this code better and helps them to improve it .
* TL ; DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
* /
2011-03-26 14:10:41 +01:00
/ * *
2011-08-11 16:26:41 +02:00
* Copyright 2009 Google Inc . , 2011 Peter 'Pita' Martischka ( Primary Technology Ltd )
2011-07-07 19:59:34 +02:00
*
2011-03-26 14:10:41 +01:00
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
2011-07-07 19:59:34 +02:00
*
2011-03-26 14:10:41 +01:00
* http : //www.apache.org/licenses/LICENSE-2.0
2011-07-07 19:59:34 +02:00
*
2011-03-26 14:10:41 +01:00
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS-IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
/* global $, window */
var socket ;
2012-01-16 03:22:28 +01:00
2012-01-29 00:26:39 +01:00
// These jQuery things should create local references, but for now `require()`
// assigns to the global `$` and augments it with plugins.
2012-03-07 02:27:03 +01:00
require ( './jquery' ) ;
require ( './farbtastic' ) ;
require ( './excanvas' ) ;
JSON = require ( './json2' ) ;
require ( './undo-xpopup' ) ;
2012-01-29 00:26:39 +01:00
2012-03-07 02:27:03 +01:00
var chat = require ( './chat' ) . chat ;
var getCollabClient = require ( './collab_client' ) . getCollabClient ;
var padconnectionstatus = require ( './pad_connectionstatus' ) . padconnectionstatus ;
var padcookie = require ( './pad_cookie' ) . padcookie ;
var paddocbar = require ( './pad_docbar' ) . paddocbar ;
var padeditbar = require ( './pad_editbar' ) . padeditbar ;
var padeditor = require ( './pad_editor' ) . padeditor ;
var padimpexp = require ( './pad_impexp' ) . padimpexp ;
var padmodals = require ( './pad_modals' ) . padmodals ;
2012-04-01 13:27:38 +02:00
var padsavedrevs = require ( './pad_savedrevs' ) ;
2012-03-07 02:27:03 +01:00
var paduserlist = require ( './pad_userlist' ) . paduserlist ;
var padutils = require ( './pad_utils' ) . padutils ;
2012-01-16 05:16:11 +01:00
2012-03-07 02:27:03 +01:00
var createCookie = require ( './pad_utils' ) . createCookie ;
var readCookie = require ( './pad_utils' ) . readCookie ;
var randomString = require ( './pad_utils' ) . randomString ;
2011-03-26 14:10:41 +01:00
2012-03-27 22:23:55 +02:00
var hooks = require ( './pluginfw/hooks' ) ;
2011-08-15 19:26:20 +02:00
function createCookie ( name , value , days , path )
2011-07-07 19:59:34 +02:00
{
if ( days )
{
var date = new Date ( ) ;
date . setTime ( date . getTime ( ) + ( days * 24 * 60 * 60 * 1000 ) ) ;
var expires = "; expires=" + date . toGMTString ( ) ;
}
else var expires = "" ;
2011-08-15 19:26:20 +02:00
if ( ! path )
path = "/" ;
document . cookie = name + "=" + value + expires + "; path=" + path ;
2011-03-26 14:10:41 +01:00
}
2011-07-07 19:59:34 +02:00
function readCookie ( name )
{
var nameEQ = name + "=" ;
var ca = document . cookie . split ( ';' ) ;
for ( var i = 0 ; i < ca . length ; i ++ )
{
var c = ca [ i ] ;
while ( c . charAt ( 0 ) == ' ' ) c = c . substring ( 1 , c . length ) ;
if ( c . indexOf ( nameEQ ) == 0 ) return c . substring ( nameEQ . length , c . length ) ;
}
return null ;
2011-03-26 14:10:41 +01:00
}
2011-07-07 19:59:34 +02:00
function randomString ( )
{
2011-07-31 12:48:06 +02:00
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ;
2011-07-07 19:59:34 +02:00
var string _length = 20 ;
var randomstring = '' ;
for ( var i = 0 ; i < string _length ; i ++ )
{
var rnum = Math . floor ( Math . random ( ) * chars . length ) ;
randomstring += chars . substring ( rnum , rnum + 1 ) ;
}
return "t." + randomstring ;
2011-03-26 14:10:41 +01:00
}
2011-08-12 17:00:09 +02:00
function getParams ( )
{
2011-11-16 00:36:26 +01:00
var params = getUrlVars ( )
var showControls = params [ "showControls" ] ;
var showChat = params [ "showChat" ] ;
var userName = params [ "userName" ] ;
var showLineNumbers = params [ "showLineNumbers" ] ;
var useMonospaceFont = params [ "useMonospaceFont" ] ;
var IsnoColors = params [ "noColors" ] ;
2011-12-04 16:33:56 +01:00
var hideQRCode = params [ "hideQRCode" ] ;
2011-12-04 19:55:35 +01:00
var rtl = params [ "rtl" ] ;
2012-02-05 15:23:01 +01:00
var alwaysShowChat = params [ "alwaysShowChat" ] ;
2011-09-04 14:48:53 +02:00
if ( IsnoColors )
{
if ( IsnoColors == "true" )
{
2012-01-16 03:22:28 +01:00
settings . noColors = true ;
2011-12-04 16:29:34 +01:00
$ ( '#clearAuthorship' ) . hide ( ) ;
2011-09-04 14:48:53 +02:00
}
}
2011-08-12 17:00:09 +02:00
if ( showControls )
{
if ( showControls == "false" )
{
$ ( '#editbar' ) . hide ( ) ;
$ ( '#editorcontainer' ) . css ( { "top" : "0px" } ) ;
}
}
if ( showChat )
{
2011-08-13 19:37:44 +02:00
if ( showChat == "false" )
{
$ ( '#chaticon' ) . hide ( ) ;
}
2011-08-12 17:00:09 +02:00
}
2011-08-13 19:37:44 +02:00
if ( showLineNumbers )
{
if ( showLineNumbers == "false" )
{
2012-01-16 03:22:28 +01:00
settings . LineNumbersDisabled = true ;
2011-08-13 19:37:44 +02:00
}
}
2011-08-13 23:10:58 +02:00
if ( useMonospaceFont )
{
if ( useMonospaceFont == "true" )
{
2012-01-16 03:22:28 +01:00
settings . useMonospaceFontGlobal = true ;
2011-08-13 23:10:58 +02:00
}
}
2011-08-13 20:53:02 +02:00
if ( userName )
{
// If the username is set as a parameter we should set a global value that we can call once we have initiated the pad.
2012-02-18 18:51:39 +01:00
settings . globalUserName = decodeURIComponent ( userName ) ;
2011-08-13 20:53:02 +02:00
}
2011-12-04 16:33:56 +01:00
if ( hideQRCode )
{
$ ( '#qrcode' ) . hide ( ) ;
}
2011-12-04 19:55:35 +01:00
if ( rtl )
{
if ( rtl == "true" )
{
2012-01-16 03:22:28 +01:00
settings . rtlIsTrue = true
2011-12-04 19:55:35 +01:00
}
}
2012-02-05 15:23:01 +01:00
if ( alwaysShowChat )
{
if ( alwaysShowChat == "true" )
{
chat . stickToScreen ( ) ;
}
}
2011-08-12 17:00:09 +02:00
}
function getUrlVars ( )
{
var vars = [ ] , hash ;
var hashes = window . location . href . slice ( window . location . href . indexOf ( '?' ) + 1 ) . split ( '&' ) ;
for ( var i = 0 ; i < hashes . length ; i ++ )
{
hash = hashes [ i ] . split ( '=' ) ;
vars . push ( hash [ 0 ] ) ;
vars [ hash [ 0 ] ] = hash [ 1 ] ;
}
return vars ;
}
2011-08-15 19:26:20 +02:00
function savePassword ( )
{
//set the password cookie
createCookie ( "password" , $ ( "#passwordinput" ) . val ( ) , null , document . location . pathname ) ;
//reload
document . location = document . location ;
}
2012-02-25 18:30:59 +01:00
function ieTestXMLHTTP ( ) {
// Test for IE known XML HTTP issue
if ( $ . browser . msie && ! window . XMLHttpRequest ) {
$ ( "#editorloadingbox" ) . html ( "You do not have XML HTTP enabled in your browser. <a target='_blank' href='https://github.com/Pita/etherpad-lite/wiki/How-to-enable-native-XMLHTTP-support-in-IE'>Fix this issue</a>" ) ;
}
}
2011-03-26 14:10:41 +01:00
function handshake ( )
{
2011-07-05 20:16:45 +02:00
var loc = document . location ;
//get the correct port
var port = loc . port == "" ? ( loc . protocol == "https:" ? 443 : 80 ) : loc . port ;
//create the url
var url = loc . protocol + "//" + loc . hostname + ":" + port + "/" ;
//find out in which subfolder we are
2012-04-25 10:23:58 +02:00
var resource = exports . baseURL + "socket.io" ;
2011-07-05 20:16:45 +02:00
//connect
2012-01-17 09:43:11 +01:00
socket = pad . socket = io . connect ( url , {
2011-11-26 00:24:10 +01:00
resource : resource ,
2012-02-27 17:33:27 +01:00
'max reconnection attempts' : 3 ,
'sync disconnect on unload' : false
2011-07-07 19:59:34 +02:00
} ) ;
2011-11-26 00:24:10 +01:00
function sendClientReady ( isReconnect )
2011-07-07 19:59:34 +02:00
{
2011-07-26 17:17:02 +02:00
var padId = document . location . pathname . substring ( document . location . pathname . lastIndexOf ( "/" ) + 1 ) ;
2011-11-28 20:26:36 +01:00
padId = decodeURIComponent ( padId ) ; // unescape neccesary due to Safari and Opera interpretation of spaces
2011-08-15 16:40:38 +02:00
2011-11-26 00:24:10 +01:00
if ( ! isReconnect )
2012-01-31 15:15:36 +01:00
document . title = padId . replace ( /_+/g , ' ' ) + " | " + document . title ;
2011-07-07 19:59:34 +02:00
var token = readCookie ( "token" ) ;
if ( token == null )
{
2012-01-29 02:38:23 +01:00
token = "t." + randomString ( ) ;
2011-07-07 19:59:34 +02:00
createCookie ( "token" , token , 60 ) ;
}
2011-08-13 23:07:21 +02:00
var sessionID = readCookie ( "sessionID" ) ;
2011-08-15 19:26:20 +02:00
var password = readCookie ( "password" ) ;
2011-07-07 19:59:34 +02:00
var msg = {
"component" : "pad" ,
"type" : "CLIENT_READY" ,
"padId" : padId ,
2011-08-13 23:07:21 +02:00
"sessionID" : sessionID ,
2011-08-15 19:26:20 +02:00
"password" : password ,
2011-07-07 19:59:34 +02:00
"token" : token ,
"protocolVersion" : 2
} ;
2011-11-26 00:24:10 +01:00
//this is a reconnect, lets tell the server our revisionnumber
if ( isReconnect == true )
{
msg . client _rev = pad . collabClient . getCurrentRevisionNumber ( ) ;
msg . reconnect = true ;
}
2011-07-07 19:59:34 +02:00
socket . json . send ( msg ) ;
2011-11-26 00:24:10 +01:00
} ;
var disconnectTimeout ;
socket . once ( 'connect' , function ( ) {
sendClientReady ( false ) ;
} ) ;
socket . on ( 'reconnect' , function ( ) {
//reconnect is before the timeout, lets stop the timeout
if ( disconnectTimeout )
{
clearTimeout ( disconnectTimeout ) ;
}
pad . collabClient . setChannelState ( "CONNECTED" ) ;
sendClientReady ( true ) ;
} ) ;
2012-02-27 17:33:27 +01:00
socket . on ( 'disconnect' , function ( reason ) {
if ( reason == "booted" ) {
pad . collabClient . setChannelState ( "DISCONNECTED" ) ;
} else {
function disconnectEvent ( )
{
pad . collabClient . setChannelState ( "DISCONNECTED" , "reconnect_timeout" ) ;
}
pad . collabClient . setChannelState ( "RECONNECTING" ) ;
disconnectTimeout = setTimeout ( disconnectEvent , 10000 ) ;
2011-11-26 00:24:10 +01:00
}
2011-07-07 19:59:34 +02:00
} ) ;
var receivedClientVars = false ;
var initalized = false ;
socket . on ( 'message' , function ( obj )
{
2011-08-15 19:26:20 +02:00
//the access was not granted, give the user a message
if ( ! receivedClientVars && obj . accessStatus )
{
if ( obj . accessStatus == "deny" )
{
2011-08-21 02:33:30 +02:00
$ ( "#editorloadingbox" ) . html ( "<b>You do not have permission to access this pad</b>" ) ;
2011-08-15 19:26:20 +02:00
}
else if ( obj . accessStatus == "needPassword" )
{
$ ( "#editorloadingbox" ) . html ( "<b>You need a password to access this pad</b><br>" +
"<input id='passwordinput' type='password' name='password'>" +
2012-01-16 06:37:47 +01:00
"<button type='button' onclick=\"" + padutils . escapeHtml ( 'require(' + JSON . stringify ( module . id ) + ").savePassword()" ) + "\">ok</button>" ) ;
2011-08-15 19:26:20 +02:00
}
else if ( obj . accessStatus == "wrongPassword" )
{
$ ( "#editorloadingbox" ) . html ( "<b>You're password was wrong</b><br>" +
"<input id='passwordinput' type='password' name='password'>" +
2012-01-16 06:37:47 +01:00
"<button type='button' onclick=\"" + padutils . escapeHtml ( 'require(' + JSON . stringify ( module . id ) + ").savePassword()" ) + "\">ok</button>" ) ;
2011-08-15 19:26:20 +02:00
}
}
2011-07-07 19:59:34 +02:00
//if we haven't recieved the clientVars yet, then this message should it be
2011-08-15 19:26:20 +02:00
else if ( ! receivedClientVars )
2011-07-07 19:59:34 +02:00
{
2011-08-15 19:26:20 +02:00
//log the message
2011-07-07 19:59:34 +02:00
if ( window . console ) console . log ( obj ) ;
receivedClientVars = true ;
2011-08-15 19:26:20 +02:00
//set some client vars
2012-04-23 12:52:30 +02:00
clientVars = obj . data ;
2011-07-31 17:13:56 +02:00
clientVars . userAgent = "Anonymous" ;
clientVars . collab _client _vars . clientAgent = "Anonymous" ;
2012-04-23 16:41:41 +02:00
2011-08-15 19:26:20 +02:00
//initalize the pad
2012-01-27 06:10:41 +01:00
pad . _afterHandshake ( ) ;
2011-07-07 19:59:34 +02:00
initalized = true ;
2011-08-13 20:53:02 +02:00
2012-04-23 16:41:41 +02:00
padeditor . ace . callWithAce ( function ( ace ) {
ace . ace _setEditable ( ! clientVars . readonly ) ;
} ) ;
2011-08-13 20:53:02 +02:00
// If the LineNumbersDisabled value is set to true then we need to hide the Line Numbers
2012-01-16 03:22:28 +01:00
if ( settings . LineNumbersDisabled == true )
2011-08-13 19:37:44 +02:00
{
2011-08-13 20:53:02 +02:00
pad . changeViewOption ( 'showLineNumbers' , false ) ;
2011-08-13 19:37:44 +02:00
}
2011-09-04 14:48:53 +02:00
2012-02-27 16:24:36 +01:00
// If the noColors value is set to true then we need to hide the background colors on the ace spans
2012-01-16 03:22:28 +01:00
if ( settings . noColors == true )
2011-09-04 14:48:53 +02:00
{
pad . changeViewOption ( 'noColors' , true ) ;
}
2011-12-04 19:55:35 +01:00
2012-01-16 03:22:28 +01:00
if ( settings . rtlIsTrue == true )
2011-12-04 19:55:35 +01:00
{
pad . changeViewOption ( 'rtl' , true ) ;
}
2011-09-04 14:48:53 +02:00
2011-08-13 23:10:58 +02:00
// If the Monospacefont value is set to true then change it to monospace.
2012-01-16 03:22:28 +01:00
if ( settings . useMonospaceFontGlobal == true )
2011-08-13 23:10:58 +02:00
{
pad . changeViewOption ( 'useMonospaceFont' , true ) ;
}
2011-08-13 20:53:02 +02:00
// if the globalUserName value is set we need to tell the server and the client about the new authorname
2012-01-16 03:22:28 +01:00
if ( settings . globalUserName !== false )
2011-08-13 20:53:02 +02:00
{
2012-01-16 03:22:28 +01:00
pad . notifyChangeName ( settings . globalUserName ) ; // Notifies the server
pad . myUserInfo . name = settings . globalUserName ;
$ ( '#myusernameedit' ) . attr ( { "value" : settings . globalUserName } ) ; // Updates the current users UI
2011-08-13 20:53:02 +02:00
}
2011-07-07 19:59:34 +02:00
}
//This handles every Message after the clientVars
else
{
2011-08-16 21:02:30 +02:00
//this message advices the client to disconnect
2011-07-07 19:59:34 +02:00
if ( obj . disconnect )
2011-03-26 14:10:41 +01:00
{
2012-04-23 13:29:27 +02:00
console . warn ( "FORCED TO DISCONNECT" ) ;
console . warn ( obj ) ;
2011-08-16 21:02:30 +02:00
padconnectionstatus . disconnected ( obj . disconnect ) ;
2011-07-07 19:59:34 +02:00
socket . disconnect ( ) ;
return ;
2011-03-26 14:10:41 +01:00
}
else
{
2011-07-07 19:59:34 +02:00
pad . collabClient . handleMessageFromServer ( obj ) ;
2011-03-26 14:10:41 +01:00
}
2011-07-07 19:59:34 +02:00
}
} ) ;
2011-08-20 19:22:10 +02:00
// Bind the colorpicker
var fb = $ ( '#colorpicker' ) . farbtastic ( { callback : '#mycolorpickerpreview' , width : 220 } ) ;
2011-03-26 14:10:41 +01:00
}
var pad = {
// don't access these directly from outside this file, except
// for debugging
collabClient : null ,
myUserInfo : null ,
diagnosticInfo : { } ,
initTime : 0 ,
2011-07-14 17:15:38 +02:00
clientTimeOffset : null ,
2011-03-26 14:10:41 +01:00
preloadedImages : false ,
padOptions : { } ,
// these don't require init; clientVars should all go through here
2011-07-07 19:59:34 +02:00
getPadId : function ( )
{
return clientVars . padId ;
} ,
getClientIp : function ( )
{
return clientVars . clientIp ;
} ,
getIsProPad : function ( )
{
return clientVars . isProPad ;
} ,
getColorPalette : function ( )
{
return clientVars . colorPalette ;
} ,
getDisplayUserAgent : function ( )
{
2011-03-26 14:10:41 +01:00
return padutils . uaDisplay ( clientVars . userAgent ) ;
} ,
2011-07-07 19:59:34 +02:00
getIsDebugEnabled : function ( )
{
return clientVars . debugEnabled ;
} ,
getPrivilege : function ( name )
{
return clientVars . accountPrivs [ name ] ;
} ,
getUserIsGuest : function ( )
{
return clientVars . userIsGuest ;
} ,
getUserId : function ( )
{
return pad . myUserInfo . userId ;
} ,
getUserName : function ( )
{
return pad . myUserInfo . name ;
} ,
sendClientMessage : function ( msg )
{
2011-03-26 14:10:41 +01:00
pad . collabClient . sendClientMessage ( msg ) ;
} ,
2011-07-07 19:59:34 +02:00
init : function ( )
2012-01-27 06:10:41 +01:00
{
2012-01-29 03:12:01 +01:00
padutils . setupGlobalExceptionHandler ( ) ;
2012-01-27 06:10:41 +01:00
$ ( document ) . ready ( function ( )
{
2012-02-25 18:30:59 +01:00
// test for XML HTTP capabiites
ieTestXMLHTTP ( ) ;
2012-02-05 00:22:25 +01:00
// start the custom js
if ( typeof customStart == "function" ) customStart ( ) ;
2012-01-27 06:10:41 +01:00
getParams ( ) ;
handshake ( ) ;
} ) ;
} ,
_afterHandshake : function ( )
2011-07-07 19:59:34 +02:00
{
2011-07-14 17:15:38 +02:00
pad . clientTimeOffset = new Date ( ) . getTime ( ) - clientVars . serverTimestamp ;
//initialize the chat
2012-01-16 06:05:19 +01:00
chat . init ( this ) ;
2011-03-26 14:10:41 +01:00
pad . initTime = + ( new Date ( ) ) ;
pad . padOptions = clientVars . initialOptions ;
2011-07-07 19:59:34 +02:00
if ( ( ! $ . browser . msie ) && ( ! ( $ . browser . mozilla && $ . browser . version . indexOf ( "1.8." ) == 0 ) ) )
{
2011-03-26 14:10:41 +01:00
document . domain = document . domain ; // for comet
}
// for IE
2011-07-07 19:59:34 +02:00
if ( $ . browser . msie )
{
try
{
2011-03-26 14:10:41 +01:00
doc . execCommand ( "BackgroundImageCache" , false , true ) ;
2011-07-07 19:59:34 +02:00
}
catch ( e )
{ }
2011-03-26 14:10:41 +01:00
}
// order of inits is important here:
2012-01-27 06:02:58 +01:00
padcookie . init ( clientVars . cookiePrefsToSet , this ) ;
2012-02-25 20:35:49 +01:00
2011-03-26 14:10:41 +01:00
$ ( "#widthprefcheck" ) . click ( pad . toggleWidthPref ) ;
2012-01-28 23:24:14 +01:00
// $("#sidebarcheck").click(pad.togglewSidebar);
2011-03-26 14:10:41 +01:00
pad . myUserInfo = {
userId : clientVars . userId ,
name : clientVars . userName ,
ip : pad . getClientIp ( ) ,
colorId : clientVars . userColor ,
userAgent : pad . getDisplayUserAgent ( )
} ;
2011-08-20 19:22:10 +02:00
2011-07-07 19:59:34 +02:00
if ( clientVars . specialKey )
{
2011-03-26 14:10:41 +01:00
pad . myUserInfo . specialKey = clientVars . specialKey ;
2011-07-07 19:59:34 +02:00
if ( clientVars . specialKeyTranslation )
{
$ ( "#specialkeyarea" ) . html ( "mode: " + String ( clientVars . specialKeyTranslation ) . toUpperCase ( ) ) ;
2011-03-26 14:10:41 +01:00
}
}
2011-07-07 19:59:34 +02:00
paddocbar . init (
{
isTitleEditable : pad . getIsProPad ( ) ,
initialTitle : clientVars . initialTitle ,
initialPassword : clientVars . initialPassword ,
guestPolicy : pad . padOptions . guestPolicy
2012-01-27 06:02:58 +01:00
} , this ) ;
padimpexp . init ( this ) ;
2012-02-29 20:40:14 +01:00
padsavedrevs . init ( this ) ;
2011-03-26 14:10:41 +01:00
2012-01-27 06:02:58 +01:00
padeditor . init ( postAceInit , pad . padOptions . view || { } , this ) ;
2011-03-26 14:10:41 +01:00
2012-01-27 06:02:58 +01:00
paduserlist . init ( pad . myUserInfo , this ) ;
2011-07-07 19:59:34 +02:00
// padchat.init(clientVars.chatHistory, pad.myUserInfo);
2011-03-26 14:10:41 +01:00
padconnectionstatus . init ( ) ;
2012-01-27 06:02:58 +01:00
padmodals . init ( this ) ;
2011-03-26 14:10:41 +01:00
2011-07-07 19:59:34 +02:00
pad . collabClient = getCollabClient ( padeditor . ace , clientVars . collab _client _vars , pad . myUserInfo , {
colorPalette : pad . getColorPalette ( )
2012-01-17 09:43:11 +01:00
} , pad ) ;
2011-03-26 14:10:41 +01:00
pad . collabClient . setOnUserJoin ( pad . handleUserJoin ) ;
pad . collabClient . setOnUpdateUserInfo ( pad . handleUserUpdate ) ;
pad . collabClient . setOnUserLeave ( pad . handleUserLeave ) ;
pad . collabClient . setOnClientMessage ( pad . handleClientMessage ) ;
pad . collabClient . setOnServerMessage ( pad . handleServerMessage ) ;
pad . collabClient . setOnChannelStateChange ( pad . handleChannelStateChange ) ;
pad . collabClient . setOnInternalAction ( pad . handleCollabAction ) ;
2011-07-07 19:59:34 +02:00
function postAceInit ( )
{
2011-03-26 14:10:41 +01:00
padeditbar . init ( ) ;
2011-07-07 19:59:34 +02:00
setTimeout ( function ( )
{
padeditor . ace . focus ( ) ;
} , 0 ) ;
2012-02-25 20:35:49 +01:00
if ( padcookie . getPref ( "chatAlwaysVisible" ) ) { // if we have a cookie for always showing chat then show it
chat . stickToScreen ( true ) ; // stick it to the screen
$ ( '#options-stickychat' ) . prop ( "checked" , true ) ; // set the checkbox to on
}
2012-02-27 16:24:36 +01:00
if ( padcookie . getPref ( "showAuthorshipColors" ) == false ) {
pad . changeViewOption ( 'showAuthorColors' , false ) ;
}
2012-04-07 01:06:29 +02:00
hooks . aCallAll ( "postAceInit" , { ace : padeditor . ace } ) ;
2011-03-26 14:10:41 +01:00
}
} ,
2011-07-07 19:59:34 +02:00
dispose : function ( )
{
2011-03-26 14:10:41 +01:00
padeditor . dispose ( ) ;
} ,
2011-07-07 19:59:34 +02:00
notifyChangeName : function ( newName )
{
2011-03-26 14:10:41 +01:00
pad . myUserInfo . name = newName ;
pad . collabClient . updateUserInfo ( pad . myUserInfo ) ;
2011-03-27 12:06:16 +02:00
//padchat.handleUserJoinOrUpdate(pad.myUserInfo);
2011-03-26 14:10:41 +01:00
} ,
2011-07-07 19:59:34 +02:00
notifyChangeColor : function ( newColorId )
{
2011-03-26 14:10:41 +01:00
pad . myUserInfo . colorId = newColorId ;
pad . collabClient . updateUserInfo ( pad . myUserInfo ) ;
2011-03-27 12:06:16 +02:00
//padchat.handleUserJoinOrUpdate(pad.myUserInfo);
2011-03-26 14:10:41 +01:00
} ,
2011-07-07 19:59:34 +02:00
notifyChangeTitle : function ( newTitle )
{
pad . collabClient . sendClientMessage (
{
2011-03-26 14:10:41 +01:00
type : 'padtitle' ,
title : newTitle ,
changedBy : pad . myUserInfo . name || "unnamed"
} ) ;
} ,
2011-07-07 19:59:34 +02:00
notifyChangePassword : function ( newPass )
{
pad . collabClient . sendClientMessage (
{
2011-03-26 14:10:41 +01:00
type : 'padpassword' ,
password : newPass ,
changedBy : pad . myUserInfo . name || "unnamed"
} ) ;
} ,
2011-07-07 19:59:34 +02:00
changePadOption : function ( key , value )
{
2011-03-26 14:10:41 +01:00
var options = { } ;
options [ key ] = value ;
pad . handleOptionsChange ( options ) ;
2011-07-07 19:59:34 +02:00
pad . collabClient . sendClientMessage (
{
2011-03-26 14:10:41 +01:00
type : 'padoptions' ,
options : options ,
changedBy : pad . myUserInfo . name || "unnamed"
} ) ;
} ,
2011-07-07 19:59:34 +02:00
changeViewOption : function ( key , value )
{
var options = {
view : { }
} ;
2011-03-26 14:10:41 +01:00
options . view [ key ] = value ;
pad . handleOptionsChange ( options ) ;
} ,
2011-07-07 19:59:34 +02:00
handleOptionsChange : function ( opts )
{
2011-03-26 14:10:41 +01:00
// opts object is a full set of options or just
// some options to change
2011-07-07 19:59:34 +02:00
if ( opts . view )
{
if ( ! pad . padOptions . view )
{
2011-03-26 14:10:41 +01:00
pad . padOptions . view = { } ;
}
2011-07-07 19:59:34 +02:00
for ( var k in opts . view )
{
2011-03-26 14:10:41 +01:00
pad . padOptions . view [ k ] = opts . view [ k ] ;
}
padeditor . setViewOptions ( pad . padOptions . view ) ;
}
2011-07-07 19:59:34 +02:00
if ( opts . guestPolicy )
{
2011-03-26 14:10:41 +01:00
// order important here
pad . padOptions . guestPolicy = opts . guestPolicy ;
paddocbar . setGuestPolicy ( opts . guestPolicy ) ;
}
} ,
2011-07-07 19:59:34 +02:00
getPadOptions : function ( )
{
2011-03-26 14:10:41 +01:00
// caller shouldn't mutate the object
return pad . padOptions ;
} ,
2011-07-07 19:59:34 +02:00
isPadPublic : function ( )
{
return ( ! pad . getIsProPad ( ) ) || ( pad . getPadOptions ( ) . guestPolicy == 'allow' ) ;
2011-03-26 14:10:41 +01:00
} ,
2011-07-07 19:59:34 +02:00
suggestUserName : function ( userId , name )
{
pad . collabClient . sendClientMessage (
{
2011-03-26 14:10:41 +01:00
type : 'suggestUserName' ,
unnamedId : userId ,
newName : name
} ) ;
} ,
2011-07-07 19:59:34 +02:00
handleUserJoin : function ( userInfo )
{
2011-03-26 14:10:41 +01:00
paduserlist . userJoinOrUpdate ( userInfo ) ;
2011-03-27 12:06:16 +02:00
//padchat.handleUserJoinOrUpdate(userInfo);
2011-03-26 14:10:41 +01:00
} ,
2011-07-07 19:59:34 +02:00
handleUserUpdate : function ( userInfo )
{
2011-03-26 14:10:41 +01:00
paduserlist . userJoinOrUpdate ( userInfo ) ;
2011-03-27 12:06:16 +02:00
//padchat.handleUserJoinOrUpdate(userInfo);
2011-03-26 14:10:41 +01:00
} ,
2011-07-07 19:59:34 +02:00
handleUserLeave : function ( userInfo )
{
2011-03-26 14:10:41 +01:00
paduserlist . userLeave ( userInfo ) ;
2011-03-27 12:06:16 +02:00
//padchat.handleUserLeave(userInfo);
2011-03-26 14:10:41 +01:00
} ,
2011-07-07 19:59:34 +02:00
handleClientMessage : function ( msg )
{
if ( msg . type == 'suggestUserName' )
{
if ( msg . unnamedId == pad . myUserInfo . userId && msg . newName && ! pad . myUserInfo . name )
{
2011-03-26 14:10:41 +01:00
pad . notifyChangeName ( msg . newName ) ;
paduserlist . setMyUserInfo ( pad . myUserInfo ) ;
}
}
2011-07-07 19:59:34 +02:00
else if ( msg . type == 'chat' )
{
2011-03-27 12:06:16 +02:00
//padchat.receiveChat(msg);
2011-03-26 14:10:41 +01:00
}
2011-07-07 19:59:34 +02:00
else if ( msg . type == 'padtitle' )
{
2011-03-26 14:10:41 +01:00
paddocbar . changeTitle ( msg . title ) ;
}
2011-07-07 19:59:34 +02:00
else if ( msg . type == 'padpassword' )
{
2011-03-26 14:10:41 +01:00
paddocbar . changePassword ( msg . password ) ;
}
2011-07-07 19:59:34 +02:00
else if ( msg . type == 'newRevisionList' )
{
2011-03-26 14:10:41 +01:00
padsavedrevs . newRevisionList ( msg . revisionList ) ;
}
2011-07-07 19:59:34 +02:00
else if ( msg . type == 'revisionLabel' )
{
2011-03-26 14:10:41 +01:00
padsavedrevs . newRevisionList ( msg . revisionList ) ;
}
2011-07-07 19:59:34 +02:00
else if ( msg . type == 'padoptions' )
{
2011-03-26 14:10:41 +01:00
var opts = msg . options ;
pad . handleOptionsChange ( opts ) ;
}
2011-07-07 19:59:34 +02:00
else if ( msg . type == 'guestanswer' )
{
2011-03-26 14:10:41 +01:00
// someone answered a prompt, remove it
paduserlist . removeGuestPrompt ( msg . guestId ) ;
}
} ,
2011-07-07 19:59:34 +02:00
editbarClick : function ( cmd )
{
if ( padeditbar )
{
2011-03-26 14:10:41 +01:00
padeditbar . toolbarClick ( cmd ) ;
}
} ,
2011-07-07 19:59:34 +02:00
dmesg : function ( m )
{
if ( pad . getIsDebugEnabled ( ) )
{
2011-03-26 14:10:41 +01:00
var djs = $ ( '#djs' ) . get ( 0 ) ;
2011-07-07 19:59:34 +02:00
var wasAtBottom = ( djs . scrollTop - ( djs . scrollHeight - $ ( djs ) . height ( ) ) >= - 20 ) ;
$ ( '#djs' ) . append ( '<p>' + m + '</p>' ) ;
if ( wasAtBottom )
{
2011-03-26 14:10:41 +01:00
djs . scrollTop = djs . scrollHeight ;
}
}
} ,
2011-07-07 19:59:34 +02:00
handleServerMessage : function ( m )
{
if ( m . type == 'NOTICE' )
{
if ( m . text )
{
alertBar . displayMessage ( function ( abar )
{
abar . find ( "#servermsgdate" ) . html ( " (" + padutils . simpleDateTime ( new Date ) + ")" ) ;
2011-03-26 14:10:41 +01:00
abar . find ( "#servermsgtext" ) . html ( m . text ) ;
} ) ;
}
2011-07-07 19:59:34 +02:00
if ( m . js )
{
window [ 'ev' + 'al' ] ( m . js ) ;
2011-03-26 14:10:41 +01:00
}
}
2011-07-07 19:59:34 +02:00
else if ( m . type == 'GUEST_PROMPT' )
{
2011-03-26 14:10:41 +01:00
paduserlist . showGuestPrompt ( m . userId , m . displayName ) ;
}
} ,
2011-07-07 19:59:34 +02:00
handleChannelStateChange : function ( newState , message )
{
2011-03-26 14:10:41 +01:00
var oldFullyConnected = ! ! padconnectionstatus . isFullyConnected ( ) ;
var wasConnecting = ( padconnectionstatus . getStatus ( ) . what == 'connecting' ) ;
2011-07-07 19:59:34 +02:00
if ( newState == "CONNECTED" )
{
2011-03-26 14:10:41 +01:00
padconnectionstatus . connected ( ) ;
}
2011-07-07 19:59:34 +02:00
else if ( newState == "RECONNECTING" )
{
2011-03-26 14:10:41 +01:00
padconnectionstatus . reconnecting ( ) ;
}
2011-07-07 19:59:34 +02:00
else if ( newState == "DISCONNECTED" )
{
2011-03-26 14:10:41 +01:00
pad . diagnosticInfo . disconnectedMessage = message ;
2011-11-26 00:24:10 +01:00
pad . diagnosticInfo . padId = pad . getPadId ( ) ;
pad . diagnosticInfo . socket = { } ;
//we filter non objects from the socket object and put them in the diagnosticInfo
//this ensures we have no cyclic data - this allows us to stringify the data
for ( var i in socket . socket )
{
var value = socket . socket [ i ] ;
var type = typeof value ;
if ( type == "string" || type == "number" )
{
pad . diagnosticInfo . socket [ i ] = value ;
}
}
2011-03-26 14:10:41 +01:00
pad . asyncSendDiagnosticInfo ( ) ;
2011-07-07 19:59:34 +02:00
if ( typeof window . ajlog == "string" )
{
window . ajlog += ( "Disconnected: " + message + '\n' ) ;
}
2011-03-26 14:10:41 +01:00
padeditor . disable ( ) ;
padeditbar . disable ( ) ;
paddocbar . disable ( ) ;
padimpexp . disable ( ) ;
padconnectionstatus . disconnected ( message ) ;
}
var newFullyConnected = ! ! padconnectionstatus . isFullyConnected ( ) ;
2011-07-07 19:59:34 +02:00
if ( newFullyConnected != oldFullyConnected )
{
2011-03-26 14:10:41 +01:00
pad . handleIsFullyConnected ( newFullyConnected , wasConnecting ) ;
}
} ,
2011-07-07 19:59:34 +02:00
handleIsFullyConnected : function ( isConnected , isInitialConnect )
{
2011-03-26 14:10:41 +01:00
// load all images referenced from CSS, one at a time,
// starting one second after connection is first established.
2011-07-07 19:59:34 +02:00
if ( isConnected && ! pad . preloadedImages )
{
window . setTimeout ( function ( )
{
if ( ! pad . preloadedImages )
{
2011-03-26 14:10:41 +01:00
pad . preloadImages ( ) ;
pad . preloadedImages = true ;
}
} , 1000 ) ;
}
padsavedrevs . handleIsFullyConnected ( isConnected ) ;
2012-01-28 23:24:14 +01:00
// pad.determineSidebarVisibility(isConnected && !isInitialConnect);
pad . determineChatVisibility ( isConnected && ! isInitialConnect ) ;
2012-02-27 16:24:36 +01:00
pad . determineAuthorshipColorsVisibility ( ) ;
2012-01-28 23:24:14 +01:00
2011-07-07 19:59:34 +02:00
} ,
2012-01-28 23:24:14 +01:00
/ * d e t e r m i n e S i d e b a r V i s i b i l i t y : f u n c t i o n ( a s N o w C o n n e c t e d F e e d b a c k )
2011-07-07 19:59:34 +02:00
{
if ( pad . isFullyConnected ( ) )
{
var setSidebarVisibility = padutils . getCancellableAction ( "set-sidebar-visibility" , function ( )
{
2012-01-28 23:24:14 +01:00
// $("body").toggleClass('hidesidebar', !! padcookie.getPref('hideSidebar'));
2011-07-07 19:59:34 +02:00
} ) ;
window . setTimeout ( setSidebarVisibility , asNowConnectedFeedback ? 3000 : 0 ) ;
}
else
{
2011-03-26 14:10:41 +01:00
padutils . cancelActions ( "set-sidebar-visibility" ) ;
$ ( "body" ) . removeClass ( 'hidesidebar' ) ;
}
} ,
2012-01-28 23:24:14 +01:00
* /
determineChatVisibility : function ( asNowConnectedFeedback ) {
var chatVisCookie = padcookie . getPref ( 'chatAlwaysVisible' ) ;
if ( chatVisCookie ) { // if the cookie is set for chat always visible
chat . stickToScreen ( true ) ; // stick it to the screen
$ ( '#options-stickychat' ) . prop ( "checked" , true ) ; // set the checkbox to on
}
else {
$ ( '#options-stickychat' ) . prop ( "checked" , false ) ; // set the checkbox for off
}
} ,
2012-02-27 16:24:36 +01:00
determineAuthorshipColorsVisibility : function ( ) {
var authColCookie = padcookie . getPref ( 'showAuthorshipColors' ) ;
if ( authColCookie ) {
pad . changeViewOption ( 'showAuthorColors' , true ) ;
$ ( '#options-colorscheck' ) . prop ( "checked" , true ) ;
}
else {
$ ( '#options-colorscheck' ) . prop ( "checked" , false ) ;
}
} ,
2011-07-07 19:59:34 +02:00
handleCollabAction : function ( action )
{
if ( action == "commitPerformed" )
{
2011-03-26 14:10:41 +01:00
padeditbar . setSyncStatus ( "syncing" ) ;
}
2011-07-07 19:59:34 +02:00
else if ( action == "newlyIdle" )
{
2011-03-26 14:10:41 +01:00
padeditbar . setSyncStatus ( "done" ) ;
}
} ,
2011-07-07 19:59:34 +02:00
hideServerMessage : function ( )
{
2011-03-26 14:10:41 +01:00
alertBar . hideMessage ( ) ;
} ,
2011-07-07 19:59:34 +02:00
asyncSendDiagnosticInfo : function ( )
{
window . setTimeout ( function ( )
{
$ . ajax (
{
2011-03-26 14:10:41 +01:00
type : 'post' ,
url : '/ep/pad/connection-diagnostic-info' ,
2011-07-07 19:59:34 +02:00
data : {
diagnosticInfo : JSON . stringify ( pad . diagnosticInfo )
} ,
success : function ( )
{ } ,
error : function ( )
{ }
2011-03-26 14:10:41 +01:00
} ) ;
} , 0 ) ;
} ,
2011-07-07 19:59:34 +02:00
forceReconnect : function ( )
{
2011-03-26 14:10:41 +01:00
$ ( 'form#reconnectform input.padId' ) . val ( pad . getPadId ( ) ) ;
pad . diagnosticInfo . collabDiagnosticInfo = pad . collabClient . getDiagnosticInfo ( ) ;
$ ( 'form#reconnectform input.diagnosticInfo' ) . val ( JSON . stringify ( pad . diagnosticInfo ) ) ;
$ ( 'form#reconnectform input.missedChanges' ) . val ( JSON . stringify ( pad . collabClient . getMissedChanges ( ) ) ) ;
$ ( 'form#reconnectform' ) . submit ( ) ;
} ,
2011-07-07 19:59:34 +02:00
toggleWidthPref : function ( )
{
var newValue = ! padcookie . getPref ( 'fullWidth' ) ;
2011-03-26 14:10:41 +01:00
padcookie . setPref ( 'fullWidth' , newValue ) ;
2011-07-07 19:59:34 +02:00
$ ( "#widthprefcheck" ) . toggleClass ( 'widthprefchecked' , ! ! newValue ) . toggleClass ( 'widthprefunchecked' , ! newValue ) ;
2011-03-26 14:10:41 +01:00
pad . handleWidthChange ( ) ;
} ,
2012-01-28 23:24:14 +01:00
/ *
2011-07-07 19:59:34 +02:00
toggleSidebar : function ( )
{
var newValue = ! padcookie . getPref ( 'hideSidebar' ) ;
2011-03-26 14:10:41 +01:00
padcookie . setPref ( 'hideSidebar' , newValue ) ;
2011-07-07 19:59:34 +02:00
$ ( "#sidebarcheck" ) . toggleClass ( 'sidebarchecked' , ! newValue ) . toggleClass ( 'sidebarunchecked' , ! ! newValue ) ;
2011-03-26 14:10:41 +01:00
pad . determineSidebarVisibility ( ) ;
} ,
2012-01-28 23:24:14 +01:00
* /
2011-07-07 19:59:34 +02:00
handleWidthChange : function ( )
{
2011-03-26 14:10:41 +01:00
var isFullWidth = padcookie . getPref ( 'fullWidth' ) ;
2011-07-07 19:59:34 +02:00
if ( isFullWidth )
{
$ ( "body" ) . addClass ( 'fullwidth' ) . removeClass ( 'limwidth' ) . removeClass ( 'squish1width' ) . removeClass ( 'squish2width' ) ;
2011-03-26 14:10:41 +01:00
}
2011-07-07 19:59:34 +02:00
else
{
2011-03-26 14:10:41 +01:00
$ ( "body" ) . addClass ( 'limwidth' ) . removeClass ( 'fullwidth' ) ;
var pageWidth = $ ( window ) . width ( ) ;
2011-07-07 19:59:34 +02:00
$ ( "body" ) . toggleClass ( 'squish1width' , ( pageWidth < 912 && pageWidth > 812 ) ) . toggleClass ( 'squish2width' , ( pageWidth <= 812 ) ) ;
2011-03-26 14:10:41 +01:00
}
} ,
// this is called from code put into a frame from the server:
2011-07-07 19:59:34 +02:00
handleImportExportFrameCall : function ( callName , varargs )
{
padimpexp . handleFrameCall . call ( padimpexp , callName , Array . prototype . slice . call ( arguments , 1 ) ) ;
2011-03-26 14:10:41 +01:00
} ,
2011-07-07 19:59:34 +02:00
callWhenNotCommitting : function ( f )
{
2011-03-26 14:10:41 +01:00
pad . collabClient . callWhenNotCommitting ( f ) ;
} ,
2011-07-07 19:59:34 +02:00
getCollabRevisionNumber : function ( )
{
2011-03-26 14:10:41 +01:00
return pad . collabClient . getCurrentRevisionNumber ( ) ;
} ,
2011-07-07 19:59:34 +02:00
isFullyConnected : function ( )
{
2011-03-26 14:10:41 +01:00
return padconnectionstatus . isFullyConnected ( ) ;
} ,
2011-07-07 19:59:34 +02:00
addHistoricalAuthors : function ( data )
{
if ( ! pad . collabClient )
{
window . setTimeout ( function ( )
{
pad . addHistoricalAuthors ( data ) ;
} , 1000 ) ;
2011-03-26 14:10:41 +01:00
}
2011-07-07 19:59:34 +02:00
else
{
2011-03-26 14:10:41 +01:00
pad . collabClient . addHistoricalAuthors ( data ) ;
}
} ,
2011-07-07 19:59:34 +02:00
preloadImages : function ( )
{
2011-11-26 00:24:10 +01:00
var images = [ "../static/img/connectingbar.gif" ] ;
2011-07-07 19:59:34 +02:00
function loadNextImage ( )
{
if ( images . length == 0 )
{
2011-03-26 14:10:41 +01:00
return ;
}
var img = new Image ( ) ;
img . src = images . shift ( ) ;
2011-07-07 19:59:34 +02:00
if ( img . complete )
{
2011-03-26 14:10:41 +01:00
scheduleLoadNextImage ( ) ;
}
2011-07-07 19:59:34 +02:00
else
{
2011-03-26 14:10:41 +01:00
$ ( img ) . bind ( 'error load onreadystatechange' , scheduleLoadNextImage ) ;
}
}
2011-07-07 19:59:34 +02:00
function scheduleLoadNextImage ( )
{
2011-03-26 14:10:41 +01:00
window . setTimeout ( loadNextImage , 0 ) ;
}
scheduleLoadNextImage ( ) ;
}
} ;
2011-07-07 19:59:34 +02:00
var alertBar = ( function ( )
{
2011-03-26 14:10:41 +01:00
var animator = padutils . makeShowHideAnimator ( arriveAtAnimationState , false , 25 , 400 ) ;
2011-07-07 19:59:34 +02:00
function arriveAtAnimationState ( state )
{
if ( state == - 1 )
{
2011-03-26 14:10:41 +01:00
$ ( "#alertbar" ) . css ( 'opacity' , 0 ) . css ( 'display' , 'block' ) ;
}
2011-07-07 19:59:34 +02:00
else if ( state == 0 )
{
2011-03-26 14:10:41 +01:00
$ ( "#alertbar" ) . css ( 'opacity' , 1 ) ;
}
2011-07-07 19:59:34 +02:00
else if ( state == 1 )
{
2011-03-26 14:10:41 +01:00
$ ( "#alertbar" ) . css ( 'opacity' , 0 ) . css ( 'display' , 'none' ) ;
}
2011-07-07 19:59:34 +02:00
else if ( state < 0 )
{
$ ( "#alertbar" ) . css ( 'opacity' , state + 1 ) ;
2011-03-26 14:10:41 +01:00
}
2011-07-07 19:59:34 +02:00
else if ( state > 0 )
{
2011-03-26 14:10:41 +01:00
$ ( "#alertbar" ) . css ( 'opacity' , 1 - state ) ;
}
}
var self = {
2011-07-07 19:59:34 +02:00
displayMessage : function ( setupFunc )
{
2011-03-26 14:10:41 +01:00
animator . show ( ) ;
setupFunc ( $ ( "#alertbar" ) ) ;
} ,
2011-07-07 19:59:34 +02:00
hideMessage : function ( )
{
2011-03-26 14:10:41 +01:00
animator . hide ( ) ;
}
} ;
return self ;
} ( ) ) ;
2012-01-16 02:23:48 +01:00
2012-01-27 06:10:41 +01:00
function init ( ) {
return pad . init ( ) ;
}
2012-01-27 06:40:13 +01:00
var settings = {
LineNumbersDisabled : false
, noColors : false
, useMonospaceFontGlobal : false
, globalUserName : false
, hideQRCode : false
, rtlIsTrue : false
} ;
pad . settings = settings ;
2012-04-25 10:23:58 +02:00
exports . baseURL = '' ;
2012-01-16 02:23:48 +01:00
exports . settings = settings ;
exports . createCookie = createCookie ;
exports . readCookie = readCookie ;
exports . randomString = randomString ;
exports . getParams = getParams ;
exports . getUrlVars = getUrlVars ;
exports . savePassword = savePassword ;
exports . handshake = handshake ;
exports . pad = pad ;
2012-01-27 06:10:41 +01:00
exports . init = init ;
2012-01-16 02:23:48 +01:00
exports . alertBar = alertBar ;
2012-02-25 20:35:49 +01:00