2011-03-26 13:10:41 +00:00
/ * *
2011-08-11 15:26:41 +01:00
* Copyright 2009 Google Inc . , 2011 Peter 'Pita' Martischka ( Primary Technology Ltd )
2011-07-07 18:59:34 +01:00
*
2011-03-26 13:10:41 +00: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 18:59:34 +01:00
*
2011-03-26 13:10:41 +00:00
* http : //www.apache.org/licenses/LICENSE-2.0
2011-07-07 18:59:34 +01:00
*
2011-03-26 13:10:41 +00: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 ;
2011-08-13 18:37:44 +01:00
var LineNumbersDisabled = false ;
2011-09-04 13:48:53 +01:00
var noColors = false ;
2011-08-13 22:10:58 +01:00
var useMonospaceFontGlobal = false ;
2011-08-13 19:53:02 +01:00
var globalUserName = false ;
2011-12-04 15:33:56 +00:00
var hideQRCode = false ;
2011-03-26 13:10:41 +00:00
2011-07-07 18:59:34 +01:00
$ ( document ) . ready ( function ( )
{
2011-07-31 17:21:01 +01:00
//start the costum js
2011-08-01 12:08:18 +01:00
if ( typeof costumStart == "function" ) costumStart ( ) ;
2011-08-12 16:00:09 +01:00
getParams ( ) ;
2011-03-26 13:10:41 +00:00
handshake ( ) ;
} ) ;
2011-07-07 18:59:34 +01:00
$ ( window ) . unload ( function ( )
{
2011-03-26 13:10:41 +00:00
pad . dispose ( ) ;
} ) ;
2011-08-15 18:26:20 +01:00
function createCookie ( name , value , days , path )
2011-07-07 18:59:34 +01: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 18:26:20 +01:00
if ( ! path )
path = "/" ;
document . cookie = name + "=" + value + expires + "; path=" + path ;
2011-03-26 13:10:41 +00:00
}
2011-07-07 18:59:34 +01: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 13:10:41 +00:00
}
2011-07-07 18:59:34 +01:00
function randomString ( )
{
2011-07-31 11:48:06 +01:00
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ;
2011-07-07 18:59:34 +01:00
var string _length = 20 ;
var randomstring = '' ;
for ( var i = 0 ; i < string _length ; i ++ )
{
var rnum = Math . floor ( Math . random ( ) * chars . length ) ;
2011-11-09 23:53:00 +01:00
randomstring += chars [ rnum ] ;
2011-07-07 18:59:34 +01:00
}
return "t." + randomstring ;
2011-03-26 13:10:41 +00:00
}
2011-08-12 16:00:09 +01:00
function getParams ( )
{
2011-11-15 21:36:26 -02: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 15:33:56 +00:00
var hideQRCode = params [ "hideQRCode" ] ;
2011-09-04 13:48:53 +01:00
if ( IsnoColors )
{
if ( IsnoColors == "true" )
{
noColors = true ;
2011-12-04 15:29:34 +00:00
$ ( '#clearAuthorship' ) . hide ( ) ;
2011-09-04 13:48:53 +01:00
}
}
2011-08-12 16:00:09 +01:00
if ( showControls )
{
if ( showControls == "false" )
{
$ ( '#editbar' ) . hide ( ) ;
$ ( '#editorcontainer' ) . css ( { "top" : "0px" } ) ;
}
}
if ( showChat )
{
2011-08-13 18:37:44 +01:00
if ( showChat == "false" )
{
$ ( '#chaticon' ) . hide ( ) ;
}
2011-08-12 16:00:09 +01:00
}
2011-08-13 18:37:44 +01:00
if ( showLineNumbers )
{
if ( showLineNumbers == "false" )
{
LineNumbersDisabled = true ;
}
}
2011-08-13 22:10:58 +01:00
if ( useMonospaceFont )
{
if ( useMonospaceFont == "true" )
{
useMonospaceFontGlobal = true ;
}
}
2011-08-13 19:53:02 +01: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.
2011-11-15 21:33:43 -02:00
globalUserName = unescape ( userName ) ;
2011-08-13 19:53:02 +01:00
}
2011-12-04 15:33:56 +00:00
if ( hideQRCode )
{
$ ( '#qrcode' ) . hide ( ) ;
}
2011-08-12 16:00:09 +01: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-11-09 23:53:00 +01:00
function hash ( password , salt )
{
return sha512 ( password + salt ) + "$" + salt ;
}
/ * G e n e r a t e t h e " t i m e d h a s h " u s e d t o g e t a c c e s s .
* The password is hashed with the database ' s salt , afterwards it is hashed again with a timestamp a few days in the future as "salt" .
* The server checks the two hashe ' s equality as usual , but also checks whether this timestamp is still in the future ( grant access )
* or if it has passed ( deny access ) . This provides an saved - password expiry mechanism which is a ) independent of the browser ' s cookie
* retention and b ) provides some level of security against "cookie stealing" ( be it by xss or otherwise ) : If Eve steals a cookie , she
* does "only" get a timed - hash lifetime access to the pad , but * not * the actual password .
* /
function savePassword ( pwsalt )
2011-08-15 18:26:20 +01:00
{
//set the password cookie
2011-11-09 23:53:00 +01:00
createCookie ( "password" , hash ( hash ( $ ( "#passwordinput" ) . val ( ) , pwsalt ) , new Date ( ) . getTime ( ) + 14 * 24 * 3600 * 1000 ) , null , document . location . pathname ) ; //FIXME some means of configuring this threshold would be really great
2011-08-15 18:26:20 +01:00
//reload
document . location = document . location ;
}
2011-03-26 13:10:41 +00: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
2011-07-07 18:59:34 +01:00
var resource = loc . pathname . substr ( 1 , loc . pathname . indexOf ( "/p/" ) ) + "socket.io" ;
2011-07-05 20:16:45 +02:00
//connect
2011-07-07 18:59:34 +01:00
socket = io . connect ( url , {
2011-11-25 15:24:10 -08:00
resource : resource ,
'max reconnection attempts' : 3
2011-07-07 18:59:34 +01:00
} ) ;
2011-11-25 15:24:10 -08:00
function sendClientReady ( isReconnect )
2011-07-07 18:59:34 +01:00
{
2011-07-26 16:17:02 +01:00
var padId = document . location . pathname . substring ( document . location . pathname . lastIndexOf ( "/" ) + 1 ) ;
2011-11-28 11:26:36 -08:00
padId = decodeURIComponent ( padId ) ; // unescape neccesary due to Safari and Opera interpretation of spaces
2011-08-15 15:40:38 +01:00
2011-11-25 15:24:10 -08:00
if ( ! isReconnect )
document . title = document . title + " | " + padId ;
2011-07-07 18:59:34 +01:00
var token = readCookie ( "token" ) ;
if ( token == null )
{
token = randomString ( ) ;
createCookie ( "token" , token , 60 ) ;
}
2011-08-13 22:07:21 +01:00
var sessionID = readCookie ( "sessionID" ) ;
2011-08-15 18:26:20 +01:00
var password = readCookie ( "password" ) ;
2011-07-07 18:59:34 +01:00
var msg = {
"component" : "pad" ,
"type" : "CLIENT_READY" ,
"padId" : padId ,
2011-08-13 22:07:21 +01:00
"sessionID" : sessionID ,
2011-08-15 18:26:20 +01:00
"password" : password ,
2011-07-07 18:59:34 +01:00
"token" : token ,
"protocolVersion" : 2
} ;
2011-11-25 15:24:10 -08: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 18:59:34 +01:00
socket . json . send ( msg ) ;
2011-11-25 15:24:10 -08: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 ) ;
} ) ;
socket . on ( 'disconnect' , function ( ) {
function disconnectEvent ( )
{
pad . collabClient . setChannelState ( "DISCONNECTED" , "reconnect_timeout" ) ;
}
pad . collabClient . setChannelState ( "RECONNECTING" ) ;
disconnectTimeout = setTimeout ( disconnectEvent , 10000 ) ;
2011-07-07 18:59:34 +01:00
} ) ;
var receivedClientVars = false ;
var initalized = false ;
socket . on ( 'message' , function ( obj )
{
2011-08-15 18:26:20 +01:00
//the access was not granted, give the user a message
if ( ! receivedClientVars && obj . accessStatus )
{
if ( obj . accessStatus == "deny" )
{
2011-08-21 01:33:30 +01:00
$ ( "#editorloadingbox" ) . html ( "<b>You do not have permission to access this pad</b>" ) ;
2011-08-15 18:26:20 +01: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'>" +
2011-11-09 23:53:00 +01:00
"<button type='button' onclick='savePassword(" + obj . passwordSalt + ")'>ok</button>" ) ;
2011-08-15 18:26:20 +01:00
}
else if ( obj . accessStatus == "wrongPassword" )
{
2011-11-09 23:53:00 +01:00
$ ( "#editorloadingbox" ) . html ( "<b>Your password was wrong</b><br>" +
2011-08-15 18:26:20 +01:00
"<input id='passwordinput' type='password' name='password'>" +
2011-11-09 23:53:00 +01:00
"<button type='button' onclick='savePassword(" + obj . passwordSalt + ")'>ok</button>" ) ;
2011-08-15 18:26:20 +01:00
}
}
2011-07-07 18:59:34 +01:00
//if we haven't recieved the clientVars yet, then this message should it be
2011-08-15 18:26:20 +01:00
else if ( ! receivedClientVars )
2011-07-07 18:59:34 +01:00
{
2011-08-15 18:26:20 +01:00
//log the message
2011-07-07 18:59:34 +01:00
if ( window . console ) console . log ( obj ) ;
receivedClientVars = true ;
2011-08-15 18:26:20 +01:00
//set some client vars
2011-07-07 18:59:34 +01:00
clientVars = obj ;
2011-07-31 16:13:56 +01:00
clientVars . userAgent = "Anonymous" ;
clientVars . collab _client _vars . clientAgent = "Anonymous" ;
2011-07-07 18:59:34 +01:00
2011-08-15 18:26:20 +01:00
//initalize the pad
2011-07-07 18:59:34 +01:00
pad . init ( ) ;
initalized = true ;
2011-08-13 19:53:02 +01:00
// If the LineNumbersDisabled value is set to true then we need to hide the Line Numbers
2011-08-13 18:37:44 +01:00
if ( LineNumbersDisabled == true )
{
2011-08-13 19:53:02 +01:00
pad . changeViewOption ( 'showLineNumbers' , false ) ;
2011-08-13 18:37:44 +01:00
}
2011-09-04 13:48:53 +01:00
// If the noColors value is set to true then we need to hide the backround colors on the ace spans
if ( noColors == true )
{
pad . changeViewOption ( 'noColors' , true ) ;
}
2011-08-13 22:10:58 +01:00
// If the Monospacefont value is set to true then change it to monospace.
if ( useMonospaceFontGlobal == true )
{
pad . changeViewOption ( 'useMonospaceFont' , true ) ;
}
2011-08-13 19:53:02 +01:00
// if the globalUserName value is set we need to tell the server and the client about the new authorname
if ( globalUserName !== false )
{
pad . notifyChangeName ( globalUserName ) ; // Notifies the server
2011-09-02 12:51:51 -07:00
pad . myUserInfo . name = globalUserName ;
2011-08-13 19:53:02 +01:00
$ ( '#myusernameedit' ) . attr ( { "value" : globalUserName } ) ; // Updates the current users UI
}
2011-07-07 18:59:34 +01:00
}
//This handles every Message after the clientVars
else
{
2011-08-16 20:02:30 +01:00
//this message advices the client to disconnect
2011-07-07 18:59:34 +01:00
if ( obj . disconnect )
2011-03-26 13:10:41 +00:00
{
2011-08-16 20:02:30 +01:00
padconnectionstatus . disconnected ( obj . disconnect ) ;
2011-07-07 18:59:34 +01:00
socket . disconnect ( ) ;
return ;
2011-03-26 13:10:41 +00:00
}
else
{
2011-07-07 18:59:34 +01:00
pad . collabClient . handleMessageFromServer ( obj ) ;
2011-03-26 13:10:41 +00:00
}
2011-07-07 18:59:34 +01:00
}
} ) ;
2011-08-20 18:22:10 +01:00
// Bind the colorpicker
var fb = $ ( '#colorpicker' ) . farbtastic ( { callback : '#mycolorpickerpreview' , width : 220 } ) ;
2011-03-26 13:10:41 +00: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 16:15:38 +01:00
clientTimeOffset : null ,
2011-03-26 13:10:41 +00:00
preloadedImages : false ,
padOptions : { } ,
// these don't require init; clientVars should all go through here
2011-07-07 18:59:34 +01: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 13:10:41 +00:00
return padutils . uaDisplay ( clientVars . userAgent ) ;
} ,
2011-07-07 18:59:34 +01:00
getIsDebugEnabled : function ( )
{
return clientVars . debugEnabled ;
} ,
getPrivilege : function ( name )
{
return clientVars . accountPrivs [ name ] ;
} ,
getUserIsGuest : function ( )
{
return clientVars . userIsGuest ;
} ,
2011-03-26 13:10:41 +00:00
//
2011-07-07 18:59:34 +01:00
getUserId : function ( )
{
return pad . myUserInfo . userId ;
} ,
getUserName : function ( )
{
return pad . myUserInfo . name ;
} ,
sendClientMessage : function ( msg )
{
2011-03-26 13:10:41 +00:00
pad . collabClient . sendClientMessage ( msg ) ;
} ,
2011-07-07 18:59:34 +01:00
init : function ( )
{
2011-07-14 16:15:38 +01:00
pad . clientTimeOffset = new Date ( ) . getTime ( ) - clientVars . serverTimestamp ;
//initialize the chat
chat . init ( ) ;
2011-03-26 13:10:41 +00:00
pad . initTime = + ( new Date ( ) ) ;
pad . padOptions = clientVars . initialOptions ;
2011-07-07 18:59:34 +01:00
if ( ( ! $ . browser . msie ) && ( ! ( $ . browser . mozilla && $ . browser . version . indexOf ( "1.8." ) == 0 ) ) )
{
2011-03-26 13:10:41 +00:00
document . domain = document . domain ; // for comet
}
// for IE
2011-07-07 18:59:34 +01:00
if ( $ . browser . msie )
{
try
{
2011-03-26 13:10:41 +00:00
doc . execCommand ( "BackgroundImageCache" , false , true ) ;
2011-07-07 18:59:34 +01:00
}
catch ( e )
{ }
2011-03-26 13:10:41 +00:00
}
// order of inits is important here:
padcookie . init ( clientVars . cookiePrefsToSet ) ;
$ ( "#widthprefcheck" ) . click ( pad . toggleWidthPref ) ;
$ ( "#sidebarcheck" ) . click ( pad . toggleSidebar ) ;
pad . myUserInfo = {
userId : clientVars . userId ,
name : clientVars . userName ,
ip : pad . getClientIp ( ) ,
colorId : clientVars . userColor ,
userAgent : pad . getDisplayUserAgent ( )
} ;
2011-08-20 18:22:10 +01:00
2011-07-07 18:59:34 +01:00
if ( clientVars . specialKey )
{
2011-03-26 13:10:41 +00:00
pad . myUserInfo . specialKey = clientVars . specialKey ;
2011-07-07 18:59:34 +01:00
if ( clientVars . specialKeyTranslation )
{
$ ( "#specialkeyarea" ) . html ( "mode: " + String ( clientVars . specialKeyTranslation ) . toUpperCase ( ) ) ;
2011-03-26 13:10:41 +00:00
}
}
2011-07-07 18:59:34 +01:00
paddocbar . init (
{
isTitleEditable : pad . getIsProPad ( ) ,
initialTitle : clientVars . initialTitle ,
initialPassword : clientVars . initialPassword ,
guestPolicy : pad . padOptions . guestPolicy
} ) ;
2011-03-26 13:10:41 +00:00
padimpexp . init ( ) ;
padsavedrevs . init ( clientVars . initialRevisionList ) ;
padeditor . init ( postAceInit , pad . padOptions . view || { } ) ;
paduserlist . init ( pad . myUserInfo ) ;
2011-07-07 18:59:34 +01:00
// padchat.init(clientVars.chatHistory, pad.myUserInfo);
2011-03-26 13:10:41 +00:00
padconnectionstatus . init ( ) ;
padmodals . init ( ) ;
2011-07-07 18:59:34 +01:00
pad . collabClient = getCollabClient ( padeditor . ace , clientVars . collab _client _vars , pad . myUserInfo , {
colorPalette : pad . getColorPalette ( )
} ) ;
2011-03-26 13:10:41 +00: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 18:59:34 +01:00
function postAceInit ( )
{
2011-03-26 13:10:41 +00:00
padeditbar . init ( ) ;
2011-07-07 18:59:34 +01:00
setTimeout ( function ( )
{
padeditor . ace . focus ( ) ;
} , 0 ) ;
2011-03-26 13:10:41 +00:00
}
} ,
2011-07-07 18:59:34 +01:00
dispose : function ( )
{
2011-03-26 13:10:41 +00:00
padeditor . dispose ( ) ;
} ,
2011-07-07 18:59:34 +01:00
notifyChangeName : function ( newName )
{
2011-03-26 13:10:41 +00:00
pad . myUserInfo . name = newName ;
pad . collabClient . updateUserInfo ( pad . myUserInfo ) ;
2011-03-27 10:06:16 +00:00
//padchat.handleUserJoinOrUpdate(pad.myUserInfo);
2011-03-26 13:10:41 +00:00
} ,
2011-07-07 18:59:34 +01:00
notifyChangeColor : function ( newColorId )
{
2011-03-26 13:10:41 +00:00
pad . myUserInfo . colorId = newColorId ;
pad . collabClient . updateUserInfo ( pad . myUserInfo ) ;
2011-03-27 10:06:16 +00:00
//padchat.handleUserJoinOrUpdate(pad.myUserInfo);
2011-03-26 13:10:41 +00:00
} ,
2011-07-07 18:59:34 +01:00
notifyChangeTitle : function ( newTitle )
{
pad . collabClient . sendClientMessage (
{
2011-03-26 13:10:41 +00:00
type : 'padtitle' ,
title : newTitle ,
changedBy : pad . myUserInfo . name || "unnamed"
} ) ;
} ,
2011-07-07 18:59:34 +01:00
notifyChangePassword : function ( newPass )
{
pad . collabClient . sendClientMessage (
{
2011-03-26 13:10:41 +00:00
type : 'padpassword' ,
password : newPass ,
changedBy : pad . myUserInfo . name || "unnamed"
} ) ;
} ,
2011-07-07 18:59:34 +01:00
changePadOption : function ( key , value )
{
2011-03-26 13:10:41 +00:00
var options = { } ;
options [ key ] = value ;
pad . handleOptionsChange ( options ) ;
2011-07-07 18:59:34 +01:00
pad . collabClient . sendClientMessage (
{
2011-03-26 13:10:41 +00:00
type : 'padoptions' ,
options : options ,
changedBy : pad . myUserInfo . name || "unnamed"
} ) ;
} ,
2011-07-07 18:59:34 +01:00
changeViewOption : function ( key , value )
{
var options = {
view : { }
} ;
2011-03-26 13:10:41 +00:00
options . view [ key ] = value ;
pad . handleOptionsChange ( options ) ;
2011-08-13 22:10:58 +01:00
// if the request isn't to hide line numbers then broadcast this to other users
if ( key != "showLineNumbers" && key != "useMonospaceFont" )
2011-07-07 18:59:34 +01:00
{
2011-08-13 18:37:44 +01:00
pad . collabClient . sendClientMessage (
{
type : 'padoptions' ,
options : options ,
changedBy : pad . myUserInfo . name || "unnamed"
} ) ;
}
2011-03-26 13:10:41 +00:00
} ,
2011-07-07 18:59:34 +01:00
handleOptionsChange : function ( opts )
{
2011-03-26 13:10:41 +00:00
// opts object is a full set of options or just
// some options to change
2011-07-07 18:59:34 +01:00
if ( opts . view )
{
if ( ! pad . padOptions . view )
{
2011-03-26 13:10:41 +00:00
pad . padOptions . view = { } ;
}
2011-07-07 18:59:34 +01:00
for ( var k in opts . view )
{
2011-03-26 13:10:41 +00:00
pad . padOptions . view [ k ] = opts . view [ k ] ;
}
padeditor . setViewOptions ( pad . padOptions . view ) ;
}
2011-07-07 18:59:34 +01:00
if ( opts . guestPolicy )
{
2011-03-26 13:10:41 +00:00
// order important here
pad . padOptions . guestPolicy = opts . guestPolicy ;
paddocbar . setGuestPolicy ( opts . guestPolicy ) ;
}
} ,
2011-07-07 18:59:34 +01:00
getPadOptions : function ( )
{
2011-03-26 13:10:41 +00:00
// caller shouldn't mutate the object
return pad . padOptions ;
} ,
2011-07-07 18:59:34 +01:00
isPadPublic : function ( )
{
return ( ! pad . getIsProPad ( ) ) || ( pad . getPadOptions ( ) . guestPolicy == 'allow' ) ;
2011-03-26 13:10:41 +00:00
} ,
2011-07-07 18:59:34 +01:00
suggestUserName : function ( userId , name )
{
pad . collabClient . sendClientMessage (
{
2011-03-26 13:10:41 +00:00
type : 'suggestUserName' ,
unnamedId : userId ,
newName : name
} ) ;
} ,
2011-07-07 18:59:34 +01:00
handleUserJoin : function ( userInfo )
{
2011-03-26 13:10:41 +00:00
paduserlist . userJoinOrUpdate ( userInfo ) ;
2011-03-27 10:06:16 +00:00
//padchat.handleUserJoinOrUpdate(userInfo);
2011-03-26 13:10:41 +00:00
} ,
2011-07-07 18:59:34 +01:00
handleUserUpdate : function ( userInfo )
{
2011-03-26 13:10:41 +00:00
paduserlist . userJoinOrUpdate ( userInfo ) ;
2011-03-27 10:06:16 +00:00
//padchat.handleUserJoinOrUpdate(userInfo);
2011-03-26 13:10:41 +00:00
} ,
2011-07-07 18:59:34 +01:00
handleUserLeave : function ( userInfo )
{
2011-03-26 13:10:41 +00:00
paduserlist . userLeave ( userInfo ) ;
2011-03-27 10:06:16 +00:00
//padchat.handleUserLeave(userInfo);
2011-03-26 13:10:41 +00:00
} ,
2011-07-07 18:59:34 +01:00
handleClientMessage : function ( msg )
{
if ( msg . type == 'suggestUserName' )
{
if ( msg . unnamedId == pad . myUserInfo . userId && msg . newName && ! pad . myUserInfo . name )
{
2011-03-26 13:10:41 +00:00
pad . notifyChangeName ( msg . newName ) ;
paduserlist . setMyUserInfo ( pad . myUserInfo ) ;
}
}
2011-07-07 18:59:34 +01:00
else if ( msg . type == 'chat' )
{
2011-03-27 10:06:16 +00:00
//padchat.receiveChat(msg);
2011-03-26 13:10:41 +00:00
}
2011-07-07 18:59:34 +01:00
else if ( msg . type == 'padtitle' )
{
2011-03-26 13:10:41 +00:00
paddocbar . changeTitle ( msg . title ) ;
}
2011-07-07 18:59:34 +01:00
else if ( msg . type == 'padpassword' )
{
2011-03-26 13:10:41 +00:00
paddocbar . changePassword ( msg . password ) ;
}
2011-07-07 18:59:34 +01:00
else if ( msg . type == 'newRevisionList' )
{
2011-03-26 13:10:41 +00:00
padsavedrevs . newRevisionList ( msg . revisionList ) ;
}
2011-07-07 18:59:34 +01:00
else if ( msg . type == 'revisionLabel' )
{
2011-03-26 13:10:41 +00:00
padsavedrevs . newRevisionList ( msg . revisionList ) ;
}
2011-07-07 18:59:34 +01:00
else if ( msg . type == 'padoptions' )
{
2011-03-26 13:10:41 +00:00
var opts = msg . options ;
pad . handleOptionsChange ( opts ) ;
}
2011-07-07 18:59:34 +01:00
else if ( msg . type == 'guestanswer' )
{
2011-03-26 13:10:41 +00:00
// someone answered a prompt, remove it
paduserlist . removeGuestPrompt ( msg . guestId ) ;
}
} ,
2011-07-07 18:59:34 +01:00
editbarClick : function ( cmd )
{
if ( padeditbar )
{
2011-03-26 13:10:41 +00:00
padeditbar . toolbarClick ( cmd ) ;
}
} ,
2011-07-07 18:59:34 +01:00
dmesg : function ( m )
{
if ( pad . getIsDebugEnabled ( ) )
{
2011-03-26 13:10:41 +00:00
var djs = $ ( '#djs' ) . get ( 0 ) ;
2011-07-07 18:59:34 +01:00
var wasAtBottom = ( djs . scrollTop - ( djs . scrollHeight - $ ( djs ) . height ( ) ) >= - 20 ) ;
$ ( '#djs' ) . append ( '<p>' + m + '</p>' ) ;
if ( wasAtBottom )
{
2011-03-26 13:10:41 +00:00
djs . scrollTop = djs . scrollHeight ;
}
}
} ,
2011-07-07 18:59:34 +01: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 13:10:41 +00:00
abar . find ( "#servermsgtext" ) . html ( m . text ) ;
} ) ;
}
2011-07-07 18:59:34 +01:00
if ( m . js )
{
window [ 'ev' + 'al' ] ( m . js ) ;
2011-03-26 13:10:41 +00:00
}
}
2011-07-07 18:59:34 +01:00
else if ( m . type == 'GUEST_PROMPT' )
{
2011-03-26 13:10:41 +00:00
paduserlist . showGuestPrompt ( m . userId , m . displayName ) ;
}
} ,
2011-07-07 18:59:34 +01:00
handleChannelStateChange : function ( newState , message )
{
2011-03-26 13:10:41 +00:00
var oldFullyConnected = ! ! padconnectionstatus . isFullyConnected ( ) ;
var wasConnecting = ( padconnectionstatus . getStatus ( ) . what == 'connecting' ) ;
2011-07-07 18:59:34 +01:00
if ( newState == "CONNECTED" )
{
2011-03-26 13:10:41 +00:00
padconnectionstatus . connected ( ) ;
}
2011-07-07 18:59:34 +01:00
else if ( newState == "RECONNECTING" )
{
2011-03-26 13:10:41 +00:00
padconnectionstatus . reconnecting ( ) ;
}
2011-07-07 18:59:34 +01:00
else if ( newState == "DISCONNECTED" )
{
2011-03-26 13:10:41 +00:00
pad . diagnosticInfo . disconnectedMessage = message ;
2011-11-25 15:24:10 -08: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 13:10:41 +00:00
pad . asyncSendDiagnosticInfo ( ) ;
2011-07-07 18:59:34 +01:00
if ( typeof window . ajlog == "string" )
{
window . ajlog += ( "Disconnected: " + message + '\n' ) ;
}
2011-03-26 13:10:41 +00:00
padeditor . disable ( ) ;
padeditbar . disable ( ) ;
paddocbar . disable ( ) ;
padimpexp . disable ( ) ;
padconnectionstatus . disconnected ( message ) ;
}
var newFullyConnected = ! ! padconnectionstatus . isFullyConnected ( ) ;
2011-07-07 18:59:34 +01:00
if ( newFullyConnected != oldFullyConnected )
{
2011-03-26 13:10:41 +00:00
pad . handleIsFullyConnected ( newFullyConnected , wasConnecting ) ;
}
} ,
2011-07-07 18:59:34 +01:00
handleIsFullyConnected : function ( isConnected , isInitialConnect )
{
2011-03-26 13:10:41 +00:00
// load all images referenced from CSS, one at a time,
// starting one second after connection is first established.
2011-07-07 18:59:34 +01:00
if ( isConnected && ! pad . preloadedImages )
{
window . setTimeout ( function ( )
{
if ( ! pad . preloadedImages )
{
2011-03-26 13:10:41 +00:00
pad . preloadImages ( ) ;
pad . preloadedImages = true ;
}
} , 1000 ) ;
}
padsavedrevs . handleIsFullyConnected ( isConnected ) ;
2011-07-07 18:59:34 +01:00
pad . determineSidebarVisibility ( isConnected && ! isInitialConnect ) ;
} ,
determineSidebarVisibility : function ( asNowConnectedFeedback )
{
if ( pad . isFullyConnected ( ) )
{
var setSidebarVisibility = padutils . getCancellableAction ( "set-sidebar-visibility" , function ( )
{
$ ( "body" ) . toggleClass ( 'hidesidebar' , ! ! padcookie . getPref ( 'hideSidebar' ) ) ;
} ) ;
window . setTimeout ( setSidebarVisibility , asNowConnectedFeedback ? 3000 : 0 ) ;
}
else
{
2011-03-26 13:10:41 +00:00
padutils . cancelActions ( "set-sidebar-visibility" ) ;
$ ( "body" ) . removeClass ( 'hidesidebar' ) ;
}
} ,
2011-07-07 18:59:34 +01:00
handleCollabAction : function ( action )
{
if ( action == "commitPerformed" )
{
2011-03-26 13:10:41 +00:00
padeditbar . setSyncStatus ( "syncing" ) ;
}
2011-07-07 18:59:34 +01:00
else if ( action == "newlyIdle" )
{
2011-03-26 13:10:41 +00:00
padeditbar . setSyncStatus ( "done" ) ;
}
} ,
2011-07-07 18:59:34 +01:00
hideServerMessage : function ( )
{
2011-03-26 13:10:41 +00:00
alertBar . hideMessage ( ) ;
} ,
2011-07-07 18:59:34 +01:00
asyncSendDiagnosticInfo : function ( )
{
window . setTimeout ( function ( )
{
$ . ajax (
{
2011-03-26 13:10:41 +00:00
type : 'post' ,
url : '/ep/pad/connection-diagnostic-info' ,
2011-07-07 18:59:34 +01:00
data : {
diagnosticInfo : JSON . stringify ( pad . diagnosticInfo )
} ,
success : function ( )
{ } ,
error : function ( )
{ }
2011-03-26 13:10:41 +00:00
} ) ;
} , 0 ) ;
} ,
2011-07-07 18:59:34 +01:00
forceReconnect : function ( )
{
2011-03-26 13:10:41 +00: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 18:59:34 +01:00
toggleWidthPref : function ( )
{
var newValue = ! padcookie . getPref ( 'fullWidth' ) ;
2011-03-26 13:10:41 +00:00
padcookie . setPref ( 'fullWidth' , newValue ) ;
2011-07-07 18:59:34 +01:00
$ ( "#widthprefcheck" ) . toggleClass ( 'widthprefchecked' , ! ! newValue ) . toggleClass ( 'widthprefunchecked' , ! newValue ) ;
2011-03-26 13:10:41 +00:00
pad . handleWidthChange ( ) ;
} ,
2011-07-07 18:59:34 +01:00
toggleSidebar : function ( )
{
var newValue = ! padcookie . getPref ( 'hideSidebar' ) ;
2011-03-26 13:10:41 +00:00
padcookie . setPref ( 'hideSidebar' , newValue ) ;
2011-07-07 18:59:34 +01:00
$ ( "#sidebarcheck" ) . toggleClass ( 'sidebarchecked' , ! newValue ) . toggleClass ( 'sidebarunchecked' , ! ! newValue ) ;
2011-03-26 13:10:41 +00:00
pad . determineSidebarVisibility ( ) ;
} ,
2011-07-07 18:59:34 +01:00
handleWidthChange : function ( )
{
2011-03-26 13:10:41 +00:00
var isFullWidth = padcookie . getPref ( 'fullWidth' ) ;
2011-07-07 18:59:34 +01:00
if ( isFullWidth )
{
$ ( "body" ) . addClass ( 'fullwidth' ) . removeClass ( 'limwidth' ) . removeClass ( 'squish1width' ) . removeClass ( 'squish2width' ) ;
2011-03-26 13:10:41 +00:00
}
2011-07-07 18:59:34 +01:00
else
{
2011-03-26 13:10:41 +00:00
$ ( "body" ) . addClass ( 'limwidth' ) . removeClass ( 'fullwidth' ) ;
var pageWidth = $ ( window ) . width ( ) ;
2011-07-07 18:59:34 +01:00
$ ( "body" ) . toggleClass ( 'squish1width' , ( pageWidth < 912 && pageWidth > 812 ) ) . toggleClass ( 'squish2width' , ( pageWidth <= 812 ) ) ;
2011-03-26 13:10:41 +00:00
}
} ,
// this is called from code put into a frame from the server:
2011-07-07 18:59:34 +01:00
handleImportExportFrameCall : function ( callName , varargs )
{
padimpexp . handleFrameCall . call ( padimpexp , callName , Array . prototype . slice . call ( arguments , 1 ) ) ;
2011-03-26 13:10:41 +00:00
} ,
2011-07-07 18:59:34 +01:00
callWhenNotCommitting : function ( f )
{
2011-03-26 13:10:41 +00:00
pad . collabClient . callWhenNotCommitting ( f ) ;
} ,
2011-07-07 18:59:34 +01:00
getCollabRevisionNumber : function ( )
{
2011-03-26 13:10:41 +00:00
return pad . collabClient . getCurrentRevisionNumber ( ) ;
} ,
2011-07-07 18:59:34 +01:00
isFullyConnected : function ( )
{
2011-03-26 13:10:41 +00:00
return padconnectionstatus . isFullyConnected ( ) ;
} ,
2011-07-07 18:59:34 +01:00
addHistoricalAuthors : function ( data )
{
if ( ! pad . collabClient )
{
window . setTimeout ( function ( )
{
pad . addHistoricalAuthors ( data ) ;
} , 1000 ) ;
2011-03-26 13:10:41 +00:00
}
2011-07-07 18:59:34 +01:00
else
{
2011-03-26 13:10:41 +00:00
pad . collabClient . addHistoricalAuthors ( data ) ;
}
} ,
2011-07-07 18:59:34 +01:00
preloadImages : function ( )
{
2011-11-25 15:24:10 -08:00
var images = [ "../static/img/connectingbar.gif" ] ;
2011-07-07 18:59:34 +01:00
function loadNextImage ( )
{
if ( images . length == 0 )
{
2011-03-26 13:10:41 +00:00
return ;
}
var img = new Image ( ) ;
img . src = images . shift ( ) ;
2011-07-07 18:59:34 +01:00
if ( img . complete )
{
2011-03-26 13:10:41 +00:00
scheduleLoadNextImage ( ) ;
}
2011-07-07 18:59:34 +01:00
else
{
2011-03-26 13:10:41 +00:00
$ ( img ) . bind ( 'error load onreadystatechange' , scheduleLoadNextImage ) ;
}
}
2011-07-07 18:59:34 +01:00
function scheduleLoadNextImage ( )
{
2011-03-26 13:10:41 +00:00
window . setTimeout ( loadNextImage , 0 ) ;
}
scheduleLoadNextImage ( ) ;
}
} ;
2011-07-07 18:59:34 +01:00
var alertBar = ( function ( )
{
2011-03-26 13:10:41 +00:00
var animator = padutils . makeShowHideAnimator ( arriveAtAnimationState , false , 25 , 400 ) ;
2011-07-07 18:59:34 +01:00
function arriveAtAnimationState ( state )
{
if ( state == - 1 )
{
2011-03-26 13:10:41 +00:00
$ ( "#alertbar" ) . css ( 'opacity' , 0 ) . css ( 'display' , 'block' ) ;
}
2011-07-07 18:59:34 +01:00
else if ( state == 0 )
{
2011-03-26 13:10:41 +00:00
$ ( "#alertbar" ) . css ( 'opacity' , 1 ) ;
}
2011-07-07 18:59:34 +01:00
else if ( state == 1 )
{
2011-03-26 13:10:41 +00:00
$ ( "#alertbar" ) . css ( 'opacity' , 0 ) . css ( 'display' , 'none' ) ;
}
2011-07-07 18:59:34 +01:00
else if ( state < 0 )
{
$ ( "#alertbar" ) . css ( 'opacity' , state + 1 ) ;
2011-03-26 13:10:41 +00:00
}
2011-07-07 18:59:34 +01:00
else if ( state > 0 )
{
2011-03-26 13:10:41 +00:00
$ ( "#alertbar" ) . css ( 'opacity' , 1 - state ) ;
}
}
var self = {
2011-07-07 18:59:34 +01:00
displayMessage : function ( setupFunc )
{
2011-03-26 13:10:41 +00:00
animator . show ( ) ;
setupFunc ( $ ( "#alertbar" ) ) ;
} ,
2011-07-07 18:59:34 +01:00
hideMessage : function ( )
{
2011-03-26 13:10:41 +00:00
animator . hide ( ) ;
}
} ;
return self ;
} ( ) ) ;