From 56c07e484aab83f44efeb42ce97cf5848499039a Mon Sep 17 00:00:00 2001 From: Chad Weider Date: Thu, 26 Jan 2012 21:40:13 -0800 Subject: [PATCH 1/9] Expose settings on pad object. --- static/js/pad2.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/static/js/pad2.js b/static/js/pad2.js index 2c7d7e0e..52247dd2 100644 --- a/static/js/pad2.js +++ b/static/js/pad2.js @@ -24,14 +24,6 @@ var socket; -var settings = {}; -settings.LineNumbersDisabled = false; -settings.noColors = false; -settings.useMonospaceFontGlobal = false; -settings.globalUserName = false; -settings.hideQRCode = false; -settings.rtlIsTrue = false; - var chat = require('/chat').chat; var getCollabClient = require('/collab_client').getCollabClient; var padconnectionstatus = require('/pad_connectionstatus').padconnectionstatus; @@ -981,6 +973,18 @@ var alertBar = (function() return self; }()); + +var settings = { + LineNumbersDisabled: false +, noColors: false +, useMonospaceFontGlobal: false +, globalUserName: false +, hideQRCode: false +, rtlIsTrue: false +}; + +pad.settings = settings; + exports.settings = settings; exports.createCookie = createCookie; exports.readCookie = readCookie; From 514698162fc7519c648960f152d29257fe610ce0 Mon Sep 17 00:00:00 2001 From: Chad Weider Date: Thu, 26 Jan 2012 21:02:58 -0800 Subject: [PATCH 2/9] Inject pad dependencies into most pad submodules. --- static/js/pad2.js | 14 +++++++------- static/js/pad_cookie.js | 4 ++-- static/js/pad_docbar.js | 4 ++-- static/js/pad_editor.js | 6 +++--- static/js/pad_impexp.js | 8 ++------ static/js/pad_modals.js | 4 ++-- static/js/pad_savedrevs.js | 4 ++-- static/js/pad_userlist.js | 4 ++-- 8 files changed, 22 insertions(+), 26 deletions(-) diff --git a/static/js/pad2.js b/static/js/pad2.js index 52247dd2..15545541 100644 --- a/static/js/pad2.js +++ b/static/js/pad2.js @@ -438,7 +438,7 @@ var pad = { } // order of inits is important here: - padcookie.init(clientVars.cookiePrefsToSet); + padcookie.init(clientVars.cookiePrefsToSet, this); $("#widthprefcheck").click(pad.toggleWidthPref); // $("#sidebarcheck").click(pad.togglewSidebar); @@ -465,16 +465,16 @@ var pad = { initialTitle: clientVars.initialTitle, initialPassword: clientVars.initialPassword, guestPolicy: pad.padOptions.guestPolicy - }); - padimpexp.init(); - padsavedrevs.init(clientVars.initialRevisionList); + }, this); + padimpexp.init(this); + padsavedrevs.init(clientVars.initialRevisionList, this); - padeditor.init(postAceInit, pad.padOptions.view || {}); + padeditor.init(postAceInit, pad.padOptions.view || {}, this); - paduserlist.init(pad.myUserInfo); + paduserlist.init(pad.myUserInfo, this); // padchat.init(clientVars.chatHistory, pad.myUserInfo); padconnectionstatus.init(); - padmodals.init(); + padmodals.init(this); pad.collabClient = getCollabClient(padeditor.ace, clientVars.collab_client_vars, pad.myUserInfo, { colorPalette: pad.getColorPalette() diff --git a/static/js/pad_cookie.js b/static/js/pad_cookie.js index 24dc1e3f..1bb5700a 100644 --- a/static/js/pad_cookie.js +++ b/static/js/pad_cookie.js @@ -87,9 +87,9 @@ var padcookie = (function() var pad = undefined; var self = { - init: function(prefsToSet) + init: function(prefsToSet, _pad) { - pad = require('/pad2').pad; // Sidestep circular dependency (should be injected). + pad = _pad; var rawCookie = getRawCookie(); if (rawCookie) diff --git a/static/js/pad_docbar.js b/static/js/pad_docbar.js index cf461c93..b83bf3bf 100644 --- a/static/js/pad_docbar.js +++ b/static/js/pad_docbar.js @@ -118,9 +118,9 @@ var paddocbar = (function() var self = { title: null, password: null, - init: function(opts) + init: function(opts, _pad) { - pad = require('/pad2').pad; // Sidestep circular dependency (should be injected). + pad = _pad; panels = { impexp: { diff --git a/static/js/pad_editor.js b/static/js/pad_editor.js index e7be8175..6d3cbf40 100644 --- a/static/js/pad_editor.js +++ b/static/js/pad_editor.js @@ -32,11 +32,11 @@ var padeditor = (function() ace: null, // this is accessed directly from other files viewZoom: 100, - init: function(readyFunc, initialViewOptions) + init: function(readyFunc, initialViewOptions, _pad) { Ace2Editor = require('/ace').Ace2Editor; - pad = require('/pad2').pad; // Sidestep circular dependency (should be injected). - settings = require('/pad2').settings; + pad = _pad; + settings = pad.settings; function aceReady() { diff --git a/static/js/pad_impexp.js b/static/js/pad_impexp.js index aa99541e..0037195f 100644 --- a/static/js/pad_impexp.js +++ b/static/js/pad_impexp.js @@ -236,13 +236,9 @@ var padimpexp = (function() ///// var pad = undefined; var self = { - init: function() + init: function(_pad) { - try { - pad = require('/pad2').pad; // Sidestep circular dependency (should be injected). - } catch (e) { - // skip (doesn't require pad when required by timeslider) - } + pad = _pad; //get /p/padname var pad_root_path = new RegExp(/.*\/p\/[^\/]+/).exec(document.location.pathname) diff --git a/static/js/pad_modals.js b/static/js/pad_modals.js index 81ef0776..b78e28f4 100644 --- a/static/js/pad_modals.js +++ b/static/js/pad_modals.js @@ -75,9 +75,9 @@ var padmodals = (function() var pad = undefined; var self = { - init: function() + init: function(_pad) { - pad = require('/pad2').pad; // Sidestep circular dependency (should be injected). + pad = _pad; self.initFeedback(); self.initShareBox(); diff --git a/static/js/pad_savedrevs.js b/static/js/pad_savedrevs.js index bb52658b..6d37dfa8 100644 --- a/static/js/pad_savedrevs.js +++ b/static/js/pad_savedrevs.js @@ -349,9 +349,9 @@ var padsavedrevs = (function() var pad = undefined; var self = { - init: function(initialRevisions) + init: function(initialRevisions, _pad) { - pad = require('/pad2').pad; // Sidestep circular dependency (should be injected). + pad = _pad; self.newRevisionList(initialRevisions, true); $("#savedrevs-savenow").click(function() diff --git a/static/js/pad_userlist.js b/static/js/pad_userlist.js index e0a12f83..2c063d74 100644 --- a/static/js/pad_userlist.js +++ b/static/js/pad_userlist.js @@ -464,9 +464,9 @@ var paduserlist = (function() var pad = undefined; var self = { - init: function(myInitialUserInfo) + init: function(myInitialUserInfo, _pad) { - pad = require('/pad2').pad; // Sidestep circular dependency (should be injected). + pad = _pad; self.setMyUserInfo(myInitialUserInfo); From 3e9b56aa7513f5fdfd0b6420ab845dc1f9856b24 Mon Sep 17 00:00:00 2001 From: Chad Weider Date: Thu, 26 Jan 2012 20:37:18 -0800 Subject: [PATCH 3/9] Give controller for pad.html a more appropriate name. --- node/utils/tar.json | 2 +- static/js/{pad2.js => pad.js} | 0 static/js/pad_utils.js | 4 ++-- static/pad.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename static/js/{pad2.js => pad.js} (100%) diff --git a/node/utils/tar.json b/node/utils/tar.json index fd285b94..5fd6f696 100644 --- a/node/utils/tar.json +++ b/node/utils/tar.json @@ -1,6 +1,7 @@ { "pad.js": [ "jquery.js" + , "pad.js" , "ace2_common.js" , "pad_utils.js" , "plugins.js" @@ -17,7 +18,6 @@ , "pad_impexp.js" , "pad_savedrevs.js" , "pad_connectionstatus.js" - , "pad2.js" , "jquery-ui.js" , "chat.js" , "excanvas.js" diff --git a/static/js/pad2.js b/static/js/pad.js similarity index 100% rename from static/js/pad2.js rename to static/js/pad.js diff --git a/static/js/pad_utils.js b/static/js/pad_utils.js index 8583ca9e..464c5058 100644 --- a/static/js/pad_utils.js +++ b/static/js/pad_utils.js @@ -34,7 +34,7 @@ var padutils = { }, uniqueId: function() { - var pad = require('/pad2').pad; // Sidestep circular dependency + var pad = require('/pad').pad; // Sidestep circular dependency function encodeNum(n, width) { // returns string that is exactly 'width' chars, padding with zeros @@ -209,7 +209,7 @@ var padutils = { }, timediff: function(d) { - var pad = require('/pad2').pad; // Sidestep circular dependency + var pad = require('/pad').pad; // Sidestep circular dependency function format(n, word) { n = Math.round(n); diff --git a/static/pad.html b/static/pad.html index e66a3d6e..28bd2fcc 100644 --- a/static/pad.html +++ b/static/pad.html @@ -298,7 +298,7 @@ From d934fd61078883d36cfe64ee79c8c0bf1cb519e9 Mon Sep 17 00:00:00 2001 From: Chad Weider Date: Thu, 26 Jan 2012 21:20:26 -0800 Subject: [PATCH 5/9] Remove all global dependencies from broadcast modules. --- static/js/broadcast.js | 11 +++++++---- static/js/broadcast_revisions.js | 1 - static/js/broadcast_slider.js | 10 +++++++--- static/timeslider.html | 5 +++-- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/static/js/broadcast.js b/static/js/broadcast.js index b49b185a..2aa0b5d0 100644 --- a/static/js/broadcast.js +++ b/static/js/broadcast.js @@ -20,16 +20,17 @@ * limitations under the License. */ -var global = this; - var makeCSSManager = require('/cssmanager_client').makeCSSManager; var domline = require('/domline_client').domline; var Changeset = require('/easysync2_client').Changeset; var AttribPool = require('/easysync2_client').AttribPool; var linestylefilter = require('/linestylefilter_client').linestylefilter; -function loadBroadcastJS() +// These parameters were global, now they are injected. A reference to the +// Timeslider controller would probably be more appropriate. +function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, BroadcastSlider) { + var changesetLoader = undefined; // just in case... (todo: this must be somewhere else in the client code.) // Below Array#map code was direct pasted by AppJet/Etherpad, licence unknown. Possible source: http://www.tutorialspoint.com/javascript/array_map.htm if (!Array.prototype.map) @@ -423,7 +424,7 @@ function loadBroadcastJS() })); } - global.changesetLoader = { + changesetLoader = { running: false, resolved: [], requestQueue1: [], @@ -763,6 +764,8 @@ function loadBroadcastJS() } receiveAuthorData(clientVars.historicalAuthorData); + + return changesetLoader; } exports.loadBroadcastJS = loadBroadcastJS; diff --git a/static/js/broadcast_revisions.js b/static/js/broadcast_revisions.js index 364ac3e8..19f3f5ff 100644 --- a/static/js/broadcast_revisions.js +++ b/static/js/broadcast_revisions.js @@ -22,7 +22,6 @@ // revision info is a skip list whos entries represent a particular revision // of the document. These revisions are connected together by various // changesets, or deltas, between any two revisions. -var global = this; function loadBroadcastRevisionsJS() { diff --git a/static/js/broadcast_slider.js b/static/js/broadcast_slider.js index 972190ac..0bdc2cab 100644 --- a/static/js/broadcast_slider.js +++ b/static/js/broadcast_slider.js @@ -19,10 +19,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -var global = this; -function loadBroadcastSliderJS() + // These parameters were global, now they are injected. A reference to the + // Timeslider controller would probably be more appropriate. +function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) { + var BroadcastSlider; (function() { // wrap this code in its own namespace @@ -203,7 +205,7 @@ function loadBroadcastSliderJS() } } - global.BroadcastSlider = { + BroadcastSlider = { onSlider: onSlider, getSliderPosition: getSliderPosition, setSliderPosition: setSliderPosition, @@ -495,6 +497,8 @@ function loadBroadcastSliderJS() { $("#viewlatest").html(loc == BroadcastSlider.getSliderLength() ? "Viewing latest content" : "View latest content"); }) + + return BroadcastSlider; } exports.loadBroadcastSliderJS = loadBroadcastSliderJS; diff --git a/static/timeslider.html b/static/timeslider.html index 4e85047e..8b66729d 100644 --- a/static/timeslider.html +++ b/static/timeslider.html @@ -140,15 +140,16 @@ var fireWhenAllScriptsAreLoaded = []; + var BroadcastSlider, changesetLoader; function handleClientVars(message) { //save the client Vars clientVars = message.data; //load all script that doesn't work without the clientVars - require('/broadcast_slider').loadBroadcastSliderJS(); + BroadcastSlider = require('/broadcast_slider').loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded); require('/broadcast_revisions').loadBroadcastRevisionsJS(); - require('/broadcast').loadBroadcastJS(); + changesetLoader = require('/broadcast').loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, BroadcastSlider); //initialize export ui padimpexp.init(); From 67e6f9fa5aac32ee2dff91fb5a3b19f0d195cca3 Mon Sep 17 00:00:00 2001 From: Chad Weider Date: Wed, 18 Jan 2012 21:39:38 -0800 Subject: [PATCH 6/9] Move timeslider code into JS. --- node/utils/tar.json | 1 + static/js/timeslider.js | 178 ++++++++++++++++++++++++++++++++++++++++ static/timeslider.html | 159 +---------------------------------- 3 files changed, 182 insertions(+), 156 deletions(-) create mode 100644 static/js/timeslider.js diff --git a/node/utils/tar.json b/node/utils/tar.json index 5fd6f696..e1e6fb2b 100644 --- a/node/utils/tar.json +++ b/node/utils/tar.json @@ -46,5 +46,6 @@ , "broadcast.js" , "broadcast_slider.js" , "broadcast_revisions.js" + , "timeslider.js" ] } diff --git a/static/js/timeslider.js b/static/js/timeslider.js new file mode 100644 index 00000000..3b49f49a --- /dev/null +++ b/static/js/timeslider.js @@ -0,0 +1,178 @@ +/** + * 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 + */ + +/** + * Copyright 2009 Google Inc. + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +function createCookie(name,value,days) +{ + if (days) { + var date = new Date(); + date.setTime(date.getTime()+(days*24*60*60*1000)); + var expires = "; expires="+date.toGMTString(); + } + else var expires = ""; + document.cookie = name+"="+value+expires+"; path=/"; +} + +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; +} + +function randomString() { + var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + var string_length = 20; + var randomstring = ''; + for (var i=0; iYou have no permission to access this pad") + } + }); + + //get all the export links + export_links = $('#export > .exportlink') + + if(document.referrer.length > 0 && document.referrer.substring(document.referrer.lastIndexOf("/")-1,document.referrer.lastIndexOf("/")) === "p") { + $("#returnbutton").attr("href", document.referrer); + } else { + $("#returnbutton").attr("href", document.location.href.substring(0,document.location.href.lastIndexOf("/"))); + } + }); +} + +//sends a message over the socket +function sendSocketMsg(type, data) +{ + var sessionID = readCookie("sessionID"); + var password = readCookie("password"); + + var msg = { "component" : "timeslider", + "type": type, + "data": data, + "padId": padId, + "token": token, + "sessionID": sessionID, + "password": password, + "protocolVersion": 2}; + + socket.json.send(msg); +} + +var fireWhenAllScriptsAreLoaded = []; + +var BroadcastSlider, changesetLoader; +function handleClientVars(message) +{ + //save the client Vars + clientVars = message.data; + + //load all script that doesn't work without the clientVars + BroadcastSlider = require('/broadcast_slider').loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded); + require('/broadcast_revisions').loadBroadcastRevisionsJS(); + changesetLoader = require('/broadcast').loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, BroadcastSlider); + + //initialize export ui + require('/pad_impexp').padimpexp.init(); + + //change export urls when the slider moves + var export_rev_regex = /(\/\d+)?\/export/ + BroadcastSlider.onSlider(function(revno) + { + export_links.each(function() + { + this.setAttribute('href', this.href.replace(export_rev_regex, '/' + revno + '/export')); + }); + }); + + //fire all start functions of these scripts, formerly fired with window.load + for(var i=0;i < fireWhenAllScriptsAreLoaded.length;i++) + { + fireWhenAllScriptsAreLoaded[i](); + } +} + +exports.init = init; diff --git a/static/timeslider.html b/static/timeslider.html index 8b66729d..3e1cae05 100644 --- a/static/timeslider.html +++ b/static/timeslider.html @@ -17,161 +17,15 @@ @@ -299,13 +153,6 @@ Return to pad -
From c12e1aff0749724b6b32d204bd058c83d9597b0d Mon Sep 17 00:00:00 2001 From: Chad Weider Date: Thu, 26 Jan 2012 21:25:02 -0800 Subject: [PATCH 7/9] Place script at bottom. --- static/timeslider.html | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/static/timeslider.html b/static/timeslider.html index 3e1cae05..a41d46c0 100644 --- a/static/timeslider.html +++ b/static/timeslider.html @@ -15,18 +15,6 @@ - - @@ -214,6 +202,18 @@
+ + From 6a4c025e086ef2e6a99ded4c4ab9b4f047febeb4 Mon Sep 17 00:00:00 2001 From: Chad Weider Date: Sat, 28 Jan 2012 18:12:01 -0800 Subject: [PATCH 8/9] Global exception handler is not registered until the page's controller adds it. It is bad form to register this handler on definition. This would cause problems if, for instance, this module was required by our Node code. --- static/js/pad.js | 2 ++ static/js/pad_utils.js | 26 +++++++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/static/js/pad.js b/static/js/pad.js index 172f9323..e6d8dc9a 100644 --- a/static/js/pad.js +++ b/static/js/pad.js @@ -401,6 +401,8 @@ var pad = { init: function() { + padutils.setupGlobalExceptionHandler(); + $(document).ready(function() { //start the costum js diff --git a/static/js/pad_utils.js b/static/js/pad_utils.js index 464c5058..071185a8 100644 --- a/static/js/pad_utils.js +++ b/static/js/pad_utils.js @@ -459,17 +459,25 @@ var padutils = { } }; -//send javascript errors to the server -window.onerror = function test (msg, url, linenumber) -{ - var errObj = {errorInfo: JSON.stringify({msg: msg, url: url, linenumber: linenumber, userAgent: navigator.userAgent})}; - var loc = document.location; - var url = loc.protocol + "//" + loc.hostname + ":" + loc.port + "/" + loc.pathname.substr(1, loc.pathname.indexOf("/p/")) + "jserror"; +var globalExceptionHandler = undefined; +function setupGlobalExceptionHandler() { + //send javascript errors to the server + if (!globalExceptionHandler) { + globalExceptionHandler = function test (msg, url, linenumber) + { + var errObj = {errorInfo: JSON.stringify({msg: msg, url: url, linenumber: linenumber, userAgent: navigator.userAgent})}; + var loc = document.location; + var url = loc.protocol + "//" + loc.hostname + ":" + loc.port + "/" + loc.pathname.substr(1, loc.pathname.indexOf("/p/")) + "jserror"; - $.post(url, errObj); + $.post(url, errObj); - return false; -}; + return false; + }; + window.onerror = globalExceptionHandler; + } +} + +padutils.setupGlobalExceptionHandler = setupGlobalExceptionHandler; padutils.binarySearch = require('/ace2_common').binarySearch; From a408557a0ed84cfda81a0b6414a3cf56d4d88e64 Mon Sep 17 00:00:00 2001 From: Chad Weider Date: Sat, 28 Jan 2012 15:26:39 -0800 Subject: [PATCH 9/9] Make implicit loading of modules unnecessary. This is one step on the way to simplifying `Minify` and allowing all of the modules within pad.js to be loaded independently in development mode (which is useful for debugging). --- node/utils/Minify.js | 5 ----- static/js/pad.js | 9 +++++++++ static/js/timeslider.js | 6 ++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/node/utils/Minify.js b/node/utils/Minify.js index ea7834dc..98774d19 100644 --- a/node/utils/Minify.js +++ b/node/utils/Minify.js @@ -306,11 +306,6 @@ function tarCode(filesInOrder, files, write) { write("\n\n\n/*** File: static/js/" + filename + " ***/\n\n\n"); write(isolateJS(files[filename], filename)); } - - for(var i = 0, ii = filesInOrder.length; i < filesInOrder.length; i++) { - var filename = filesInOrder[i]; - write('require(' + JSON.stringify('/' + filename.replace(/^\/+/, '')) + ');\n'); - } } // Wrap the following code in a self executing function and assign exports to diff --git a/static/js/pad.js b/static/js/pad.js index e6d8dc9a..fb297d4a 100644 --- a/static/js/pad.js +++ b/static/js/pad.js @@ -24,6 +24,15 @@ var socket; +// These jQuery things should create local references, but for now `require()` +// assigns to the global `$` and augments it with plugins. +require('/jquery'); +require('/jquery-ui'); +require('/farbtastic'); +require('/excanvas'); +require('/json2'); +require('/undo-xpopup'); + var chat = require('/chat').chat; var getCollabClient = require('/collab_client').getCollabClient; var padconnectionstatus = require('/pad_connectionstatus').padconnectionstatus; diff --git a/static/js/timeslider.js b/static/js/timeslider.js index 3b49f49a..939c4c64 100644 --- a/static/js/timeslider.js +++ b/static/js/timeslider.js @@ -20,6 +20,12 @@ * limitations under the License. */ +// These jQuery things should create local references, but for now `require()` +// assigns to the global `$` and augments it with plugins. +require('/jquery'); +require('/json2'); +require('/undo-xpopup'); + function createCookie(name,value,days) { if (days) {