adding all weblabels from weblabels.fsf.org
[weblabels.fsf.org.git] / etherpad.fsf.org / 20120516 / files / pad.js
CommitLineData
5a920362 1/**
2 * This code is mostly from the old Etherpad. Please help us to comment this code.
3 * This helps other people to understand this code better and helps them to improve it.
4 * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
5 */
6
7/**
8 * Copyright 2009 Google Inc., 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS-IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 */
22
23/* global $, window */
24
25var socket;
26
27// These jQuery things should create local references, but for now `require()`
28// assigns to the global `$` and augments it with plugins.
29require('/jquery');
30require('/farbtastic');
31require('/excanvas');
32JSON = require('/json2');
33require('/undo-xpopup');
34require('/prefixfree');
35
36var chat = require('/chat').chat;
37var getCollabClient = require('/collab_client').getCollabClient;
38var padconnectionstatus = require('/pad_connectionstatus').padconnectionstatus;
39var padcookie = require('/pad_cookie').padcookie;
40var paddocbar = require('/pad_docbar').paddocbar;
41var padeditbar = require('/pad_editbar').padeditbar;
42var padeditor = require('/pad_editor').padeditor;
43var padimpexp = require('/pad_impexp').padimpexp;
44var padmodals = require('/pad_modals').padmodals;
45var padsavedrevs = require('/pad_savedrevs').padsavedrevs;
46var paduserlist = require('/pad_userlist').paduserlist;
47var padutils = require('/pad_utils').padutils;
48
49var createCookie = require('/pad_utils').createCookie;
50var readCookie = require('/pad_utils').readCookie;
51var randomString = require('/pad_utils').randomString;
52
53function getParams()
54{
55 var params = getUrlVars()
56 var showControls = params["showControls"];
57 var showChat = params["showChat"];
58 var userName = params["userName"];
59 var showLineNumbers = params["showLineNumbers"];
60 var useMonospaceFont = params["useMonospaceFont"];
61 var IsnoColors = params["noColors"];
62 var hideQRCode = params["hideQRCode"];
63 var rtl = params["rtl"];
64 var alwaysShowChat = params["alwaysShowChat"];
65
66 if(IsnoColors)
67 {
68 if(IsnoColors == "true")
69 {
70 settings.noColors = true;
71 $('#clearAuthorship').hide();
72 }
73 }
74 if(showControls)
75 {
76 if(showControls == "false")
77 {
78 $('#editbar').hide();
79 $('#editorcontainer').css({"top":"0px"});
80 }
81 }
82 if(showChat)
83 {
84 if(showChat == "false")
85 {
86 $('#chaticon').hide();
87 }
88 }
89 if(showLineNumbers)
90 {
91 if(showLineNumbers == "false")
92 {
93 settings.LineNumbersDisabled = true;
94 }
95 }
96 if(useMonospaceFont)
97 {
98 if(useMonospaceFont == "true")
99 {
100 settings.useMonospaceFontGlobal = true;
101 }
102 }
103 if(userName)
104 {
105 // If the username is set as a parameter we should set a global value that we can call once we have initiated the pad.
106 settings.globalUserName = decodeURIComponent(userName);
107 }
108 if(hideQRCode)
109 {
110 $('#qrcode').hide();
111 }
112 if(rtl)
113 {
114 if(rtl == "true")
115 {
116 settings.rtlIsTrue = true
117 }
118 }
119 if(alwaysShowChat)
120 {
121 if(alwaysShowChat == "true")
122 {
123 chat.stickToScreen();
124 }
125 }
126}
127
128function getUrlVars()
129{
130 var vars = [], hash;
131 var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
132 for(var i = 0; i < hashes.length; i++)
133 {
134 hash = hashes[i].split('=');
135 vars.push(hash[0]);
136 vars[hash[0]] = hash[1];
137 }
138 return vars;
139}
140
141function savePassword()
142{
143 //set the password cookie
144 createCookie("password",$("#passwordinput").val(),null,document.location.pathname);
145 //reload
146 document.location=document.location;
147}
148
149function ieTestXMLHTTP(){
150 // Test for IE known XML HTTP issue
151 if ($.browser.msie && !window.XMLHttpRequest){
152 $("#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>");
153 }
154}
155function handshake()
156{
157 var loc = document.location;
158 //get the correct port
159 var port = loc.port == "" ? (loc.protocol == "https:" ? 443 : 80) : loc.port;
160 //create the url
161 var url = loc.protocol + "//" + loc.hostname + ":" + port + "/";
162 //find out in which subfolder we are
163 var resource = loc.pathname.substr(1, loc.pathname.indexOf("/p/")) + "socket.io";
164 //connect
165 socket = pad.socket = io.connect(url, {
166 resource: resource,
167 'max reconnection attempts': 3,
168 'sync disconnect on unload' : false
169 });
170
171 function sendClientReady(isReconnect)
172 {
173 var padId = document.location.pathname.substring(document.location.pathname.lastIndexOf("/") + 1);
174 padId = decodeURIComponent(padId); // unescape neccesary due to Safari and Opera interpretation of spaces
175
176 if(!isReconnect)
177 document.title = padId.replace(/_+/g, ' ') + " | " + document.title;
178
179 var token = readCookie("token");
180 if (token == null)
181 {
182 token = "t." + randomString();
183 createCookie("token", token, 60);
184 }
185
186 var sessionID = readCookie("sessionID");
187 var password = readCookie("password");
188
189 var msg = {
190 "component": "pad",
191 "type": "CLIENT_READY",
192 "padId": padId,
193 "sessionID": sessionID,
194 "password": password,
195 "token": token,
196 "protocolVersion": 2
197 };
198
199 //this is a reconnect, lets tell the server our revisionnumber
200 if(isReconnect == true)
201 {
202 msg.client_rev=pad.collabClient.getCurrentRevisionNumber();
203 msg.reconnect=true;
204 }
205
206 socket.json.send(msg);
207 };
208
209 var disconnectTimeout;
210
211 socket.once('connect', function () {
212 sendClientReady(false);
213 });
214
215 socket.on('reconnect', function () {
216 //reconnect is before the timeout, lets stop the timeout
217 if(disconnectTimeout)
218 {
219 clearTimeout(disconnectTimeout);
220 }
221
222 pad.collabClient.setChannelState("CONNECTED");
223 sendClientReady(true);
224 });
225
226 socket.on('disconnect', function (reason) {
227 if(reason == "booted"){
228 pad.collabClient.setChannelState("DISCONNECTED");
229 } else {
230 function disconnectEvent()
231 {
232 pad.collabClient.setChannelState("DISCONNECTED", "reconnect_timeout");
233 }
234
235 pad.collabClient.setChannelState("RECONNECTING");
236
237 disconnectTimeout = setTimeout(disconnectEvent, 10000);
238 }
239 });
240
241 var receivedClientVars = false;
242 var initalized = false;
243
244 socket.on('message', function(obj)
245 {
246 //the access was not granted, give the user a message
247 if(!receivedClientVars && obj.accessStatus)
248 {
249 if(obj.accessStatus == "deny")
250 {
251 $("#editorloadingbox").html("<b>You do not have permission to access this pad</b>");
252 }
253 else if(obj.accessStatus == "needPassword")
254 {
255 $("#editorloadingbox").html("<b>You need a password to access this pad</b><br>" +
256 "<input id='passwordinput' type='password' name='password'>"+
257 "<button type='button' onclick=\"" + padutils.escapeHtml('require('+JSON.stringify(module.id)+").savePassword()") + "\">ok</button>");
258 }
259 else if(obj.accessStatus == "wrongPassword")
260 {
261 $("#editorloadingbox").html("<b>You're password was wrong</b><br>" +
262 "<input id='passwordinput' type='password' name='password'>"+
263 "<button type='button' onclick=\"" + padutils.escapeHtml('require('+JSON.stringify(module.id)+").savePassword()") + "\">ok</button>");
264 }
265 }
266
267 //if we haven't recieved the clientVars yet, then this message should it be
268 else if (!receivedClientVars)
269 {
270 //log the message
271 if (window.console) console.log(obj);
272
273 receivedClientVars = true;
274
275 //set some client vars
276 clientVars = obj;
277 clientVars.userAgent = "Anonymous";
278 clientVars.collab_client_vars.clientAgent = "Anonymous";
279
280 //initalize the pad
281 pad._afterHandshake();
282 initalized = true;
283
284 // If the LineNumbersDisabled value is set to true then we need to hide the Line Numbers
285 if (settings.LineNumbersDisabled == true)
286 {
287 pad.changeViewOption('showLineNumbers', false);
288 }
289
290 // If the noColors value is set to true then we need to hide the background colors on the ace spans
291 if (settings.noColors == true)
292 {
293 pad.changeViewOption('noColors', true);
294 }
295
296 if (settings.rtlIsTrue == true)
297 {
298 pad.changeViewOption('rtl', true);
299 }
300
301 // If the Monospacefont value is set to true then change it to monospace.
302 if (settings.useMonospaceFontGlobal == true)
303 {
304 pad.changeViewOption('useMonospaceFont', true);
305 }
306 // if the globalUserName value is set we need to tell the server and the client about the new authorname
307 if (settings.globalUserName !== false)
308 {
309 pad.notifyChangeName(settings.globalUserName); // Notifies the server
310 pad.myUserInfo.name = settings.globalUserName;
311 $('#myusernameedit').attr({"value":settings.globalUserName}); // Updates the current users UI
312 }
313 }
314 //This handles every Message after the clientVars
315 else
316 {
317 //this message advices the client to disconnect
318 if (obj.disconnect)
319 {
320 padconnectionstatus.disconnected(obj.disconnect);
321 socket.disconnect();
322 return;
323 }
324 else
325 {
326 pad.collabClient.handleMessageFromServer(obj);
327 }
328 }
329 });
330 // Bind the colorpicker
331 var fb = $('#colorpicker').farbtastic({ callback: '#mycolorpickerpreview', width: 220});
332}
333
334var pad = {
335 // don't access these directly from outside this file, except
336 // for debugging
337 collabClient: null,
338 myUserInfo: null,
339 diagnosticInfo: {},
340 initTime: 0,
341 clientTimeOffset: null,
342 preloadedImages: false,
343 padOptions: {},
344
345 // these don't require init; clientVars should all go through here
346 getPadId: function()
347 {
348 return clientVars.padId;
349 },
350 getClientIp: function()
351 {
352 return clientVars.clientIp;
353 },
354 getIsProPad: function()
355 {
356 return clientVars.isProPad;
357 },
358 getColorPalette: function()
359 {
360 return clientVars.colorPalette;
361 },
362 getDisplayUserAgent: function()
363 {
364 return padutils.uaDisplay(clientVars.userAgent);
365 },
366 getIsDebugEnabled: function()
367 {
368 return clientVars.debugEnabled;
369 },
370 getPrivilege: function(name)
371 {
372 return clientVars.accountPrivs[name];
373 },
374 getUserIsGuest: function()
375 {
376 return clientVars.userIsGuest;
377 },
378 getUserId: function()
379 {
380 return pad.myUserInfo.userId;
381 },
382 getUserName: function()
383 {
384 return pad.myUserInfo.name;
385 },
386 sendClientMessage: function(msg)
387 {
388 pad.collabClient.sendClientMessage(msg);
389 },
390
391 init: function()
392 {
393 padutils.setupGlobalExceptionHandler();
394
395 $(document).ready(function()
396 {
397 // test for XML HTTP capabiites
398 ieTestXMLHTTP();
399 // start the custom js
400 if (typeof customStart == "function") customStart();
401 getParams();
402 handshake();
403 });
404 },
405 _afterHandshake: function()
406 {
407 pad.clientTimeOffset = new Date().getTime() - clientVars.serverTimestamp;
408
409 //initialize the chat
410 chat.init(this);
411 pad.initTime = +(new Date());
412 pad.padOptions = clientVars.initialOptions;
413
414 if ((!$.browser.msie) && (!($.browser.mozilla && $.browser.version.indexOf("1.8.") == 0)))
415 {
416 document.domain = document.domain; // for comet
417 }
418
419 // for IE
420 if ($.browser.msie)
421 {
422 try
423 {
424 doc.execCommand("BackgroundImageCache", false, true);
425 }
426 catch (e)
427 {}
428 }
429
430 // order of inits is important here:
431 padcookie.init(clientVars.cookiePrefsToSet, this);
432
433 $("#widthprefcheck").click(pad.toggleWidthPref);
434 // $("#sidebarcheck").click(pad.togglewSidebar);
435
436 pad.myUserInfo = {
437 userId: clientVars.userId,
438 name: clientVars.userName,
439 ip: pad.getClientIp(),
440 colorId: clientVars.userColor,
441 userAgent: pad.getDisplayUserAgent()
442 };
443
444 if (clientVars.specialKey)
445 {
446 pad.myUserInfo.specialKey = clientVars.specialKey;
447 if (clientVars.specialKeyTranslation)
448 {
449 $("#specialkeyarea").html("mode: " + String(clientVars.specialKeyTranslation).toUpperCase());
450 }
451 }
452 paddocbar.init(
453 {
454 isTitleEditable: pad.getIsProPad(),
455 initialTitle: clientVars.initialTitle,
456 initialPassword: clientVars.initialPassword,
457 guestPolicy: pad.padOptions.guestPolicy
458 }, this);
459 padimpexp.init(this);
460 padsavedrevs.init(clientVars.initialRevisionList, this);
461
462 padeditor.init(postAceInit, pad.padOptions.view || {}, this);
463
464 paduserlist.init(pad.myUserInfo, this);
465 // padchat.init(clientVars.chatHistory, pad.myUserInfo);
466 padconnectionstatus.init();
467 padmodals.init(this);
468
469 pad.collabClient = getCollabClient(padeditor.ace, clientVars.collab_client_vars, pad.myUserInfo, {
470 colorPalette: pad.getColorPalette()
471 }, pad);
472 pad.collabClient.setOnUserJoin(pad.handleUserJoin);
473 pad.collabClient.setOnUpdateUserInfo(pad.handleUserUpdate);
474 pad.collabClient.setOnUserLeave(pad.handleUserLeave);
475 pad.collabClient.setOnClientMessage(pad.handleClientMessage);
476 pad.collabClient.setOnServerMessage(pad.handleServerMessage);
477 pad.collabClient.setOnChannelStateChange(pad.handleChannelStateChange);
478 pad.collabClient.setOnInternalAction(pad.handleCollabAction);
479
480 function postAceInit()
481 {
482 padeditbar.init();
483 setTimeout(function()
484 {
485 padeditor.ace.focus();
486 }, 0);
487 if(padcookie.getPref("chatAlwaysVisible")){ // if we have a cookie for always showing chat then show it
488 chat.stickToScreen(true); // stick it to the screen
489 $('#options-stickychat').prop("checked", true); // set the checkbox to on
490 }
491 if(padcookie.getPref("showAuthorshipColors") == false){
492 pad.changeViewOption('showAuthorColors', false);
493 }
494 }
495 },
496 dispose: function()
497 {
498 padeditor.dispose();
499 },
500 notifyChangeName: function(newName)
501 {
502 pad.myUserInfo.name = newName;
503 pad.collabClient.updateUserInfo(pad.myUserInfo);
504 //padchat.handleUserJoinOrUpdate(pad.myUserInfo);
505 },
506 notifyChangeColor: function(newColorId)
507 {
508 pad.myUserInfo.colorId = newColorId;
509 pad.collabClient.updateUserInfo(pad.myUserInfo);
510 //padchat.handleUserJoinOrUpdate(pad.myUserInfo);
511 },
512 notifyChangeTitle: function(newTitle)
513 {
514 pad.collabClient.sendClientMessage(
515 {
516 type: 'padtitle',
517 title: newTitle,
518 changedBy: pad.myUserInfo.name || "unnamed"
519 });
520 },
521 notifyChangePassword: function(newPass)
522 {
523 pad.collabClient.sendClientMessage(
524 {
525 type: 'padpassword',
526 password: newPass,
527 changedBy: pad.myUserInfo.name || "unnamed"
528 });
529 },
530 changePadOption: function(key, value)
531 {
532 var options = {};
533 options[key] = value;
534 pad.handleOptionsChange(options);
535 pad.collabClient.sendClientMessage(
536 {
537 type: 'padoptions',
538 options: options,
539 changedBy: pad.myUserInfo.name || "unnamed"
540 });
541 },
542 changeViewOption: function(key, value)
543 {
544 var options = {
545 view: {}
546 };
547 options.view[key] = value;
548 pad.handleOptionsChange(options);
549 },
550 handleOptionsChange: function(opts)
551 {
552 // opts object is a full set of options or just
553 // some options to change
554 if (opts.view)
555 {
556 if (!pad.padOptions.view)
557 {
558 pad.padOptions.view = {};
559 }
560 for (var k in opts.view)
561 {
562 pad.padOptions.view[k] = opts.view[k];
563 }
564 padeditor.setViewOptions(pad.padOptions.view);
565 }
566 if (opts.guestPolicy)
567 {
568 // order important here
569 pad.padOptions.guestPolicy = opts.guestPolicy;
570 paddocbar.setGuestPolicy(opts.guestPolicy);
571 }
572 },
573 getPadOptions: function()
574 {
575 // caller shouldn't mutate the object
576 return pad.padOptions;
577 },
578 isPadPublic: function()
579 {
580 return (!pad.getIsProPad()) || (pad.getPadOptions().guestPolicy == 'allow');
581 },
582 suggestUserName: function(userId, name)
583 {
584 pad.collabClient.sendClientMessage(
585 {
586 type: 'suggestUserName',
587 unnamedId: userId,
588 newName: name
589 });
590 },
591 handleUserJoin: function(userInfo)
592 {
593 paduserlist.userJoinOrUpdate(userInfo);
594 //padchat.handleUserJoinOrUpdate(userInfo);
595 },
596 handleUserUpdate: function(userInfo)
597 {
598 paduserlist.userJoinOrUpdate(userInfo);
599 //padchat.handleUserJoinOrUpdate(userInfo);
600 },
601 handleUserLeave: function(userInfo)
602 {
603 paduserlist.userLeave(userInfo);
604 //padchat.handleUserLeave(userInfo);
605 },
606 handleClientMessage: function(msg)
607 {
608 if (msg.type == 'suggestUserName')
609 {
610 if (msg.unnamedId == pad.myUserInfo.userId && msg.newName && !pad.myUserInfo.name)
611 {
612 pad.notifyChangeName(msg.newName);
613 paduserlist.setMyUserInfo(pad.myUserInfo);
614 }
615 }
616 else if (msg.type == 'chat')
617 {
618 //padchat.receiveChat(msg);
619 }
620 else if (msg.type == 'padtitle')
621 {
622 paddocbar.changeTitle(msg.title);
623 }
624 else if (msg.type == 'padpassword')
625 {
626 paddocbar.changePassword(msg.password);
627 }
628 else if (msg.type == 'newRevisionList')
629 {
630 padsavedrevs.newRevisionList(msg.revisionList);
631 }
632 else if (msg.type == 'revisionLabel')
633 {
634 padsavedrevs.newRevisionList(msg.revisionList);
635 }
636 else if (msg.type == 'padoptions')
637 {
638 var opts = msg.options;
639 pad.handleOptionsChange(opts);
640 }
641 else if (msg.type == 'guestanswer')
642 {
643 // someone answered a prompt, remove it
644 paduserlist.removeGuestPrompt(msg.guestId);
645 }
646 },
647 editbarClick: function(cmd)
648 {
649 if (padeditbar)
650 {
651 padeditbar.toolbarClick(cmd);
652 }
653 },
654 dmesg: function(m)
655 {
656 if (pad.getIsDebugEnabled())
657 {
658 var djs = $('#djs').get(0);
659 var wasAtBottom = (djs.scrollTop - (djs.scrollHeight - $(djs).height()) >= -20);
660 $('#djs').append('<p>' + m + '</p>');
661 if (wasAtBottom)
662 {
663 djs.scrollTop = djs.scrollHeight;
664 }
665 }
666 },
667 handleServerMessage: function(m)
668 {
669 if (m.type == 'NOTICE')
670 {
671 if (m.text)
672 {
673 alertBar.displayMessage(function(abar)
674 {
675 abar.find("#servermsgdate").html(" (" + padutils.simpleDateTime(new Date) + ")");
676 abar.find("#servermsgtext").html(m.text);
677 });
678 }
679 if (m.js)
680 {
681 window['ev' + 'al'](m.js);
682 }
683 }
684 else if (m.type == 'GUEST_PROMPT')
685 {
686 paduserlist.showGuestPrompt(m.userId, m.displayName);
687 }
688 },
689 handleChannelStateChange: function(newState, message)
690 {
691 var oldFullyConnected = !! padconnectionstatus.isFullyConnected();
692 var wasConnecting = (padconnectionstatus.getStatus().what == 'connecting');
693 if (newState == "CONNECTED")
694 {
695 padconnectionstatus.connected();
696 }
697 else if (newState == "RECONNECTING")
698 {
699 padconnectionstatus.reconnecting();
700 }
701 else if (newState == "DISCONNECTED")
702 {
703 pad.diagnosticInfo.disconnectedMessage = message;
704 pad.diagnosticInfo.padId = pad.getPadId();
705 pad.diagnosticInfo.socket = {};
706
707 //we filter non objects from the socket object and put them in the diagnosticInfo
708 //this ensures we have no cyclic data - this allows us to stringify the data
709 for(var i in socket.socket)
710 {
711 var value = socket.socket[i];
712 var type = typeof value;
713
714 if(type == "string" || type == "number")
715 {
716 pad.diagnosticInfo.socket[i] = value;
717 }
718 }
719
720 pad.asyncSendDiagnosticInfo();
721 if (typeof window.ajlog == "string")
722 {
723 window.ajlog += ("Disconnected: " + message + '\n');
724 }
725 padeditor.disable();
726 padeditbar.disable();
727 paddocbar.disable();
728 padimpexp.disable();
729
730 padconnectionstatus.disconnected(message);
731 }
732 var newFullyConnected = !! padconnectionstatus.isFullyConnected();
733 if (newFullyConnected != oldFullyConnected)
734 {
735 pad.handleIsFullyConnected(newFullyConnected, wasConnecting);
736 }
737 },
738 handleIsFullyConnected: function(isConnected, isInitialConnect)
739 {
740 // load all images referenced from CSS, one at a time,
741 // starting one second after connection is first established.
742 if (isConnected && !pad.preloadedImages)
743 {
744 window.setTimeout(function()
745 {
746 if (!pad.preloadedImages)
747 {
748 pad.preloadImages();
749 pad.preloadedImages = true;
750 }
751 }, 1000);
752 }
753
754 padsavedrevs.handleIsFullyConnected(isConnected);
755
756 // pad.determineSidebarVisibility(isConnected && !isInitialConnect);
757 pad.determineChatVisibility(isConnected && !isInitialConnect);
758 pad.determineAuthorshipColorsVisibility();
759
760 },
761/* determineSidebarVisibility: function(asNowConnectedFeedback)
762 {
763 if (pad.isFullyConnected())
764 {
765 var setSidebarVisibility = padutils.getCancellableAction("set-sidebar-visibility", function()
766 {
767 // $("body").toggleClass('hidesidebar', !! padcookie.getPref('hideSidebar'));
768 });
769 window.setTimeout(setSidebarVisibility, asNowConnectedFeedback ? 3000 : 0);
770 }
771 else
772 {
773 padutils.cancelActions("set-sidebar-visibility");
774 $("body").removeClass('hidesidebar');
775 }
776 },
777*/
778 determineChatVisibility: function(asNowConnectedFeedback){
779 var chatVisCookie = padcookie.getPref('chatAlwaysVisible');
780 if(chatVisCookie){ // if the cookie is set for chat always visible
781 chat.stickToScreen(true); // stick it to the screen
782 $('#options-stickychat').prop("checked", true); // set the checkbox to on
783 }
784 else{
785 $('#options-stickychat').prop("checked", false); // set the checkbox for off
786 }
787 },
788 determineAuthorshipColorsVisibility: function(){
789 var authColCookie = padcookie.getPref('showAuthorshipColors');
790 if (authColCookie){
791 pad.changeViewOption('showAuthorColors', true);
792 $('#options-colorscheck').prop("checked", true);
793 }
794 else {
795 $('#options-colorscheck').prop("checked", false);
796 }
797 },
798 handleCollabAction: function(action)
799 {
800 if (action == "commitPerformed")
801 {
802 padeditbar.setSyncStatus("syncing");
803 }
804 else if (action == "newlyIdle")
805 {
806 padeditbar.setSyncStatus("done");
807 }
808 },
809 hideServerMessage: function()
810 {
811 alertBar.hideMessage();
812 },
813 asyncSendDiagnosticInfo: function()
814 {
815 window.setTimeout(function()
816 {
817 $.ajax(
818 {
819 type: 'post',
820 url: '/ep/pad/connection-diagnostic-info',
821 data: {
822 diagnosticInfo: JSON.stringify(pad.diagnosticInfo)
823 },
824 success: function()
825 {},
826 error: function()
827 {}
828 });
829 }, 0);
830 },
831 forceReconnect: function()
832 {
833 $('form#reconnectform input.padId').val(pad.getPadId());
834 pad.diagnosticInfo.collabDiagnosticInfo = pad.collabClient.getDiagnosticInfo();
835 $('form#reconnectform input.diagnosticInfo').val(JSON.stringify(pad.diagnosticInfo));
836 $('form#reconnectform input.missedChanges').val(JSON.stringify(pad.collabClient.getMissedChanges()));
837 $('form#reconnectform').submit();
838 },
839 toggleWidthPref: function()
840 {
841 var newValue = !padcookie.getPref('fullWidth');
842 padcookie.setPref('fullWidth', newValue);
843 $("#widthprefcheck").toggleClass('widthprefchecked', !! newValue).toggleClass('widthprefunchecked', !newValue);
844 pad.handleWidthChange();
845 },
846/*
847 toggleSidebar: function()
848 {
849 var newValue = !padcookie.getPref('hideSidebar');
850 padcookie.setPref('hideSidebar', newValue);
851 $("#sidebarcheck").toggleClass('sidebarchecked', !newValue).toggleClass('sidebarunchecked', !! newValue);
852 pad.determineSidebarVisibility();
853 },
854*/
855 handleWidthChange: function()
856 {
857 var isFullWidth = padcookie.getPref('fullWidth');
858 if (isFullWidth)
859 {
860 $("body").addClass('fullwidth').removeClass('limwidth').removeClass('squish1width').removeClass('squish2width');
861 }
862 else
863 {
864 $("body").addClass('limwidth').removeClass('fullwidth');
865
866 var pageWidth = $(window).width();
867 $("body").toggleClass('squish1width', (pageWidth < 912 && pageWidth > 812)).toggleClass('squish2width', (pageWidth <= 812));
868 }
869 },
870 // this is called from code put into a frame from the server:
871 handleImportExportFrameCall: function(callName, varargs)
872 {
873 padimpexp.handleFrameCall.call(padimpexp, callName, Array.prototype.slice.call(arguments, 1));
874 },
875 callWhenNotCommitting: function(f)
876 {
877 pad.collabClient.callWhenNotCommitting(f);
878 },
879 getCollabRevisionNumber: function()
880 {
881 return pad.collabClient.getCurrentRevisionNumber();
882 },
883 isFullyConnected: function()
884 {
885 return padconnectionstatus.isFullyConnected();
886 },
887 addHistoricalAuthors: function(data)
888 {
889 if (!pad.collabClient)
890 {
891 window.setTimeout(function()
892 {
893 pad.addHistoricalAuthors(data);
894 }, 1000);
895 }
896 else
897 {
898 pad.collabClient.addHistoricalAuthors(data);
899 }
900 },
901 preloadImages: function()
902 {
903 var images = ["../static/img/connectingbar.gif"];
904
905 function loadNextImage()
906 {
907 if (images.length == 0)
908 {
909 return;
910 }
911 var img = new Image();
912 img.src = images.shift();
913 if (img.complete)
914 {
915 scheduleLoadNextImage();
916 }
917 else
918 {
919 $(img).bind('error load onreadystatechange', scheduleLoadNextImage);
920 }
921 }
922
923 function scheduleLoadNextImage()
924 {
925 window.setTimeout(loadNextImage, 0);
926 }
927 scheduleLoadNextImage();
928 }
929};
930
931var alertBar = (function()
932{
933
934 var animator = padutils.makeShowHideAnimator(arriveAtAnimationState, false, 25, 400);
935
936 function arriveAtAnimationState(state)
937 {
938 if (state == -1)
939 {
940 $("#alertbar").css('opacity', 0).css('display', 'block');
941 }
942 else if (state == 0)
943 {
944 $("#alertbar").css('opacity', 1);
945 }
946 else if (state == 1)
947 {
948 $("#alertbar").css('opacity', 0).css('display', 'none');
949 }
950 else if (state < 0)
951 {
952 $("#alertbar").css('opacity', state + 1);
953 }
954 else if (state > 0)
955 {
956 $("#alertbar").css('opacity', 1 - state);
957 }
958 }
959
960 var self = {
961 displayMessage: function(setupFunc)
962 {
963 animator.show();
964 setupFunc($("#alertbar"));
965 },
966 hideMessage: function()
967 {
968 animator.hide();
969 }
970 };
971 return self;
972}());
973
974function init() {
975 return pad.init();
976}
977
978var settings = {
979 LineNumbersDisabled: false
980, noColors: false
981, useMonospaceFontGlobal: false
982, globalUserName: false
983, hideQRCode: false
984, rtlIsTrue: false
985};
986
987pad.settings = settings;
988
989exports.settings = settings;
990exports.createCookie = createCookie;
991exports.readCookie = readCookie;
992exports.randomString = randomString;
993exports.getParams = getParams;
994exports.getUrlVars = getUrlVars;
995exports.savePassword = savePassword;
996exports.handshake = handshake;
997exports.pad = pad;
998exports.init = init;
999exports.alertBar = alertBar;
1000