aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--README.md4
-rw-r--r--etherpad/etc/etherpad.localdev-default.properties1
-rw-r--r--etherpad/src/etherpad/control/admin/pluginmanager.js7
-rw-r--r--etherpad/src/etherpad/control/pad/pad_control.js34
-rw-r--r--etherpad/src/etherpad/helpers.js30
-rw-r--r--etherpad/src/etherpad/legacy_urls.js2
-rw-r--r--etherpad/src/etherpad/pad/padutils.js37
-rw-r--r--etherpad/src/etherpad/utils.js61
-rw-r--r--etherpad/src/main.js8
-rw-r--r--etherpad/src/plugins/testplugin/controllers/testplugin.js15
-rw-r--r--etherpad/src/plugins/testplugin/templates/page.ejs23
-rw-r--r--etherpad/src/plugins/testplugin/templates/testplugin.ejs10
-rw-r--r--etherpad/src/plugins/twitterStyleTags/controllers/tagBrowser.js213
-rw-r--r--etherpad/src/plugins/twitterStyleTags/hooks.js15
-rw-r--r--etherpad/src/plugins/twitterStyleTags/main.js4
-rw-r--r--etherpad/src/plugins/twitterStyleTags/models/tagQuery.js227
-rw-r--r--etherpad/src/plugins/twitterStyleTags/static/css/tagBrowser.css2
-rw-r--r--etherpad/src/plugins/twitterStyleTags/templates/tagBrowser.ejs199
-rw-r--r--etherpad/src/plugins/urlIndexer/controllers/urlBrowser.js132
-rw-r--r--etherpad/src/plugins/urlIndexer/hooks.js49
-rw-r--r--etherpad/src/plugins/urlIndexer/main.js34
-rw-r--r--etherpad/src/plugins/urlIndexer/templates/urlBrowser.ejs53
-rw-r--r--etherpad/src/static/css/pad2_ejs.css22
-rw-r--r--etherpad/src/static/js/broadcast.js3
-rw-r--r--etherpad/src/static/js/broadcast_slider.js2
-rw-r--r--etherpad/src/static/js/pad.js.old1984
-rw-r--r--etherpad/src/static/js/plugins.js9
-rw-r--r--etherpad/src/static/js/store.js2
-rw-r--r--etherpad/src/templates/admin/pluginmanager.ejs147
-rw-r--r--etherpad/src/templates/pad/pad_body2.ejs576
-rw-r--r--etherpad/src/themes/default/templates/500_body.ejs (renamed from etherpad/src/templates/500_body.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/admin/pluginmanager.ejs74
-rw-r--r--etherpad/src/themes/default/templates/email/padinvite.ejs (renamed from etherpad/src/templates/email/padinvite.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/framed/framedfooter.ejs (renamed from etherpad/src/templates/framed/framedfooter.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/framed/framedheader-pro.ejs (renamed from etherpad/src/templates/framed/framedheader-pro.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/framed/framedheader.ejs (renamed from etherpad/src/templates/framed/framedheader.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/framed/framedpage-pro.ejs (renamed from etherpad/src/templates/framed/framedpage-pro.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/framed/framedpage.ejs (renamed from etherpad/src/templates/framed/framedpage.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/html.ejs (renamed from etherpad/src/templates/html.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/main/home.ejs (renamed from etherpad/src/templates/main/home.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/main/pro_signup_body.ejs (renamed from etherpad/src/templates/main/pro_signup_body.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/misc/pad_default.ejs (renamed from etherpad/src/templates/misc/pad_default.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/notice.ejs (renamed from etherpad/src/templates/notice.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pad/create_body.ejs (renamed from etherpad/src/templates/pad/create_body.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pad/pad_body2.ejs505
-rw-r--r--etherpad/src/themes/default/templates/pad/pad_iphone_body.ejs (renamed from etherpad/src/templates/pad/pad_iphone_body.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pad/padview_body.ejs (renamed from etherpad/src/templates/pad/padview_body.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/page.ejs135
-rw-r--r--etherpad/src/themes/default/templates/pro-account/recover.ejs (renamed from etherpad/src/templates/pro-account/recover.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro-account/sign-in.ejs (renamed from etherpad/src/templates/pro-account/sign-in.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro-help/main.ejs (renamed from etherpad/src/templates/pro-help/main.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro-help/pro-help-template.ejs (renamed from etherpad/src/templates/pro-help/pro-help-template.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/account/account-welcome-email.ejs (renamed from etherpad/src/templates/pro/account/account-welcome-email.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/account/forgot-password-email.ejs (renamed from etherpad/src/templates/pro/account/forgot-password-email.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/account/forgot-password.ejs (renamed from etherpad/src/templates/pro/account/forgot-password.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/account/my-account.ejs (renamed from etherpad/src/templates/pro/account/my-account.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/account/signin.ejs (renamed from etherpad/src/templates/pro/account/signin.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/admin/account-manager.ejs (renamed from etherpad/src/templates/pro/admin/account-manager.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/admin/admin-template.ejs (renamed from etherpad/src/templates/pro/admin/admin-template.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/admin/delete-account.ejs (renamed from etherpad/src/templates/pro/admin/delete-account.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/admin/manage-account.ejs (renamed from etherpad/src/templates/pro/admin/manage-account.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/admin/new-account.ejs (renamed from etherpad/src/templates/pro/admin/new-account.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/padlist/pro-padlist.ejs (renamed from etherpad/src/templates/pro/padlist/pro-padlist.ejs)0
-rw-r--r--etherpad/src/themes/default/templates/pro/pro_home.ejs (renamed from etherpad/src/templates/pro/pro_home.ejs)0
-rw-r--r--infrastructure/ace/www/ace2_outer.js14
-rw-r--r--infrastructure/ace/www/domline.js9
-rw-r--r--infrastructure/ace/www/linestylefilter.js9
-rw-r--r--infrastructure/com.etherpad/licensing.scala2
-rw-r--r--infrastructure/framework-src/modules/ejs.js16
69 files changed, 1568 insertions, 3101 deletions
diff --git a/README.md b/README.md
index e8df528..c60e847 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# About Etherpad
EtherPad is a web-based realtime collaborative document editor.
-EtherPad currently lives at http://etherpad.org
+EtherPad currently lives at <http://etherpad.org>
-For instructions to build and run EtherPad, see: http://doc.etherpad.org/ep/tag/?query=installation
+For instructions to build and run EtherPad, see: <http://doc.etherpad.org/ep/tag/?query=installation>
diff --git a/etherpad/etc/etherpad.localdev-default.properties b/etherpad/etc/etherpad.localdev-default.properties
index 98327fd..374101f 100644
--- a/etherpad/etc/etherpad.localdev-default.properties
+++ b/etherpad/etc/etherpad.localdev-default.properties
@@ -20,3 +20,4 @@ transportPrefix = /comet
transportUseWildcardSubdomains = true
useHttpsUrls = false
useVirtualFileRoot = ./src
+theme = default
diff --git a/etherpad/src/etherpad/control/admin/pluginmanager.js b/etherpad/src/etherpad/control/admin/pluginmanager.js
index 39edc4a..c4bee5b 100644
--- a/etherpad/src/etherpad/control/admin/pluginmanager.js
+++ b/etherpad/src/etherpad/control/admin/pluginmanager.js
@@ -26,6 +26,7 @@ import("etherpad.pro.pro_utils");
import("etherpad.helpers");
import("etherpad.pro.pro_accounts.getSessionProAccount");
import("etherpad.admin.plugins");
+import("etherpad.pad.padutils");
function onRequest() {
@@ -52,8 +53,14 @@ function onRequest() {
userId: padusers.getUserId(),
});
+
+ padutils.setOptsAndCookiePrefs(request);
+ var prefs = helpers.getClientVar('cookiePrefsToSet');
+ var bodyClass = (prefs.isFullWidth ? "fullwidth" : "limwidth")
+
renderHtml("admin/pluginmanager.ejs",
{
+ prefs: prefs,
config: appjet.config,
bodyClass: 'nonpropad',
isPro: pro_utils.isProDomainRequest(),
diff --git a/etherpad/src/etherpad/control/pad/pad_control.js b/etherpad/src/etherpad/control/pad/pad_control.js
index 3d32355..2a6a1be 100644
--- a/etherpad/src/etherpad/control/pad/pad_control.js
+++ b/etherpad/src/etherpad/control/pad/pad_control.js
@@ -331,15 +331,6 @@ function render_pad(localPadId) {
var specialKey = request.params.specialKey ||
(sessions.isAnEtherpadAdmin() ? collab_server.getSpecialKey('invisible') :
null);
- if (request.params.fullScreen) { // tokbox, embedding
- opts.fullScreen = true;
- }
- if (request.params.tokbox) {
- opts.tokbox = true;
- }
- if (request.params.sidebar) {
- opts.sidebar = Boolean(Number(request.params.sidebar));
- }
helpers.addClientVars({
padId: localPadId,
@@ -365,34 +356,17 @@ function render_pad(localPadId) {
userColor: assignColorId(pad, userId),
specialKey: specialKey,
specialKeyTranslation: collab_server.translateSpecialKey(specialKey),
- opts: opts
});
});
var isProUser = (isPro && ! padusers.isGuest(userId));
- var isFullWidth = false;
- var hideSidebar = false;
- var cookiePrefs = padutils.getPrefsCookieData();
- if (cookiePrefs) {
- isFullWidth = !! cookiePrefs.fullWidth;
- hideSidebar = !! cookiePrefs.hideSidebar;
- }
- if (opts.fullScreen) {
- isFullWidth = true;
- if (opts.tokbox) {
- hideSidebar = true;
- }
- }
- if ('sidebar' in opts) {
- hideSidebar = ! opts.sidebar;
- }
- var bodyClass = (isFullWidth ? "fullwidth" : "limwidth")+
+ padutils.setOptsAndCookiePrefs(request);
+ var prefs = helpers.getClientVar('cookiePrefsToSet');
+ var bodyClass = (prefs.isFullWidth ? "fullwidth" : "limwidth") +
" "+(isPro ? "propad" : "nonpropad")+" "+
(isProUser ? "prouser" : "nonprouser");
- var cookiePrefsToSet = {fullWidth:isFullWidth, hideSidebar:hideSidebar};
- helpers.addClientVars({cookiePrefsToSet: cookiePrefsToSet});
renderHtml("pad/pad_body2.ejs",
{localPadId:localPadId,
@@ -404,7 +378,7 @@ function render_pad(localPadId) {
isProAccountHolder: isProUser,
account: getSessionProAccount(), // may be falsy
toHTML: toHTML,
- prefs: {isFullWidth:isFullWidth, hideSidebar:hideSidebar},
+ prefs: prefs,
signinUrl: '/ep/account/sign-in?cont='+
encodeURIComponent(request.url),
fullSuperdomain: pro_utils.getFullSuperdomainHost()
diff --git a/etherpad/src/etherpad/helpers.js b/etherpad/src/etherpad/helpers.js
index e16c2f7..54bee2d 100644
--- a/etherpad/src/etherpad/helpers.js
+++ b/etherpad/src/etherpad/helpers.js
@@ -77,6 +77,10 @@ function addClientVars(vars) {
});
}
+function getClientVar(name) {
+ return _hd().clientVars[name];
+}
+
function addToHead(stuff) {
_hd().headExtra += stuff;
}
@@ -274,3 +278,29 @@ function rafterTerminationDate() {
return "March 31, 2010";
}
+function updateToUrl(setParams, deleteParams, setPath) {
+ var params = {};
+
+ for (param in request.params)
+ if (deleteParams === undefined || deleteParams.indexOf(param) == -1)
+ params[param] = request.params[param];
+
+ if (setParams !== undefined)
+ for (param in setParams)
+ params[param] = setParams[param];
+
+ var path = request.path;
+ if (setPath !== undefined)
+ path = setPath;
+
+ var paramStr = '';
+ for (param in params) {
+ if (paramStr == '')
+ paramStr += '?';
+ else
+ paramStr += '&';
+ paramStr += param + '=' + params[param];
+ }
+
+ return path + paramStr;
+} \ No newline at end of file
diff --git a/etherpad/src/etherpad/legacy_urls.js b/etherpad/src/etherpad/legacy_urls.js
index 458f3b6..d8aa629 100644
--- a/etherpad/src/etherpad/legacy_urls.js
+++ b/etherpad/src/etherpad/legacy_urls.js
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-/* legacy URLs only apply to the public etherpad.com site. (not Pro or PNE). */
+/* legacy URLs only apply to the public main site. (not Pro or PNE). */
var _legacyURLs = {
'/ep/beta-signup': '/',
diff --git a/etherpad/src/etherpad/pad/padutils.js b/etherpad/src/etherpad/pad/padutils.js
index 2fdf579..dc4c9ab 100644
--- a/etherpad/src/etherpad/pad/padutils.js
+++ b/etherpad/src/etherpad/pad/padutils.js
@@ -25,6 +25,7 @@ import("etherpad.pro.pro_accounts");
import("etherpad.pro.pro_padmeta");
import("etherpad.pad.model");
import("etherpad.sessions.getSession");
+import("etherpad.helpers");
jimport("java.lang.System.out.println");
@@ -152,3 +153,39 @@ function getProDisplayTitle(localPadId, title) {
}
}
+
+function setOptsAndCookiePrefs(request) {
+ opts = {};
+ if (request.params.fullScreen) { // tokbox, embedding
+ opts.fullScreen = true;
+ }
+ if (request.params.tokbox) {
+ opts.tokbox = true;
+ }
+ if (request.params.sidebar) {
+ opts.sidebar = Boolean(Number(request.params.sidebar));
+ }
+ helpers.addClientVars({opts: opts});
+
+
+ var prefs = getPrefsCookieData();
+
+ var prefsToSet = {
+ fullWidth:false,
+ hideSidebar:false
+ };
+ if (prefs) {
+ prefsToSet.isFullWidth = !! prefs.fullWidth;
+ prefsToSet.hideSidebar = !! prefs.hideSidebar;
+ }
+ if (opts.fullScreen) {
+ prefsToSet.isFullWidth = true;
+ if (opts.tokbox) {
+ prefsToSet.hideSidebar = true;
+ }
+ }
+ if ('sidebar' in opts) {
+ prefsToSet.hideSidebar = ! opts.sidebar;
+ }
+ helpers.addClientVars({cookiePrefsToSet: prefsToSet});
+}
diff --git a/etherpad/src/etherpad/utils.js b/etherpad/src/etherpad/utils.js
index 3e35f00..65ebe1f 100644
--- a/etherpad/src/etherpad/utils.js
+++ b/etherpad/src/etherpad/utils.js
@@ -40,6 +40,8 @@ import("etherpad.admin.plugins");
jimport("java.lang.System.out.print");
jimport("java.lang.System.out.println");
+jimport("java.io.File");
+
//----------------------------------------------------------------
// utilities
//----------------------------------------------------------------
@@ -57,17 +59,69 @@ function randomUniquePadId() {
// template rendering
//----------------------------------------------------------------
+function findExistsingFile(files) {
+ for (var i = 0; i < files.length; i++) {
+ var f = new File('./src' + files[i]);
+ if (f.exists())
+ return files[i];
+ }
+}
+
function findTemplate(filename, plugin) {
- if (plugin != undefined)
- return '/plugins/' + plugin + '/templates/' + filename;
+ var files = [];
+
+ var pluginList = [plugin];
+ try {
+ if (plugin.forEach !== undefined)
+ pluginList = plugin;
+ else
+ pluginList = [plugin];
+ } catch (e) {}
+
+ pluginList.forEach(function (plugin) {
+ if (plugin != undefined) {
+ files.push('/plugins/' + plugin + '/templates/' + filename);
+ files.push('/themes/' + appjet.config.theme + '/plugins/' + plugin + '/templates/' + filename);
+ files.push('/themes/default/plugins/' + plugin + '/templates/' + filename);
+ }
+ });
+ files.push('/themes/' + appjet.config.theme + '/templates/' + filename);
+ files.push('/themes/default/templates/' + filename);
+
+ return findExistsingFile(files);
+}
+
+function Template(params, plugin) {
+ this._defines = {}
+ this._params = params;
+ this._params.template = this;
+ this._plugin = plugin;
+}
+
+Template.prototype.define = function(name, fn) {
+ this._defines[name] = fn;
+ return '';
+}
+
+Template.prototype.use = function (name, fn, arg) {
+ if (this._defines[name] != undefined)
+ return this._defines[name](arg);
+ else if (fn != undefined)
+ return fn(arg);
else
- return '/templates/' + filename;
+ return '';
+}
+
+Template.prototype.inherit = function (template) {
+ return renderTemplateAsString(template, this._params, this._plugin);
}
function renderTemplateAsString(filename, data, plugin) {
data = data || {};
data.helpers = helpers; // global helpers
data.plugins = plugins; // Access callHook and the like...
+ if (data.template == undefined)
+ new Template(data, plugin);
var f = findTemplate(filename, plugin); //"/templates/"+filename;
if (! appjet.scopeCache.ejs) {
@@ -76,6 +130,7 @@ function renderTemplateAsString(filename, data, plugin) {
var cacheObj = appjet.scopeCache.ejs[filename];
if (cacheObj === undefined || fileLastModified(f) > cacheObj.mtime) {
var templateText = readFile(f);
+ templateText += "<%: template.use('body', function () { return ''; }); %> ";
cacheObj = {};
cacheObj.tmpl = new EJS({text: templateText, name: filename});
cacheObj.mtime = fileLastModified(f);
diff --git a/etherpad/src/main.js b/etherpad/src/main.js
index d925638..738df51 100644
--- a/etherpad/src/main.js
+++ b/etherpad/src/main.js
@@ -287,6 +287,14 @@ function checkHost() {
// Check for HTTPS
function checkHTTPS() {
+ /* Open-source note: this function used to check the protocol and make
+ * sure that pages that needed to be secure went over HTTPS, and pages
+ * that didn't go over HTTP. However, when we open-sourced the code,
+ * we disabled HTTPS because we didn't want to ship the etherpad.com
+ * private crypto keys. --aiba */
+ return;
+
+
if (stringutils.startsWith(request.path, "/static/")) { return; }
if (sessions.getSession().disableHttps || request.params.disableHttps) {
diff --git a/etherpad/src/plugins/testplugin/controllers/testplugin.js b/etherpad/src/plugins/testplugin/controllers/testplugin.js
index 0c79e06..da74ade 100644
--- a/etherpad/src/plugins/testplugin/controllers/testplugin.js
+++ b/etherpad/src/plugins/testplugin/controllers/testplugin.js
@@ -29,7 +29,6 @@ import("sqlbase.sqlbase");
import("sqlbase.sqlcommon");
import("sqlbase.sqlobj");
-
function onRequest() {
var isPro = pro_utils.isProDomainRequest();
var userId = padusers.getUserId();
@@ -47,11 +46,13 @@ function onRequest() {
var isProUser = (isPro && ! padusers.isGuest(userId));
- renderHtml("testplugin.ejs",
- {
- isPro: isPro,
- isProAccountHolder: isProUser,
- account: getSessionProAccount(), // may be falsy
- }, 'testplugin');
+ renderHtml(
+ "testplugin.ejs",
+ {
+ isPro: isPro,
+ isProAccountHolder: isProUser,
+ account: getSessionProAccount(), // may be falsy
+ },
+ 'testplugin');
return true;
}
diff --git a/etherpad/src/plugins/testplugin/templates/page.ejs b/etherpad/src/plugins/testplugin/templates/page.ejs
new file mode 100644
index 0000000..71633c0
--- /dev/null
+++ b/etherpad/src/plugins/testplugin/templates/page.ejs
@@ -0,0 +1,23 @@
+<% /* 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. */ %>
+
+<% template.define('body', function() { var ejs_data=''; %>
+ <div id="blabla">
+ <h1>Page header</h1>
+ <%: template.use('content', function() { var ejs_data=''; %>
+ Original content
+ <% return ejs_data; }); %>
+ <div>footer</div>
+ </div>
+<% return ejs_data; }); %>
diff --git a/etherpad/src/plugins/testplugin/templates/testplugin.ejs b/etherpad/src/plugins/testplugin/templates/testplugin.ejs
index f70ca8d..69c4453 100644
--- a/etherpad/src/plugins/testplugin/templates/testplugin.ejs
+++ b/etherpad/src/plugins/testplugin/templates/testplugin.ejs
@@ -24,6 +24,10 @@ limitations under the License. */ %>
helpers.addToHead('\n<style type="text/css" title="dynamicsyntax"></style>\n');
%>
-<div id="padpage">
- Welcome to the test plugin
-</div>
+<% template.inherit('page.ejs') %>
+
+<% template.define('content', function() { var ejs_data=''; %>
+ <div id="padpage">
+ Welcome to the test plugin
+ </div>
+<% return ejs_data; }); %>
diff --git a/etherpad/src/plugins/twitterStyleTags/controllers/tagBrowser.js b/etherpad/src/plugins/twitterStyleTags/controllers/tagBrowser.js
index 793067d..5335ab7 100644
--- a/etherpad/src/plugins/twitterStyleTags/controllers/tagBrowser.js
+++ b/etherpad/src/plugins/twitterStyleTags/controllers/tagBrowser.js
@@ -15,6 +15,8 @@
* limitations under the License.
*/
+import("plugins.twitterStyleTags.models.tagQuery");
+
import("faststatic");
import("dispatch.{Dispatcher,PrefixMatcher,forward}");
@@ -29,207 +31,21 @@ import("etherpad.pro.pro_accounts.getSessionProAccount");
import("sqlbase.sqlbase");
import("sqlbase.sqlcommon");
import("sqlbase.sqlobj");
+import("etherpad.pad.padutils");
-function tagsToQuery(tags, antiTags) {
- var prefixed = [];
- for (i = 0; i < antiTags.length; i++)
- prefixed[i] = '!' + antiTags[i];
- return tags.concat(prefixed).join(',');
-}
-
-function stringFormat(text, obj) {
- var name;
- for (name in obj) {
- //iterate through the params and replace their placeholders from the original text
- text = text.replace(new RegExp('%\\(' + name + '\\)s', 'gi' ), obj[name]);
- }
- return text;
-}
-
-/* All these sql query functions both takes a querySql object as
- * parameter and returns one. This object has two members - sql and
- * params. Sql is a string of an sql table name or a subqyery in
- * parens. The table pr subquery should have an ID column containing a
- * PAD_ID.
- */
-
-/* Filters pads by tags and anti-tags */
-function getQueryToSql(tags, antiTags, querySql) {
- var queryTable;
- var queryParams;
-
- if (querySql == null) {
- queryTable = 'PAD_META';
- queryParams = [];
- } else {
- queryTable = querySql.sql;
- queryParams = querySql.params;
- }
-
- var exceptArray = [];
- var joinArray = [];
- var whereArray = [];
- var exceptParamArray = [];
- var joinParamArray = [];
-
- var info = new Object();
- info.queryTable = queryTable;
- info.n = 0;
- var i;
-
- for (i = 0; i < antiTags.length; i++) {
- tag = antiTags[i];
- exceptArray.push(
- stringFormat(
- 'left join (PAD_TAG as pt%(n)s ' +
- ' join TAG AS t%(n)s on ' +
- ' t%(n)s.NAME = ? ' +
- ' and t%(n)s.ID = pt%(n)s.TAG_ID) on ' +
- ' pt%(n)s.PAD_ID = p.ID ',
- info));
- whereArray.push(stringFormat('pt%(n)s.TAG_ID is null', info));
- exceptParamArray.push(tag);
- info.n += 1;
- }
- for (i = 0; i < tags.length; i++) {
- tag = tags[i];
- joinArray.push(
- stringFormat(
- 'join PAD_TAG as pt%(n)s on ' +
- ' pt%(n)s.PAD_ID = p.ID ' +
- 'join TAG as t%(n)s on ' +
- ' t%(n)s.ID = pt%(n)s.TAG_ID ' +
- ' and t%(n)s.NAME = ? ',
- info));
- joinParamArray.push(tag);
- info.n += 1;
- }
-
- info["joins"] = joinArray.join(' ');
- info["excepts"] = exceptArray.join(' ');
- info["wheres"] = whereArray.length > 0 ? ' where ' + whereArray.join(' and ') : '';
-
- /* Create a subselect from all the joins */
- return {
- sql: stringFormat(
- '(select distinct ' +
- ' p.ID ' +
- ' from ' +
- ' %(queryTable)s as p ' +
- ' %(joins)s ' +
- ' %(excepts)s ' +
- ' %(wheres)s ' +
- ') ',
- info),
- params: queryParams.concat(joinParamArray).concat(exceptParamArray)};
-}
-
-/* Returns the sql to count the number of results from some other
- * query. */
-function nrSql(querySql) {
- var queryTable;
- var queryParams;
-
- if (querySql == null) {
- queryTable = 'PAD_META';
- queryParams = [];
- } else {
- queryTable = querySql.sql;
- queryParams = querySql.params;
- }
-
- var info = [];
- info['query_sql'] = queryTable
- return {
- sql: stringFormat('(select count(*) as total from %(query_sql)s as q)', info),
- params: queryParams};
-}
-
-/* Returns the sql to select the 10 best new tags to tack on to a
- * query, that is, the tags that are closest to halving the result-set
- * if tacked on. */
-function newTagsSql(querySql) {
- var queryTable;
- var queryParams;
-
- if (querySql == null) {
- queryTable = 'PAD_META';
- queryParams = [];
- } else {
- queryTable = querySql.sql;
- queryParams = querySql.params;
- }
-
- var info = [];
- info["query_post_table"] = queryTable;
- var queryNrSql = nrSql(querySql);
- info["query_nr_sql"] = queryNrSql.sql;
- queryNrParams = queryNrSql.params;
-
- return {
- sql: stringFormat('' +
- 'select ' +
- ' t.NAME tagname, ' +
- ' count(tp.PAD_ID) as matches, ' +
- ' tn.total - count(tp.PAD_ID) as antimatches, ' +
- ' abs(count(tp.PAD_ID) - (tn.total / 2)) as weight ' +
- 'from ' +
- ' TAG as t, ' +
- ' PAD_TAG as tp, ' +
- ' %(query_nr_sql)s as tn ' +
- 'where ' +
- ' tp.TAG_ID = t.ID ' +
- ' and tp.PAD_ID in %(query_post_table)s ' +
- ' and tp.PAD_ID NOT LIKE \'%$%\'' +
- 'group by t.NAME, tn.total ' +
- 'having ' +
- ' count(tp.PAD_ID) > 0 and count(tp.PAD_ID) < tn.total ' +
- 'order by ' +
- ' abs(count(tp.PAD_ID) - (tn.total / 2)) asc ' +
- 'limit 10 ' +
- '', info),
- params: queryNrParams.concat(queryParams)};
-}
-
-function onRequest() {
- var tags = new Array();
- var antiTags = new Array();
-
- if (request.params.query != undefined && request.params.query != '') {
- var query = request.params.query.split(',');
- for (i = 0; i < query.length; i++)
- if (query[i][0] == '!')
- antiTags.push(query[i].substring(1));
- else
- tags.push(query[i]);
- }
+function onRequest() {
+ var tags = tagQuery.queryToTags(request.params.query);
/* Create the pad filter sql */
- var querySql = getQueryToSql(tags.concat(['public']), antiTags);
+ var querySql = tagQuery.getQueryToSql(tags.tags.concat(['public']), tags.antiTags);
/* Use the pad filter sql to figure out which tags to show in the tag browser this time. */
- var queryNewTagsSql = newTagsSql(querySql);
+ var queryNewTagsSql = tagQuery.newTagsSql(querySql);
var newTags = sqlobj.executeRaw(queryNewTagsSql.sql, queryNewTagsSql.params);
- /* Select the 10 last changed matching pads and some extra information on them. Except the Pro Pads*/
- var sql = '' +
- 'select ' +
- ' m.id as ID, ' +
- ' DATE_FORMAT(m.lastWriteTime, \'%a, %d %b %Y %H:%i:%s GMT\') as lastWriteTime, ' +
- ' c.TAGS ' +
- 'from ' +
- querySql.sql + ' as q ' +
- ' join PAD_SQLMETA as m on ' +
- ' m.id = q.ID ' +
- ' join PAD_TAG_CACHE as c on ' +
- ' c.PAD_ID = q.ID ' +
- 'where ' +
- ' m.id NOT LIKE \'%$%\'' +
- 'order by ' +
- ' m.lastWriteTime desc ' +
- 'limit 10';
- var matchingPads = sqlobj.executeRaw(sql, querySql.params);
+ padSql = tagQuery.padInfoSql(querySql, 10);
+ var matchingPads = sqlobj.executeRaw(padSql.sql, padSql.params);
for (i = 0; i < matchingPads.length; i++) {
matchingPads[i].TAGS = matchingPads[i].TAGS.split('#');
@@ -251,12 +67,17 @@ function onRequest() {
var isProUser = (isPro && ! padusers.isGuest(userId));
+ padutils.setOptsAndCookiePrefs(request);
+ var prefs = helpers.getClientVar('cookiePrefsToSet');
+ var bodyClass = (prefs.isFullWidth ? "fullwidth" : "limwidth")
+
var info = {
+ prefs: prefs,
config: appjet.config,
- tagsToQuery: tagsToQuery,
+ tagQuery: tagQuery,
padIdToReadonly: server_utils.padIdToReadonly,
- tags: tags,
- antiTags: antiTags,
+ tags: tags.tags,
+ antiTags: tags.antiTags,
newTags: newTags,
matchingPads: matchingPads,
bodyClass: 'nonpropad',
diff --git a/etherpad/src/plugins/twitterStyleTags/hooks.js b/etherpad/src/plugins/twitterStyleTags/hooks.js
index 003bc32..1072579 100644
--- a/etherpad/src/plugins/twitterStyleTags/hooks.js
+++ b/etherpad/src/plugins/twitterStyleTags/hooks.js
@@ -23,10 +23,10 @@ function padModelWriteToDB(args) {
else
old_tags_str = '';
- var old_tags = old_tags_str != '' ? old_tags_str.split('#') : new Array();
+ // var old_tags = old_tags_str != '' ? old_tags_str.split('#') : new Array();
if (new_tags_str != old_tags_str) {
- log.info({message: 'Updating tags', new_tags:new_tags, old_tags:old_tags});
+ // log.info({message: 'Updating tags', new_tags:new_tags, old_tags:old_tags});
if (old_tags_row)
sqlobj.update("PAD_TAG_CACHE", {PAD_ID: args.padId }, {TAGS: new_tags.join('#')});
@@ -44,4 +44,13 @@ function padModelWriteToDB(args) {
sqlobj.insert("PAD_TAG", {PAD_ID: args.padId, TAG_ID: tag_row['ID']});
}
}
-} \ No newline at end of file
+}
+
+function docbarItemsAll() {
+ return ["<td class='docbarbutton'><a href='/ep/tag/'>Home</a></td>"];
+}
+
+function docbarItemsTagBrowser() {
+ return ["<td class='docbarbutton'><a href='/ep/tag/'>Pads</a></td>"];
+}
+
diff --git a/etherpad/src/plugins/twitterStyleTags/main.js b/etherpad/src/plugins/twitterStyleTags/main.js
index 34d5d85..d64abff 100644
--- a/etherpad/src/plugins/twitterStyleTags/main.js
+++ b/etherpad/src/plugins/twitterStyleTags/main.js
@@ -5,13 +5,15 @@ import("sqlbase.sqlobj");
import("sqlbase.sqlcommon");
function init() {
- this.hooks = ['handlePath', 'aceGetFilterStack', 'aceCreateDomLine', 'padModelWriteToDB'];
+ this.hooks = ['handlePath', 'aceGetFilterStack', 'aceCreateDomLine', 'padModelWriteToDB', 'docbarItemsAll', 'docbarItemsTagBrowser'];
this.client = new main.init();
this.description = 'Twitter-style tags allows the user to tag pads by writing #tagname anywhere in the pad text. Tags are automatically linked to searches for that tag in other pads. This plugin also provides an alternative home-page for Etherpad with a display of the last changed public pads as well as that information available as an RSS stream.';
this.handlePath = hooks.handlePath;
this.aceGetFilterStack = main.aceGetFilterStack;
this.aceCreateDomLine = main.aceCreateDomLine;
this.padModelWriteToDB = hooks.padModelWriteToDB;
+ this.docbarItemsAll = hooks.docbarItemsAll;
+ this.docbarItemsTagBrowser = hooks.docbarItemsTagBrowser;
this.install = install;
this.uninstall = uninstall;
diff --git a/etherpad/src/plugins/twitterStyleTags/models/tagQuery.js b/etherpad/src/plugins/twitterStyleTags/models/tagQuery.js
new file mode 100644
index 0000000..8a32ef7
--- /dev/null
+++ b/etherpad/src/plugins/twitterStyleTags/models/tagQuery.js
@@ -0,0 +1,227 @@
+/**
+ * Copyright 2010 RedHog, Egil Möller <egil.moller@piratpartiet.se>
+ * Copyright 2010 Pita, Peter Martischka <petermartischka@googlemail.com>
+ *
+ * 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.
+ */
+
+import("sqlbase.sqlbase");
+import("sqlbase.sqlcommon");
+import("sqlbase.sqlobj");
+import("etherpad.log");
+
+function tagsToQuery(tags, antiTags) {
+ var prefixed = [];
+ for (i = 0; i < antiTags.length; i++)
+ prefixed[i] = '!' + antiTags[i];
+ return tags.concat(prefixed).join(',');
+}
+
+function queryToTags(query) {
+ var tags = {
+ tags: new Array(),
+ antiTags: new Array()
+ };
+
+ if (query != undefined && query != '') {
+ var query = query.split(',');
+ for (i = 0; i < query.length; i++)
+ if (query[i][0] == '!')
+ tags.antiTags.push(query[i].substring(1));
+ else
+ tags.tags.push(query[i]);
+ }
+ return tags;
+}
+
+function stringFormat(text, obj) {
+ var name;
+ for (name in obj) {
+ //iterate through the params and replace their placeholders from the original text
+ text = text.replace(new RegExp('%\\(' + name + '\\)s', 'gi' ), obj[name]);
+ }
+ return text;
+}
+
+/* All these sql query functions both takes a querySql object as
+ * parameter and returns one. This object has two members - sql and
+ * params. Sql is a string of an sql table name or a subqyery in
+ * parens. The table pr subquery should have an ID column containing a
+ * PAD_ID.
+ */
+
+/* Filters pads by tags and anti-tags */
+function getQueryToSql(tags, antiTags, querySql) {
+ var queryTable;
+ var queryParams;
+
+ if (querySql == null) {
+ queryTable = 'PAD_META';
+ queryParams = [];
+ } else {
+ queryTable = querySql.sql;
+ queryParams = querySql.params;
+ }
+
+ var exceptArray = [];
+ var joinArray = [];
+ var whereArray = [];
+ var exceptParamArray = [];
+ var joinParamArray = [];
+
+ var info = new Object();
+ info.queryTable = queryTable;
+ info.n = 0;
+ var i;
+
+ for (i = 0; i < antiTags.length; i++) {
+ tag = antiTags[i];
+ exceptArray.push(
+ stringFormat(
+ 'left join (PAD_TAG as pt%(n)s ' +
+ ' join TAG AS t%(n)s on ' +
+ ' t%(n)s.NAME = ? ' +
+ ' and t%(n)s.ID = pt%(n)s.TAG_ID) on ' +
+ ' pt%(n)s.PAD_ID = p.ID ',
+ info));
+ whereArray.push(stringFormat('pt%(n)s.TAG_ID is null', info));
+ exceptParamArray.push(tag);
+ info.n += 1;
+ }
+ for (i = 0; i < tags.length; i++) {
+ tag = tags[i];
+ joinArray.push(
+ stringFormat(
+ 'join PAD_TAG as pt%(n)s on ' +
+ ' pt%(n)s.PAD_ID = p.ID ' +
+ 'join TAG as t%(n)s on ' +
+ ' t%(n)s.ID = pt%(n)s.TAG_ID ' +
+ ' and t%(n)s.NAME = ? ',
+ info));
+ joinParamArray.push(tag);
+ info.n += 1;
+ }
+
+ info["joins"] = joinArray.join(' ');
+ info["excepts"] = exceptArray.join(' ');
+ info["wheres"] = whereArray.length > 0 ? ' where ' + whereArray.join(' and ') : '';
+
+ /* Create a subselect from all the joins */
+ return {
+ sql: stringFormat(
+ '(select distinct ' +
+ ' p.ID ' +
+ ' from ' +
+ ' %(queryTable)s as p ' +
+ ' %(joins)s ' +
+ ' %(excepts)s ' +
+ ' %(wheres)s ' +
+ ') ',
+ info),
+ params: queryParams.concat(joinParamArray).concat(exceptParamArray)};
+}
+
+/* Returns the sql to count the number of results from some other
+ * query. */
+function nrSql(querySql) {
+ var queryTable;
+ var queryParams;
+
+ if (querySql == null) {
+ queryTable = 'PAD_META';
+ queryParams = [];
+ } else {
+ queryTable = querySql.sql;
+ queryParams = querySql.params;
+ }
+
+ var info = [];
+ info['query_sql'] = queryTable
+ return {
+ sql: stringFormat('(select count(*) as total from %(query_sql)s as q)', info),
+ params: queryParams};
+}
+
+/* Returns the sql to select the 10 best new tags to tack on to a
+ * query, that is, the tags that are closest to halving the result-set
+ * if tacked on. */
+function newTagsSql(querySql) {
+ var queryTable;
+ var queryParams;
+
+ if (querySql == null) {
+ queryTable = 'PAD_META';
+ queryParams = [];
+ } else {
+ queryTable = querySql.sql;
+ queryParams = querySql.params;
+ }
+
+ var info = [];
+ info["query_post_table"] = queryTable;
+ var queryNrSql = nrSql(querySql);
+ info["query_nr_sql"] = queryNrSql.sql;
+ queryNrParams = queryNrSql.params;
+
+ return {
+ sql: stringFormat('' +
+ 'select ' +
+ ' t.NAME tagname, ' +
+ ' count(tp.PAD_ID) as matches, ' +
+ ' tn.total - count(tp.PAD_ID) as antimatches, ' +
+ ' abs(count(tp.PAD_ID) - (tn.total / 2)) as weight ' +
+ 'from ' +
+ ' TAG as t, ' +
+ ' PAD_TAG as tp, ' +
+ ' %(query_nr_sql)s as tn ' +
+ 'where ' +
+ ' tp.TAG_ID = t.ID ' +
+ ' and tp.PAD_ID in %(query_post_table)s ' +
+ ' and tp.PAD_ID NOT LIKE \'%$%\'' +
+ 'group by t.NAME, tn.total ' +
+ 'having ' +
+ ' count(tp.PAD_ID) > 0 and count(tp.PAD_ID) < tn.total ' +
+ 'order by ' +
+ ' abs(count(tp.PAD_ID) - (tn.total / 2)) asc ' +
+ 'limit 10 ' +
+ '', info),
+ params: queryNrParams.concat(queryParams)};
+}
+
+/* Select the X last changed matching pads and some extra information
+ * on them. Except the Pro Pads*/
+function padInfoSql(querySql, limit, offset) {
+ var sql = '' +
+ 'select ' +
+ ' m.id as ID, ' +
+ ' DATE_FORMAT(m.lastWriteTime, \'%a, %d %b %Y %H:%i:%s GMT\') as lastWriteTime, ' +
+ ' c.TAGS ' +
+ 'from ' +
+ querySql.sql + ' as q ' +
+ ' join PAD_SQLMETA as m on ' +
+ ' m.id = q.ID ' +
+ ' join PAD_TAG_CACHE as c on ' +
+ ' c.PAD_ID = q.ID ' +
+ 'where ' +
+ ' m.id NOT LIKE \'%$%\'' +
+ 'order by ' +
+ ' m.lastWriteTime desc ';
+ if (limit != undefined)
+ sql += 'limit ' + limit + " ";
+ if (offset != undefined)
+ sql += 'offset ' + offset + " ";
+ return {
+ sql: sql,
+ params: querySql.params
+ };
+}
diff --git a/etherpad/src/plugins/twitterStyleTags/static/css/tagBrowser.css b/etherpad/src/plugins/twitterStyleTags/static/css/tagBrowser.css
index f3321a4..55fcda2 100644
--- a/etherpad/src/plugins/twitterStyleTags/static/css/tagBrowser.css
+++ b/etherpad/src/plugins/twitterStyleTags/static/css/tagBrowser.css
@@ -76,7 +76,7 @@ h1 {
}
#editbarinner {
- line-height: 36px;
+ line-height: 29px;
font-size: 16px;
padding-left: 6pt;
}
diff --git a/etherpad/src/plugins/twitterStyleTags/templates/tagBrowser.ejs b/etherpad/src/plugins/twitterStyleTags/templates/tagBrowser.ejs
index 1f33eb8..e101196 100644
--- a/etherpad/src/plugins/twitterStyleTags/templates/tagBrowser.ejs
+++ b/etherpad/src/plugins/twitterStyleTags/templates/tagBrowser.ejs
@@ -14,35 +14,11 @@ 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. */ %>
<%
+ template.inherit('page.ejs');
helpers.setHtmlTitle("EtherPad: Browse tags");
helpers.includeCss("plugins/twitterStyleTags/tagBrowser.css");
helpers.includeCss("plugins/twitterStyleTags/pad.css");
- helpers.setBodyId("padbody");
- helpers.addBodyClass("limwidth nonpropad nonprouser");
- helpers.includeCss("pad2_ejs.css");
- helpers.includeJs("undo-xpopup.js");
- helpers.includeCometJs();
- helpers.includeJQuery();
- helpers.includeJs("json2.js");
- helpers.includeJs("colorutils.js");
- helpers.includeJs("ace.js");
- helpers.includeJs("collab_client.js");
- helpers.includeJs("draggable.js");
- helpers.includeJs("pad_utils.js");
- helpers.includeJs("pad_cookie.js");
- helpers.includeJs("pad_editor.js");
- helpers.includeJs("pad_userlist.js");
- helpers.includeJs("pad_editbar.js");
- helpers.includeJs("pad_chat.js");
- helpers.includeJs("pad_docbar.js");
- helpers.includeJs("pad_impexp.js");
- helpers.includeJs("pad_savedrevs.js");
- helpers.includeJs("pad_connectionstatus.js");
- helpers.includeJs("pad_modals.js");
- helpers.includeJs("pad2.js");
- helpers.suppressGA();
- helpers.setRobotsPolicy({index: false, follow: false});
- helpers.addToHead('\n<link rel="alternate" href="/ep/tag/?query=' + tagsToQuery(tags, antiTags) + '&format=rss" type="application/rss+xml" title="Query results as RSS" />\n');
+ helpers.addToHead('\n<link rel="alternate" href="' + helpers.updateToUrl({format:'rss'}) + '" type="application/rss+xml" title="Query results as RSS" />\n');
function inArray(item, arr) {
for (var i = 0; i < arr.length; i++)
@@ -51,108 +27,89 @@ limitations under the License. */ %>
return false;
}
%>
+<% template.define('docBarTitle', function() { var ejs_data=''; %>
+ <td id="docbarpadtitle"><span>Browse Tags</span></td>
+<% return ejs_data; }); %>
-<div id="padpage">
- <div id="padtop">
- <div id="topbar">
- <div id="topbarleft"><!-- --></div>
- <div id="topbarright"><!-- --></div>
- <div id="topbarcenter"><a href="/" id="topbaretherpad">EtherPad</a></div>
- <% if (isProAccountHolder) { %>
- <div id="accountnav"><%= toHTML(account.email) %><a href="/ep/account/sign-out">(sign out)</a></div>
- <% } else if (isPro) { %>
- <div id="accountnav"><a href="<%= signinUrl %>">sign in</a></div>
+<%
+ template.define('docBarItems', function() {
+ return plugins.callHookStr('docbarItemsTagBrowserPad', {}, '', '', '') +
+ plugins.callHookStr('docbarItemsTagBrowser', {}, '', '', '');
+ });
+%>
+
+<% template.define('sideBar', function() { var ejs_data=''; %>
+ <div id="padusers">
+ <% if (isProAccountEnabled()) { %>
+ <a href="/ep/pad/newpad" style="padding: 25px 0" id="home-newpad">
+ Create new pad
+ </a>
+ <a href="/ep/pro-signup/" style="padding: 25px 0" id="home-newteam">
+ Create new team
+ </a>
+ <% } else { %>
+ <a href="/ep/pad/newpad" id="home-newpad">
+ Create new pad
+ </a>
<% } %>
</div>
- <div id="docbar">
- <table border="0" cellpadding="0" cellspacing="0" width="100%" id="docbartable">
- <td><img src="/static/img/jun09/pad/roundcorner_left.gif"></td>
- <td id="docbarpadtitle"><span>Browse Tags</span></td>
- <td width="100%">&nbsp;</td>
- <td><img src="/static/img/jun09/pad/roundcorner_right.gif"></td>
- </table>
- </div>
- <div id="padmain">
- <div id="padsidebar">
- <div id="padusers">
- <% if (isProAccountEnabled()) { %>
- <a href="/ep/pad/newpad" style="padding: 25px 0" id="home-newpad">
- Create new pad
- </a>
- <a href="/ep/pro-signup/" style="padding: 25px 0" id="home-newteam">
- Create new team
- </a>
- <% } else { %>
- <a href="/ep/pad/newpad" id="home-newpad">
- Create new pad
- </a>
- <% } %>
- </div>
+ <div id="hdraggie"><!-- --></div>
- <div id="hdraggie"><!-- --></div>
+ <div id="padchat"><iframe src="<%= config['motdPage'] %>" width="100%" height="100%"></iframe></div>
+<% return ejs_data; }); %>
- <div id="padchat"><iframe src="<%= config['motdPage'] %>" width="100%" height="100%"></iframe></div>
- </div> <!-- /padsidebar -->
-
- <div id="padeditor">
- <div id="editbar" class="enabledtoolbar">
- <div id="editbarleft"><!-- --></div>
- <div id="editbarright"><!-- --></div>
-
- <div id="editbarinner">
- Query:
- <% if (tags.length == 0 && antiTags.length == 0) { %>
- Latest changed pads
- <% } else { %>
- <% for (i = 0; i < tags.length; i++) { %>
- <a href="/ep/tag/?query=<%= tagsToQuery(tags.filter(function (tag) { return tag != tags[i]}), antiTags) %>" class="padtag" title="<%= tags[i] %> matches">#<%= tags[i] %></a>
- <% } %>
- <% for (i = 0; i < antiTags.length; i++) { %>
- <a href="/ep/tag/?query=<%= tagsToQuery(tags, antiTags.filter(function (tag) { return tag != antiTags[i]})) %>" class="anti_padtag" title="<%= antiTags[i] %> matches">!#<%= antiTags[i] %></a>
- <% } %>
- <% } %>
- </div>
- </div>
- <div id="editorcontainerbox">
- <div id="editorcontainer">
- <div class="query-refiner">
- <h1>Search for pads that have the tag</h1>
- <% for (i = 0; i < newTags.length; i++) { %>
- <a href="/ep/tag/?query=<%= tagsToQuery(tags.concat([newTags[i].tagname]),antiTags) %>" class="padtag" title="<%= newTags[i].matches %> matches">#<%= newTags[i].tagname %></a>
- <% } %>
+<% template.define('editBarItemsLeft', function() { var ejs_data=''; %>
+ <td>
+ Query:
+ <% if (tags.length == 0 && antiTags.length == 0) { %>
+ Latest changed pads
+ <% } else { %>
+ <% for (i = 0; i < tags.length; i++) { %>
+ <a href="<%= helpers.updateToUrl({query:tagQuery.tagsToQuery(tags.filter(function (tag) { return tag != tags[i]}), antiTags)}) %>" class="padtag" title="<%= tags[i] %> matches">#<%= tags[i] %></a>
+ <% } %>
+ <% for (i = 0; i < antiTags.length; i++) { %>
+ <a href="<%= helpers.updateToUrl({query:tagQuery.tagsToQuery(tags, antiTags.filter(function (tag) { return tag != antiTags[i]}))}) %>" class="anti_padtag" title="<%= antiTags[i] %> matches">!#<%= antiTags[i] %></a>
+ <% } %>
+ <% } %>
+ </td>
+<% return ejs_data; }); %>
- <h1>Search for pads that <em>don't</em> have the tag</h1>
- <% for (i = 0; i < newTags.length; i++) { %>
- <a href="/ep/tag/?query=<%= tagsToQuery(tags,antiTags.concat([newTags[i].tagname])) %>" class="anti_padtag" title="<%= newTags[i].antimatches %> matches">!#<%= newTags[i].tagname %></a>
- <% } %>
- </div>
+<% template.define('contentArea', function() { var ejs_data=''; %>
+ <div id="editorcontainer">
+ <div class="query-refiner">
+ <%: template.use('queryRefiner', function() { var ejs_data=''; %>
+ <h1>Search for pads that have the tag</h1>
+ <% for (i = 0; i < newTags.length; i++) { %>
+ <a href="<%= helpers.updateToUrl({query:tagQuery.tagsToQuery(tags.concat([newTags[i].tagname]),antiTags)}) %>" class="padtag" title="<%= newTags[i].matches %> matches">#<%= newTags[i].tagname %></a>
+ <% } %>
- <dl>
- <% for (i = 0; i < matchingPads.length; i++) { %>
- <%
- var matchingPadId = matchingPads[i].ID;
- var matchingPadUrl = matchingPadId;
- if (!inArray('writable', matchingPads[i].TAGS)) {
- matchingPadId = padIdToReadonly(matchingPads[i].ID);
- matchingPadUrl = 'ep/pad/view/' + matchingPadId + '/latest';
- }
- %>
- <dt><a href="/<%= matchingPadUrl %>"><%= matchingPadId %></a><dt>
- <dd>
- <% for (j = 0; j < matchingPads[i].TAGS.length; j++) { %>
- <a href="/ep/tag/?query=<%= tagsToQuery(tags.concat([matchingPads[i].TAGS[j]]), antiTags) %>" class="padtag" title="<%= matchingPads[i].TAGS[j] %> matches">#<%= matchingPads[i].TAGS[j] %></a>
- <% } %>
- </dd>
- <% } %>
- </dl>
- </div>
- </div>
- </div><!-- /padeditor -->
+ <h1>Search for pads that <em>don't</em> have the tag</h1>
+ <% for (i = 0; i < newTags.length; i++) { %>
+ <a href="<%= helpers.updateToUrl({query:tagQuery.tagsToQuery(tags,antiTags.concat([newTags[i].tagname]))}) %>" class="anti_padtag" title="<%= newTags[i].antimatches %> matches">!#<%= newTags[i].tagname %></a>
+ <% } %>
+ <% return ejs_data; }); %>
+ </div>
- <div id="bottomarea">
- <div id="widthprefcheck" class="widthprefunchecked"><!-- --></div>
- <div id="sidebarcheck" class="sidebarchecked"><!-- --></div>
+ <dl>
+ <%: template.use('queryResult', function() { var ejs_data=''; %>
+ <% for (i = 0; i < matchingPads.length; i++) { %>
+ <%
+ var matchingPadId = matchingPads[i].ID;
+ var matchingPadUrl = matchingPadId;
+ if (!inArray('writable', matchingPads[i].TAGS)) {
+ matchingPadId = padIdToReadonly(matchingPads[i].ID);
+ matchingPadUrl = 'ep/pad/view/' + matchingPadId + '/latest';
+ }
+ %>
+ <dt><a href="/<%= matchingPadUrl %>"><%= matchingPadId %></a><dt>
+ <dd>
+ <% for (j = 0; j < matchingPads[i].TAGS.length; j++) { %>
+ <a href="<%= helpers.updateToUrl({query:tagQuery.tagsToQuery(tags.concat([matchingPads[i].TAGS[j]]), antiTags)}) %>" class="padtag" title="<%= matchingPads[i].TAGS[j] %> matches">#<%= matchingPads[i].TAGS[j] %></a>
+ <% } %>
+ </dd>
+ <% } %>
+ <% return ejs_data; }); %>
+ </dl>
</div>
- </div>
-</div>
+<% return ejs_data; }); %>
diff --git a/etherpad/src/plugins/urlIndexer/controllers/urlBrowser.js b/etherpad/src/plugins/urlIndexer/controllers/urlBrowser.js
new file mode 100644
index 0000000..cdb9602
--- /dev/null
+++ b/etherpad/src/plugins/urlIndexer/controllers/urlBrowser.js
@@ -0,0 +1,132 @@
+/**
+ * Copyright 2009 RedHog, Egil Möller <egil.moller@piratpartiet.se>
+ * Copyright 2010 Pita, Peter Martischka <petermartischka@googlemail.com>
+ *
+ * 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.
+ */
+
+import("plugins.twitterStyleTags.models.tagQuery");
+
+import("faststatic");
+import("dispatch.{Dispatcher,PrefixMatcher,forward}");
+
+import("etherpad.utils.*");
+import("etherpad.collab.server_utils");
+import("etherpad.globals.*");
+import("etherpad.log");
+import("etherpad.pad.padusers");
+import("etherpad.pro.pro_utils");
+import("etherpad.helpers");
+import("etherpad.pro.pro_accounts.getSessionProAccount");
+import("sqlbase.sqlbase");
+import("sqlbase.sqlcommon");
+import("sqlbase.sqlobj");
+import("etherpad.pad.padutils");
+
+function urlSql(querySql, limit, offset) {
+ var sql = '' +
+ 'select ' +
+ ' u.URL, ' +
+ ' m.id as ID, ' +
+ ' DATE_FORMAT(m.lastWriteTime, \'%a, %d %b %Y %H:%i:%s GMT\') as lastWriteTime, ' +
+ ' c.TAGS ' +
+ 'from ' +
+ querySql.sql + ' as q ' +
+ ' join PAD_SQLMETA as m on ' +
+ ' m.id = q.ID ' +
+ ' join PAD_TAG_CACHE as c on ' +
+ ' c.PAD_ID = q.ID ' +
+ ' join PAD_URL as u on ' +
+ ' u.PAD_ID = q.ID ' +
+ 'where ' +
+ ' m.id NOT LIKE \'%$%\'' +
+ 'order by ' +
+ ' u.URL asc ';
+ if (limit != undefined)
+ sql += 'limit ' + limit + " ";
+ if (offset != undefined)
+ sql += 'offset ' + offset + " ";
+ return {
+ sql: sql,
+ params: querySql.params
+ };
+}
+
+function onRequest() {
+ var tags = tagQuery.queryToTags(request.params.query);
+
+ /* Create the pad filter sql */
+ var querySql = tagQuery.getQueryToSql(tags.tags.concat(['public']), tags.antiTags);
+
+ /* Use the pad filter sql to figure out which tags to show in the tag browser this time. */
+ var queryNewTagsSql = tagQuery.newTagsSql(querySql);
+ var newTags = sqlobj.executeRaw(queryNewTagsSql.sql, queryNewTagsSql.params);
+
+ url = urlSql(querySql, 10);
+ var matchingUrls = sqlobj.executeRaw(url.sql, url.params);
+
+ for (i = 0; i < matchingUrls.length; i++) {
+ matchingUrls[i].TAGS = matchingUrls[i].TAGS.split('#');
+ }
+
+ var isPro = pro_utils.isProDomainRequest();
+ var userId = padusers.getUserId();
+
+ helpers.addClientVars({
+ userAgent: request.headers["User-Agent"],
+ debugEnabled: request.params.djs,
+ clientIp: request.clientAddr,
+ colorPalette: COLOR_PALETTE,
+ serverTimestamp: +(new Date),
+ isProPad: isPro,
+ userIsGuest: padusers.isGuest(userId),
+ userId: userId,
+ });
+
+ var isProUser = (isPro && ! padusers.isGuest(userId));
+
+ padutils.setOptsAndCookiePrefs(request);
+ var prefs = helpers.getClientVar('cookiePrefsToSet');
+ var bodyClass = (prefs.isFullWidth ? "fullwidth" : "limwidth")
+
+ var info = {
+ prefs: prefs,
+ config: appjet.config,
+ tagQuery: tagQuery,
+ padIdToReadonly: server_utils.padIdToReadonly,
+ tags: tags.tags,
+ antiTags: tags.antiTags,
+ newTags: newTags,
+ matchingPads: [],
+ matchingUrls: matchingUrls,
+ bodyClass: 'nonpropad',
+ isPro: isPro,
+ isProAccountHolder: isProUser,
+ account: getSessionProAccount(), // may be falsy
+ };
+
+ var format = "html";
+ if (request.params.format != undefined)
+ format = request.params.format;
+
+ if (format == "html")
+ renderHtml("urlBrowser.ejs", info, ['urlIndexer', 'twitterStyleTags']);
+ else if (format == "rss") {
+ response.setContentType("application/xml; charset=utf-8");
+ response.write(renderTemplateAsString("tagRss.ejs", info, 'urlIndexer'));
+ if (request.acceptsGzip) {
+ response.setGzip(true);
+ }
+ }
+ return true;
+}
diff --git a/etherpad/src/plugins/urlIndexer/hooks.js b/etherpad/src/plugins/urlIndexer/hooks.js
new file mode 100644
index 0000000..e0ff050
--- /dev/null
+++ b/etherpad/src/plugins/urlIndexer/hooks.js
@@ -0,0 +1,49 @@
+import("etherpad.log");
+import("dispatch.{Dispatcher,PrefixMatcher,forward}");
+import("sqlbase.sqlobj");
+import("plugins.urlIndexer.controllers.urlBrowser");
+
+function handlePath() {
+ return [[PrefixMatcher('/ep/url'), forward(urlBrowser)]];
+}
+
+REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/;
+REGEX_URLCHAR = new RegExp('('+/[-:@a-zA-Z0-9_.,~%+\/\\?=&#;()$]/.source+'|'+REGEX_WORDCHAR.source+')');
+REGEX_URL = new RegExp(/(?:(?:https?|s?ftp|ftps|file|smb|afp|nfs|(x-)?man|gopher|txmt):\/\/|mailto:)/.source+REGEX_URLCHAR.source+'*(?![:.,;])'+REGEX_URLCHAR.source, 'g');
+
+function padModelWriteToDB(args) {
+ /* Update tags for the pad */
+
+ var new_urls = args.pad.text().match(REGEX_URL);
+ if (new_urls == null) new_urls = new Array();
+ var new_urls_str = new_urls.join(' ')
+
+ var old_urls_row = sqlobj.selectSingle("PAD_URL_CACHE", { PAD_ID: args.padId });
+ var old_urls_str;
+ if (old_urls_row !== null)
+ old_urls_str = old_urls_row['URLS'];
+ else
+ old_urls_str = '';
+
+ // var old_urls = old_urls_str != '' ? old_urls_str.split(' ') : new Array();
+
+ if (new_urls_str != old_urls_str) {
+ // log.info({message: 'Updating urls', new_urls:new_urls, old_urls:old_urls});
+
+ if (old_urls_row)
+ sqlobj.update("PAD_URL_CACHE", {PAD_ID: args.padId }, {URLS: new_urls.join(' ')});
+ else
+ sqlobj.insert("PAD_URL_CACHE", {PAD_ID: args.padId, URLS: new_urls.join(' ')});
+
+ sqlobj.deleteRows("PAD_URL", {PAD_ID: args.padId});
+
+ for (i = 0; i < new_urls.length; i++) {
+ sqlobj.insert("PAD_URL", {PAD_ID: args.padId, URL: new_urls[i]});
+ }
+ }
+}
+
+function docbarItemsTagBrowser() {
+ return ["<td class='docbarbutton'><a href='/ep/url/'>URLs</a></td>"];
+}
+
diff --git a/etherpad/src/plugins/urlIndexer/main.js b/etherpad/src/plugins/urlIndexer/main.js
new file mode 100644
index 0000000..18bdef1
--- /dev/null
+++ b/etherpad/src/plugins/urlIndexer/main.js
@@ -0,0 +1,34 @@
+import("etherpad.log");
+import("plugins.urlIndexer.hooks");
+import("sqlbase.sqlobj");
+import("sqlbase.sqlcommon");
+
+function init() {
+ this.hooks = ['padModelWriteToDB', 'handlePath', 'docbarItemsTagBrowser'];
+ this.description = 'Indexes URLs linked to in pads so that they can be displayed outside pads, searched for etc.';
+ this.padModelWriteToDB = hooks.padModelWriteToDB;
+ this.handlePath = hooks.handlePath;
+ this.docbarItemsTagBrowser = hooks.docbarItemsTagBrowser;
+
+ this.install = install;
+ this.uninstall = uninstall;
+}
+
+function install() {
+ log.info("Installing urlIndexer");
+
+ sqlobj.createTable('PAD_URL', {
+ PAD_ID: 'varchar(128) character set utf8 collate utf8_bin not null references PAD_META(ID)',
+ URL: 'varchar(1024) character set utf8 collate utf8_bin not null',
+ });
+
+ sqlobj.createTable('PAD_URL_CACHE', {
+ PAD_ID: 'varchar(128) character set utf8 collate utf8_bin unique not null references PAD_META(ID)',
+ URLS: 'text collate utf8_bin not null',
+ });
+}
+
+function uninstall() {
+ log.info("Uninstalling urlIndexer");
+}
+
diff --git a/etherpad/src/plugins/urlIndexer/templates/urlBrowser.ejs b/etherpad/src/plugins/urlIndexer/templates/urlBrowser.ejs
new file mode 100644
index 0000000..1996dc5
--- /dev/null
+++ b/etherpad/src/plugins/urlIndexer/templates/urlBrowser.ejs
@@ -0,0 +1,53 @@
+<% /*
+Copyright 2009 Google Inc.
+Copyright 2010 Pita, Peter Martischka <petermartischka@googlemail.com>
+
+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. */ %>
+<%
+ template.inherit('tagBrowser.ejs');
+ helpers.setHtmlTitle("EtherPad: Browse URLs by tags");
+ helpers.includeCss("plugins/twitterStyleTags/tagBrowser.css");
+ helpers.includeCss("plugins/twitterStyleTags/pad.css");
+ helpers.addToHead('\n<link rel="alternate" href="' + helpers.updateToUrl({format:'rss'}) + '" type="application/rss+xml" title="Query results as RSS" />\n');
+
+ function inArray(item, arr) {
+ for (var i = 0; i < arr.length; i++)
+ if (arr[i] == item)
+ return true;
+ return false;
+ }
+%>
+
+<% template.define('docBarTitle', function() { var ejs_data=''; %>
+ <td id="docbarpadtitle"><span>Browse URLs by tags</span></td>
+<% return ejs_data; }); %>
+
+<% template.define('queryResult', function() { var ejs_data=''; %>
+ <% for (i = 0; i < matchingUrls.length; i++) { %>
+ <%
+ var matchingPadId = matchingUrls[i].ID;
+ var matchingPadUrl = matchingPadId;
+ if (!inArray('writable', matchingUrls[i].TAGS)) {
+ matchingPadId = padIdToReadonly(matchingUrls[i].ID);
+ matchingPadUrl = 'ep/pad/view/' + matchingPadId + '/latest';
+ }
+ %>
+ <dt><a href="<%= matchingUrls[i].URL %>"><%= matchingUrls[i].URL %></a><dt>
+ <dd>
+ <a href="<%= matchingPadUrl %>"><%= matchingPadId %></a>:
+ <% for (j = 0; j < matchingUrls[i].TAGS.length; j++) { %>
+ <a href="<%= helpers.updateToUrl({query:tagQuery.tagsToQuery(tags.concat([matchingUrls[i].TAGS[j]]), antiTags)}) %>" class="padtag" title="<%= matchingUrls[i].TAGS[j] %> matches">#<%= matchingUrls[i].TAGS[j] %></a>
+ <% } %>
+ </dd>
+ <% } %>
+<% return ejs_data; }); %>
diff --git a/etherpad/src/static/css/pad2_ejs.css b/etherpad/src/static/css/pad2_ejs.css
index 08e95d2..0519a9d 100644
--- a/etherpad/src/static/css/pad2_ejs.css
+++ b/etherpad/src/static/css/pad2_ejs.css
@@ -68,31 +68,31 @@ a#hidetopmsg { position: absolute; right: 5px; bottom: 5px; }
.docbarbutton
{
- padding: 2px;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ padding-left: 4px;
+ padding-right: 4px;
border-left: 1px solid #CCC;
white-space: nowrap;
- vertical-align: top;
}
.docbarbutton img
{
border: 0px;
width: 13px;
- height: 13px;
margin-right: 2px;
- position:relative;
- top: 3px;
+ vertical-align: middle;
+ margin-top: 3px;
+ margin-bottom: 2px;
}
.docbarbutton a
{
- font-size:10px;
+ font-size: 10px;
+ line-height: 18px;
text-decoration: none;
color: #444;
font-weight: bold;
- margin:0 2px;
- position:relative;
- top: 1px;
}
.docbarbutton.highlight
@@ -166,9 +166,9 @@ a#hidetopmsg { position: absolute; right: 5px; bottom: 5px; }
{
position:absolute;
top: 6px;
- left: 570px;
+ right: 7px;
height: 24px;
- width:15px;
+ width:23px;
}
#editbarsavetable td, #editbartable td
diff --git a/etherpad/src/static/js/broadcast.js b/etherpad/src/static/js/broadcast.js
index 9fa8141..8ea0a15 100644
--- a/etherpad/src/static/js/broadcast.js
+++ b/etherpad/src/static/js/broadcast.js
@@ -15,6 +15,7 @@
*/
// 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)
{
Array.prototype.map = function(fun /*, thisp*/)
@@ -35,6 +36,7 @@ if (!Array.prototype.map)
};
}
+// Below Array#forEach code was direct pasted by AppJet/Etherpad, licence unknown. Possible source: http://www.tutorialspoint.com/javascript/array_foreach.htm
if (!Array.prototype.forEach)
{
Array.prototype.forEach = function(fun /*, thisp*/)
@@ -52,6 +54,7 @@ if (!Array.prototype.forEach)
};
}
+// Below Array#indexOf code was direct pasted by AppJet/Etherpad, licence unknown. Possible source: http://www.tutorialspoint.com/javascript/array_indexof.htm
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(elt /*, from*/)
diff --git a/etherpad/src/static/js/broadcast_slider.js b/etherpad/src/static/js/broadcast_slider.js
index 255d7f2..8977e3d 100644
--- a/etherpad/src/static/js/broadcast_slider.js
+++ b/etherpad/src/static/js/broadcast_slider.js
@@ -138,7 +138,7 @@ var global = this;
swatchtd.append(swatch);
tr.append(swatchtd);
var nametd = $('<td></td>');
- nametd.html(author.name || "unnamed");
+ nametd.text(author.name || "unnamed");
tr.append(nametd);
$("#authorstable").append(tr);
} else {
diff --git a/etherpad/src/static/js/pad.js.old b/etherpad/src/static/js/pad.js.old
deleted file mode 100644
index 6191b31..0000000
--- a/etherpad/src/static/js/pad.js.old
+++ /dev/null
@@ -1,1984 +0,0 @@
-//----------------------------------------------------------------
-// initialization
-//----------------------------------------------------------------
-
-$(document).ready(function() {
- if (!pad.initialized) {
- pad.init();
- }
-});
-
-$(window).unload(function() {
- if (pad.ace) {
- pad.ace.destroy();
- }
-});
-
-pad = {
- initTime: 0,
- initialized: false,
- myUserInfo: null, /* userInfo for this client's user */
- debugEnabled: false,
- userBoxIds: {},
- lastBoxId: 0,
- connectionState: 'DISCONNECTED',
- notifyQueue: [],
- lastNotify: 0,
- persistLastNotify: false,
- collabClient: null,
- users: {},
- ace: null,
- padId: null,
- wrapLines: true,
- initialCookiePrefs: {},
- revisionList: [],
- clientTimeOffset: (+new Date()) - clientVars.serverTimestamp,
- REVISIONCOUNT_STEP: 5,
- shownRevisions: 5,
- sideBarVisible: true,
- sideBoxVisibility: {},
- diagnosticInfo: {},
- experiencingConnectionTrouble: false,
- padHasFocus: true,
- isFreshCookie: false,
- viewZoom: 100,
- title: null,
- password: null,
- isEditingTitle: false
-};
-
-pad.initCookie = function() {
- pad.initialCookiePrefs = pad.getInitialCookiePrefs();
-};
-
-pad.initPrefsPane = function() {
- // Setup checkbox prefs.
- function scbp(n, v) {
- var t = pad.initialCookiePrefs[v];
- pad.markPref(n, t);
- }
- scbp('wrap', 'wrapLines');
- scbp('showcolors', 'showAuthorColors');
- scbp('linenums', 'showLineNumbers');
- scbp('fullwidth', 'fullWidth');
-
- pad.setFullWidth(pad.initialCookiePrefs.fullWidth);
-
- // events
- function prefclick(elt) {
- var d = $(elt);
- var name = d.attr('id').substr("checkpref".length);
- var t = !pad.isPrefMarked(name);
- pad.markPref(name, t);
- pad.updatePref(name, t);
- pad.saveCookie();
- }
- $('div.prefcheckbox').mousedown(function(e) {
- prefclick(this);
- e.preventDefault();
- return false;
- });
- $('div.prefcheckbox').mouseup(pad.handlerPreventDefault);
- $('div.prefcheckbox').click(pad.handlerPreventDefault);
-};
-
-pad.initAce = function(donefunc) {
-
- // ACE functions.
- function editorReady() {
- $('#editorcell').removeClass('editorcell_loading').addClass('editorcell_loaded');
- $('#sidebar').removeClass('sidebar_loading');
- $('#loadingbox').remove();
- $(window).bind("resize", pad.resizePage);
- setTimeout(function() { ace.focus(); pad.resizePage(); }, 0);
- donefunc();
- }
-
- // Setup ace.
- pad.dmesg("pad.init(): loading Ace2Editor");
- var ace = new Ace2Editor();
- ace.init("editorcontainer", "", editorReady);
- ace.setProperty("wraps", pad.initialCookiePrefs.wrapLines);
- ace.setProperty("showsAuthorColors", pad.initialCookiePrefs.showAuthorColors);
- ace.setProperty("lineNumbers", pad.initialCookiePrefs.showLineNumbers);
- if (pad.initialCookiePrefs.highlightJs === true) {
- ace.setProperty("lexer", "js");
- pad.markPref('jshighlight', true);
- } else {
- ace.setProperty("lexer", "txt");
- pad.markPref('jshighlight', false);
- }
- // star window title on dirty
- ace.setNotifyDirty(function() {
- if (!pad.padHasFocus) {
- var currentTitle = $(document).attr('title');
- if (currentTitle.charAt(0) != '*') {
- $(document).attr('title', '* '+currentTitle);
- }
- }
- });
- if (pad.debugEnabled) {
- ace.setProperty("dmesg", pad.dmesg);
- }
-
- pad.ace = ace;
-};
-
-pad.initMyUserInfo = function() {
- // assigned colorId
- var colorId = clientVars.assignedColorId;
- if (!clientVars.colorPalette[colorId]) {
- colorId = Math.floor((Math.random() * clientVars.colorPalette.length));
- }
-
- // Populate user info.
- pad.dmesg("clientVars: "+JSON.stringify(clientVars));
- pad.myUserInfo = {
- userId: (pad.initialCookiePrefs.userId || pad.uniqueId()),
- name: pad.getDefaultUsername(),
- ip: clientVars.clientIp,
- colorId: colorId,
- userAgent: pad.uaDisplay(clientVars.userAgent)
- };
-
- pad.userJoin(pad.myUserInfo);
- pad.dmesg("myUserInfo: "+JSON.stringify(pad.myUserInfo));
-};
-
-pad.initSideBoxes = function() {
- // expand side-bars if cookie indicates
- for (paneName in pad.initialCookiePrefs.sideBoxVisibility) {
- if (pad.initialCookiePrefs.sideBoxVisibility[paneName]) {
- pad.showSideBox(paneName);
- }
- }
-};
-
-pad.initCollab = function() {
- var collabOptions = {
- colorPalette: clientVars.colorPalette
- };
- pad.collabClient = getCollabClient(pad.ace,
- clientVars.collab_client_vars,
- pad.myUserInfo,
- collabOptions);
-
- pad.collabClient.setOnClientMessage(pad.onClientMessage);
- pad.collabClient.setOnServerMessage(pad.onServerMessage);
- pad.collabClient.setOnUserJoin(pad.userJoin);
- pad.collabClient.setOnUserLeave(pad.userLeave);
- pad.collabClient.setOnUpdateUserInfo(pad.updateUserInfo);
- pad.collabClient.setOnChannelStateChange(pad.channelStateChange);
- pad.collabClient.setOnConnectionTrouble(pad.onConnectionTrouble);
-};
-
-pad.initRevisions = function() {
- // Render revision list.
- pad.revisionList = clientVars.initialRevisionList;
- pad.renderRevisionList();
-
- // Events
- $('#savenow').click(function(e) {
- pad.saveRevision();
- e.preventDefault();
- return false;
- });
- setInterval(function() {
- pad.renderRevisionList(true);
- }, (2*60*1000)); // to update times correctly
-};
-
-pad.initEvents = function() {
- // shareurl click
- $("#headurl").click(function() { selectElementContents($("#shareurl").get(0)); });
-
- // feedback form
- $('#feedbacksubmit').click(function(e) {
- pad.submitfeedback();
- e.preventDefault();
- return false;
- });
-
- // sidepane expand/collapse events
- $('#sidebar div.sideheadwrap').mousedown(function(e) {
- var paneName = $(this).attr('id').substr("head".length);
- if (pad.isSideBoxVisible(paneName)) {
- pad.hideSideBox(paneName);
- } else {
- pad.showSideBox(paneName);
- }
- e.preventDefault();
- return false;
- });
- $('#sidebar div.sideheadwrap').mouseup(pad.handlerPreventDefault);
- $('#sidebar div.sideheadwrap').click(pad.handlerPreventDefault);
-
- // ---- share link ----
- $('#invitemore').show();
- $('#invite_email_submit').click(pad.invitemoreSendEmail);
- pad.setOnEnterKey('#invite_email, #invite_email_submit', pad.invitemoreSendEmail);
-
- // ---- force reconnect ----
- $('button.forcereconnect').click(function() {
- pad.forceReconnect();
- });
-};
-
-pad.initFocusTracker = function() {
- var myFrames = [];
- function walkframes(frame, depth) {
- try {
- if (depth > 4) { return; }
- myFrames.push(frame);
- $(frame).contents().find('iframe').each(function() {
- walkframes(this, depth+1);
- });
- } catch (ex) {/*swallow*/}
- }
- myFrames.push($(window));
- $('iframe').each(function() { walkframes(this, 1); });
-
- function onFocus() { pad.padHasFocus = true; }
- function onBlur() { pad.padHasFocus = false; }
-
- for (var i = 0; i < myFrames.length; i++) {
- var f = myFrames[i];
- $(f).focus(onFocus).blur(onBlur);
- /*
- if (f.contentDocument) {
- $(f.contentDocument).click(onFocus);
- }*/
- }
- /* $(document).click(onFocus); */
-
- // Reclaim the title periodically
- var focusedLastCheck = true;
- setInterval(function() {
- if (!focusedLastCheck && pad.padHasFocus) {
- $(document).attr('title', 'EtherPad: '+pad.padId);
- }
- focusedLastCheck = pad.padHasFocus;
- }, 1000);
-};
-
-pad.initWelcomeMessage = function() {
- if (pad.isFreshCookie && (clientVars.numConnectedUsers == 0)) {
- pad.invitemoreShow();
- }
-};
-
-pad.initResizeTimer = function() {
- pad.resizePage(true);
- setInterval(function() { pad.resizePage(true); }, 2000);
-}
-
-pad.initModalDialogs = function() {
- pad.swallowAllMouseEvents($("#dialogtopbar"));
-}
-
-pad.initImportExport = function() {
- // pad.addExportFrames();
- pad.addImportFrames();
- $('#importfileinput').change(pad.fileInputUpdated);
- $('#importform').submit(pad.fileInputSubmit);
- $('.disabledexport').click(pad.cantExport)
- // $('.requiresoffice').click(pad.exportDoLongClick);
- // $('.exportlink').click(pad.exportHideMessages);
-}
-
-pad.initRichText = function() {
- $(".toptoolbarbutton").attr("unselectable", "on"); // for IE
- $("#toptoolbar").removeClass("disabledtoolbar");
-}
-
-pad.initViewBar = function() {
-
- pad.setViewFont(pad.initialCookiePrefs.viewFont || 'normal'); // sets pad.viewFont
- pad.setViewZoom(pad.initialCookiePrefs.viewZoom || 100); // sets pad.viewZoom
-
- $("#bottoolbar").css('display', 'block'); // show it
- $("#bottoolbar").removeClass("disabledtoolbar");
-
- $("#viewzoommenu").change(function(evt) {
- pad.setViewZoom(Number($("#viewzoommenu").val().substring(1))); // remove 'z' from val
- });
- $("#viewfontmenu").change(function(evt) {
- pad.setViewFont($("#viewfontmenu").val());
- });
-}
-
-pad.initPadTitle = function() {
- pad.title = clientVars.initialTitle;
- pad.password = clientVars.initialPassword;
-
- $("#padtitle").submit(function(evt) {
- pad.submitTitle(true);
- evt.preventDefault();
- return false;
- });
- $("#padtitleedit").keyup(function(evt) {
- if (evt.which == 27) {
- // "escape" key
- pad.submitTitle(false);
- }
- });
- pad.renderPadTitle();
-}
-
-pad.init = function() {
- // note: order of init calls is important.
-
- pad.debugEnabled = clientVars.debugEnabled;
- pad.padId = clientVars.padId;
- pad.diagnosticInfo.uniqueId = pad.uniqueId();
-
- pad.dmesg("pad.init()");
-
- pad.initCookie();
- pad.initResizeTimer();
- pad.initAce(function() {
- document.domain = document.domain; // for comet, set after ACE creates its frames
- pad.initMyUserInfo();
- pad.initSideBoxes();
- pad.initCollab();
- pad.initRichText();
- pad.initViewBar();
- pad.initRevisions();
- pad.initPrefsPane();
- pad.initChat();
- pad.initEvents();
- pad.initFocusTracker();
- pad.initPadTitle();
- $('a#hidesidebar').show();
- pad.initTime = +(new Date());
- pad.initialized = true;
- pad.saveCookie(); // must happen after pad.initialized = true.
- pad.initModalDialogs();
- pad.initImportExport();
- pad.initWelcomeMessage();
- pad.dmesg("pad.init(): done!");
- });
-};
-
-//----------------------------------------------------------------
-
-pad.getDefaultUsername = function() {
- var cookieName = pad.initialCookiePrefs.name;
- if (cookieName) {
- return cookieName;
- }
- var nameGuess = clientVars.nameGuess;
- if (nameGuess) { return nameGuess; }
- return null;
-};
-
-pad.getCurrentPageHeight = function() {
- return $("#padcontent").offset().top + $("#padcontent").height() + 1;
-}
-
-pad.resizePage = function(dontReschedule) {
- // this method should not require any init to have happened
-
- var visibleHeight = document.documentElement.clientHeight;
- var sizedContentHeight = $("#sizedcontent").height() - 2; // subtract 2 for border
- var pageHeight = pad.getCurrentPageHeight();
-
- var newHeight = visibleHeight - (pageHeight - sizedContentHeight);
- var totalToolbarHeight = $("#toptoolbar").outerHeight() + $("#bottoolbar").outerHeight();
-
- // editor (left column, 1)
- var oldHeight1 = $("#editorcontainer").height() - totalToolbarHeight;
- var newHeight1 = newHeight - totalToolbarHeight;
-
- // sidebar (right column, 2)
- var oldHeight2 = $("#sidebar").height();
- var newHeight2 = newHeight;
-
- if (newHeight1 != oldHeight1) {
- $("#editorcontainer").css('height', newHeight1+"px");
- if (pad.ace) {
- pad.ace.adjustSize();
- }
- }
- if (newHeight2 != oldHeight2) {
- $("#sidebar").css('height', newHeight2+"px");
- }
-
- pad.repositionModals();
- if (pad.initialized) {
- pad.renderPadTitle();
- }
-
- if (! dontReschedule) {
- // try again in a bit in case we missed the correct size,
- // but don't let that call cause another setTimeout
- setTimeout(function() { pad.resizePage(true); }, 100);
- }
-};
-
-pad.setOnEnterKey = function(eltpath, f) {
- $(eltpath).keydown(function(e) {
- if (e.keyCode == 13) {
- f(e);
- e.preventDefault();
- return false;
- }
- return true; //continue event
- });
-};
-
-//----------------------------------------------------------------
-// New pad button.
-//----------------------------------------------------------------
-
-pad.newPad = function() {
- $('#newpad').submit();
-};
-
-//----------------------------------------------------------------
-// UI Preferences
-//----------------------------------------------------------------
-
-pad.isPrefMarked = function(n) {
- var v = !!$('#checkpref'+n+' input').attr('checked');
- pad.dmesg("isPrefMarked("+n+") = "+v);
- return v;
-};
-
-pad.markPref = function(n, t) {
- var i = $('#checkpref'+n+' input');
- if (t) {
- i.attr('checked', 'checked');
- } else {
- i.removeAttr('checked');
- }
-};
-
-pad.updatePref = function(name, val) {
- var ace = pad.ace;
- if (name == "showcolors") {
- ace.setProperty("showsAuthorColors", val);
- }
- if (name == "wrap") {
- ace.setProperty("wraps", val);
- }
- if (name == "linenums") {
- ace.setProperty("lineNumbers", val);
- }
- if (name == "jshighlight") {
- if (val) {
- ace.setProperty("lexer", "js");
- } else {
- ace.setProperty("lexer", "txt");
- }
- }
- if (name == "fullwidth") {
- pad.setFullWidth(val);
- }
-};
-
-//----------------------------------------------------------------
-
-pad.uniqueId = function() {
- return [
- clientVars.clientIp,
- String(+(new Date())),
- String(Math.floor(Math.random()*100000))
- ].join('.');
-};
-
-pad.getUserDisplayName = function(userInfo) {
- // strip HTML from newName.
- // TODO: better HTML escaping?
- var name = userInfo.name;
- if (!(typeof(name) == "string")) {
- name = "unnamed";
- if (userInfo.userId == pad.myUserInfo.userId) {
- name += ' (me)';
- }
- }
- return name;
-};
-
-//----------------------------------------------------------------
-// userJoin
-//----------------------------------------------------------------
-
-pad.userJoin = function(userInfo) {
- pad.dmesg("pad.userJoin: "+userInfo.name+"/"+userInfo.userId);
- pad.users[userInfo.userId] = userInfo;
-
- var name = pad.escapeHtml(pad.getUserDisplayName(userInfo));
- if (userInfo.userId != pad.myUserInfo.userId) {
- var currentTime = +(new Date());
- if ((currentTime - pad.initTime) > 1000*2) {
- pad.notify('<i>'+name+'</i> has joined the pad.');
- }
- }
-
- // assign an ID for the userbox div
- var boxId = pad.userBoxIds[userInfo.userId];
- if (!boxId) {
- pad.lastBoxId++;
- boxId = "userbox"+pad.lastBoxId;
- pad.userBoxIds[userInfo.userId] = boxId;
- var classNames = "userbox";
- if (userInfo.userId == pad.myUserInfo.userId) { classNames += " me"; }
- var userbox = '<div class="'+classNames+'" id="'+boxId+'"><!-- --></div>';
- $('#userlist').append(userbox);
- }
-
- $('#userlist div.lastuser').removeClass('lastuser');
- $('#'+boxId).addClass('lastuser').hide();
-
- pad.updateUserBox(userInfo);
- pad.updateChatHistoryForUser(userInfo);
-
- // show
- $('#'+boxId).fadeIn('slow');
-};
-
-pad.updateUserBox = function(userInfo) {
- var nameHtml = '<span class="username">' + pad.escapeHtml(pad.getUserDisplayName(userInfo)) + '</span>';
- var changeLink = '';
- var isMe = (userInfo.userId == pad.myUserInfo.userId);
- if (isMe) {
- changeLink = '<div id="rightuserlink">'+
- '<a id="changenamelink" href="javascript: void;" class="small_link">edit name/color</a>'+
- '</div>';
- }
- var displayIp = userInfo.ip + '/' + userInfo.userAgent;
- var boxId = pad.userBoxIds[userInfo.userId];
- var box = $('#'+boxId);
- if (box.size() != 1) {
- pad.notify("Warning: spurious user update for user &lt;"+userInfo.userId+"&gt;");
- return;
- }
- var bgcolor = clientVars.colorPalette[userInfo.colorId];
- box.empty().html([
- '<div class="userinfowrap' + (isMe ? ' myuserwrap' : '') + '">',
- '<div class="usercolor" style="background-color: ',bgcolor, '">',
- '&nbsp;</div>',
- '<div class="userinfo">',
- changeLink,
- ' <div>',
- nameHtml,
- ' </div>',
- ' <div class="ip">',
- displayIp,
- ' </div>',
- '</div>',
- '<div style="clear: both;"><!-- --></div>',
- '</div>'
- ].join(''));
- if (isMe) {
- $('#userlist div.myuserwrap').click(pad.myUserInfoClick);
- }
-};
-
-pad.myUserInfoClick = function(e) {
- if (pad.isEditingUserInfo) {
- return true;
- }
- pad.oldColorId = pad.myUserInfo.colorId;
- pad.isEditingUserInfo = true;
- $('#userlist div.me').hide().html([
- '<div class="edituserinfo">',
- '<h4>Name:</h4>',
- '<p><input type="text" id="mynewname" /></p>',
- '<h4>Color:</h4>',
- pad.renderColorPicker(),
- '<button id="savemyuserinfo">Save</button>',
- '<button id="canceleditmyuserinfo">Cancel</button>',
- '</div>'
- ].join('')).fadeIn('fast', function() {});
-
- $('input#mynewname').val(pad.getUserDisplayName(pad.myUserInfo)).focus().select();
- pad.setOnEnterKey('input#mynewname', pad.saveMyNewUserInfo);
-
- $('#canceleditmyuserinfo').click(pad.cancelEditMyUserInfo);
- $('#savemyuserinfo').click(pad.saveMyNewUserInfo);
-
- e.preventDefault();
- return false;
-};
-
-pad.cancelEditMyUserInfo = function(e) {
- if (pad.oldColorId != pad.myUserInfo.colorId) {
- pad.myUserInfo.colorId = pad.oldColorId;
- pad.collabClient.updateUserInfo(pad.myUserInfo);
- }
- $('#userlist div.me').fadeOut('fast', function() {
- pad.updateUserBox(pad.myUserInfo);
- $('#userlist div.me').fadeIn('fast');
- pad.isEditingUserInfo = false;
- });
- e.preventDefault();
- return false;
-};
-
-pad.saveMyNewUserInfo = function(e) {
- var newName = $('#mynewname').val();
- if (newName != "unnamed (me)") {
- pad.myUserInfo.name = newName;
- }
- $('#userlist div.me').fadeOut('fast', function() {
- $('#userlist div.me').html('Saving...');
- pad.collabClient.updateUserInfo(pad.myUserInfo);
- pad.saveCookie();
- pad.updateUserBox(pad.myUserInfo);
- $('#userlist div.me').fadeIn('fast');
- pad.isEditingUserInfo = false;
- pad.updateChatHistoryForUser(pad.myUserInfo);
- });
- e.preventDefault();
- return false;
-};
-
-pad.renderColorPicker = function() {
- function renderColorSquare(i) {
- var classNames = "";
- if (i == pad.myUserInfo.colorId) {
- classNames += " selectedcolor";
- }
- var html = [
- '<a class="'+classNames+'"',
- ' id="colorchoice'+i+'"',
- ' style="background: '+clientVars.colorPalette[i], ';"',
- ' href="javascript:void pad.chooseNewColor('+i+');">',
- '&nbsp;</a>'
- ].join('');
- return html;
- }
- var r = '<div id="colorpicker">';
- for (var i = 0; i < clientVars.colorPalette.length; i++) {
- r += renderColorSquare(i);
- }
- r += '<div style="clear: both;"><!-- --></div></div>';
- return r;
-};
-
-pad.chooseNewColor = function(colorId) {
- pad.myUserInfo.colorId = colorId;
- pad.collabClient.updateUserInfo(pad.myUserInfo);
- $('#colorpicker a').removeClass('selectedcolor');
- $('#colorpicker a#colorchoice'+colorId).addClass('selectedcolor');
-};
-
-//----------------------------------------------------------------
-// userLeave
-//----------------------------------------------------------------
-
-pad.userLeave = function(userInfo) {
- pad.dmesg("pad.userLeave: "+userInfo.name+"/"+userInfo.userId);
-
- var box = $('#'+pad.userBoxIds[userInfo.userId]);
- box.attr('id', ('oldbox'+(+(new Date()))));
-
- delete pad.users[userInfo.userId];
- delete pad.userBoxIds[userInfo.userId];
-
- box.fadeOut('slow', function() {
- box.remove();
- var boxes = $('#userlist').children();
- if (boxes.size() > 0) {
- $(boxes.get(boxes.size()-1)).addClass('lastuser');
- }
- });
-
- pad.updateChatHistoryForUser(userInfo);
-};
-
-//----------------------------------------------------------------
-// updateUserInfo
-//----------------------------------------------------------------
-
-pad.updateUserInfo = function(userInfo) {
- pad.updateUserBox(userInfo);
- pad.updateChatHistoryForUser(userInfo);
- // TODO: draw attention to the updated userbox somehow? flash it?
- var oldInfo = pad.users[userInfo.userId];
- if (oldInfo.name != userInfo.name) {
- var oldName = pad.escapeHtml(pad.getUserDisplayName(oldInfo));
- var newName = pad.escapeHtml(pad.getUserDisplayName(userInfo));
- pad.notify("<i>"+oldName+"</i> is now known as <i>"+newName+"</i>.");
- }
- if (oldInfo.colorId != userInfo.colorId) {
- pad.notify("<i>"+pad.escapeHtml(pad.getUserDisplayName(userInfo))+"</i> has a new background color.");
- }
- pad.users[userInfo.userId] = userInfo;
-};
-
-//----------------------------------------------------------------
-// channelStateChange
-//----------------------------------------------------------------
-
-pad.channelStateChange = function(newState, message) {
- pad.connectionState = newState;
- if (newState == "CONNECTED") {
- $('#savenow').removeAttr('disabled');
- pad.displayConnectionStatus('connected');
- pad.notify("Connected to EtherPad synchronization server.");
- }
- if (newState == "RECONNECTING") {
- $('#savenow').attr('disabled', true);
- pad.displayConnectionStatus('connecting');
- pad.notify("Lost connection with server. Attempting to reconnect...", true);
- }
- if (newState == "DISCONNECTED") {
- pad.diagnosticInfo.disconnectedMessage = message;
- pad.diagnosticInfo.padInitTime = pad.initTime;
- pad.asyncSendDiagnosticInfo();
-
- $('#savenow').attr('disabled', true);
-
- pad.displayConnectionStatus('disconnected');
- if (typeof top.ajlog == "string") { top.ajlog += ("Disconnected: "+message+'\n'); }
-
- $('div#bigtoperror_wrap').addClass('hidden');
- $('div.bigtoperror').hide();
- pad.clearNotificationQueue();
- if (pad.ace) {
- pad.ace.setProperty("grayedOut", true);
- pad.ace.setEditable(false);
- }
- if (message == "userdup") {
- $('div#disconnected_userdup').show();
- } else if (message == "looping") {
- $('div#disconnected_looping').show();
- $('div#reconnect_advise').show();
- } else if (message == "slowcommit") {
- $('div#disconnected_slowcommit').show();
- $('div#reconnect_advise').show();
- } else if (message == "initsocketfail") {
- $('div#disconnected_initsocketfail').show();
- $('div#reconnect_advise').show();
- } else {
- $('div#disconnected_unknown').show();
- $('div#reconnect_advise').show();
- }
- pad.notify("Lost connection with server.");
- $('div#bigtoperror_wrap').html();
- $('div#bigtoperror_wrap').removeClass('hidden').fadeIn('fast', function() {
- pad.resizePage();
- });
- $('div#userlist div.userbox').remove();
- }
-};
-
-//----------------------------------------------------------------
-// Notification system
-//----------------------------------------------------------------
-
-pad.notify = function(message, persist) {
- pad.notifyQueue.push([message, persist]);
- setTimeout(pad.processNotifyQueue, 50);
-};
-
-pad.clearNotificationQueue = function() {
- delete pad.notifyQueue;
- pad.notifyQueue = [];
-};
-
-pad.processNotifyQueue = function() {
- if (pad.notifyQueue.length == 0) {
- return;
- }
- var msSinceLast = (+(new Date()) - pad.lastNotify);
- if (msSinceLast < 1000) {
- setTimeout(pad.processNotifyQueue, 1050-msSinceLast);
- return;
- }
- var msg = pad.notifyQueue.shift();
- $('#topbarmsg').fadeOut('fast', function() {
- $('#topbarmsg').html(msg[0]).fadeIn('slow');
- });
- pad.lastNotify = +(new Date());
-
- // set window title if blurred
- function striptags(x) {
- return x.replace(/<[^\>]+>/g, '');
- }
- if (!pad.padHasFocus) {
- $(document).attr('title', '* '+striptags(msg[0]));
- }
-
- // clear it after 5 seconds unless "persist" was specified
- pad.persistLastNotify = msg[1];
- setTimeout(function() {
- if (!pad.persistLastNotify) {
- $('#topbarmsg').fadeOut('slow');
- }
- }, 5000);
-};
-
-//----------------------------------------------------------------
-// Cookies
-//----------------------------------------------------------------
-
-pad.saveCookie = function() {
- if (!pad.initialized) { return; }
- var prefs = {
- userId: pad.myUserInfo.userId,
- name: pad.myUserInfo.name,
- colorId: pad.myUserInfo.colorId,
- wrapLines: pad.isPrefMarked('wrap'),
- showAuthorColors: pad.isPrefMarked('showcolors'),
- showLineNumbers: pad.isPrefMarked('linenums'),
- highlightJs: pad.isPrefMarked('jshighlight'),
- fullWidth: pad.isPrefMarked('fullwidth'),
- sideBoxVisibility: pad.sideBoxVisibility,
- viewZoom: pad.viewZoom,
- viewFont: pad.viewFont
- };
- var expiresDate = new Date();
- expiresDate.setFullYear(3000);
- document.cookie = ('prefs='+escape(JSON.stringify(prefs))+
- ';expires='+expiresDate.toGMTString());
-
- // If the browser rejects the cookie, then show an error message.
- if (clientVars.isProPad &&
- !(document.cookie &&
- (document.cookie.length > 0) &&
- (document.cookie.indexOf('prefs') >= 0))) {
-
- if (!pad.alreadyWarnedAboutNoCookies) {
- alert("Warning: it appears that your browser does not have cookies enabled."+
- " EtherPad uses cookies to keep track of unique users for the purpose"+
- " of putting a quota on the number of active users. Using EtherPad without "+
- " cookies may fill up your server's user quota faster than expected.");
- pad.alreadyWarnedAboutNoCookies = true;
- }
- }
-};
-
-pad.getInitialCookiePrefs = function() {
-
- function _getExistingCookie() {
- if (document.cookie.length < 1) {
- pad.isFreshCookie = true;
- return {};
- }
- var name = "prefs";
- var start = document.cookie.indexOf(name + "=");
- if (start == -1) {
- pad.isFreshCookie = true;
- return {};
- }
- start = start + name.length + 1;
- var end = document.cookie.indexOf(";", start);
- if (end == -1) {
- end = document.cookie.length;
- }
- try {
- return JSON.parse(unescape(document.cookie.substring(start, end)));
- } catch (ex) {
- pad.isFreshCookie = true;
- return {};
- }
- }
-
- var cp = _getExistingCookie();
-
- // required cookie fields & defaults
- function _setDefault(name, val) {
- if (cp[name] === undefined) {
- cp[name] = val;
- }
- }
- _setDefault('sideBoxVisibility', {});
- _setDefault('wrapLines', true);
- _setDefault('showAuthorColors', true);
- _setDefault('showLineNumbers', false);
- _setDefault('fullWidth', false);
-
- return cp;
-};
-
-//----------------------------------------------------------------
-
-pad.forceReconnect = function(diagnosticInfo) {
- $('form#reconnect input#padId').val(pad.padId);
- pad.diagnosticInfo.collabDiagnosticInfo = pad.collabClient.getDiagnosticInfo();
- $('form#reconnect input#diagnosticInfo').val(JSON.stringify(pad.diagnosticInfo));
- $('form#reconnect input#missedChanges').val(JSON.stringify(pad.collabClient.getMissedChanges()));
- $('form#reconnect').submit();
-};
-
-pad.dmesg = function(m) {
- if (pad.debugEnabled) {
- $('#djs').append('<p>'+m+'</p>');
- var djs = $('#djs').get(0);
- djs.scrollTop = djs.scrollHeight;
- }
-};
-
-pad.showSideBar = function() {
- $('#sidebarcell').show().addClass('visible');
- $('a#showsidebar').hide();
- $('a#hidesidebar').show();
- pad.sideBarVisible = true;
- pad.saveCookie();
- return false;
-};
-
-pad.hideSideBar = function() {
- $('#sidebarcell').hide().removeClass('visible');
- $('a#showsidebar').show();
- $('a#hidesidebar').hide();
- pad.sideBarVisible = false;
- pad.saveCookie();
- return false;
-};
-
-pad.setFullWidth = function(fullWidth) {
- if (fullWidth) {
- //$('#padhead, #appjetfooter').fadeOut('fast').addClass('hidden');
- $('body').removeClass('limwidth').addClass('fullwidth');
- $('#widthlink').attr('title', "Use fixed pad width");
- } else {
- // hack:
- $("#padtitle").css('width', '400px');
-
- //$('#padhead, #appjetfooter').removeClass('hidden').fadeIn('fast');
- $('body').removeClass('fullwidth').addClass('limwidth');
- $('#widthlink').attr('title', "Use full window width");
- }
- if (pad.initialized) {
- pad.resizePage();
- }
-};
-
-pad.toggleFullWidth = function() {
- // fires when user clicks icon in corner; updates preferences
- var oldValue = pad.isPrefMarked("fullwidth");
- var newValue = ! oldValue;
-
- pad.markPref("fullwidth", newValue);
- pad.updatePref("fullwidth", newValue);
-
- pad.saveCookie();
-}
-
-pad.handlerPreventDefault = function(e) {
- e.preventDefault();
- return false;
-}
-
-pad.swallowAllMouseEvents = function(jqueryNodes) {
- jqueryNodes.click(pad.handlerPreventDefault);
- jqueryNodes.mousedown(pad.handlerPreventDefault);
- jqueryNodes.mouseup(pad.handlerPreventDefault);
-}
-
-//----------------------------------------------------------------
-// Saved Revisions
-//----------------------------------------------------------------
-
-pad.renderRevisionList = function(fast) {
- var rlis = pad.revisionList;
- var content = "";
- for (var i = 0; (i < rlis.length) && (i < pad.shownRevisions); i++) {
- var rnum = rlis.length - i;
- var name = pad.escapeHtml(rlis[i].savedBy);
- name += " ("+rlis[i].ip+")";
- var when = pad.timediff(new Date(rlis[i].timestamp));
- var viewLink = '/ep/pad/view/'+pad.padId+'/'+rlis[i].id;
- var restoreLink = 'javascript:void pad.restoreRevision('+rnum+');';
- var label = pad.escapeHtml(rlis[i].label || ('Revision '+rnum));
- if (rlis[i].savedById == pad.myUserInfo.userId &&
- ((+(new Date()) - rlis[i].timestamp) < (24*60*60*1000))) {
- label = ('<a class="editrlabel small_link" href="javascript: void pad.editRevisionLabel('+rnum+');">'+
- label + '</a>');
- }
- content += ('<div class="revisioninfo" id="revisioninfo_'+rnum+'">'+
- ' <div class="rleft">'+
- ' <div id="rlabel'+rnum+'">'+label+'</div>'+
- ' <div class="ractions">'+
- ' <a class="small_link" target="_blank" href="'+viewLink+'">view</a>&nbsp;|&nbsp;<a class="small_link" href="'+restoreLink+'">restore</a>'+
- ' </div>'+
- ' </div>'+
- ' <div class="rright">saved '+when+' by '+name+'</div>'+
- ' <div style="clear: both;"><!-- --></div>'+
- '</div>');
- }
- var areMore = (pad.shownRevisions < pad.revisionList.length);
- var areFewer = (pad.shownRevisions > pad.REVISIONCOUNT_STEP);
- content += '<div class="revisionbottomlinks">';
- if (areMore || areFewer) {
- content += 'show:&nbsp;';
- }
- if (areFewer) {
- content += '<a class="small_link" href="javascript:void pad.fewerRevisions();">fewer</a>';
- }
- if (areMore && areFewer) {
- content += '&nbsp;|&nbsp;';
- }
- if (areMore) {
- content += '<a class="small_link" href="javascript:void pad.moreRevisions();">more</a>';
- }
- content += '</div>';
-
- if (fast) {
- $('#revisionlist').html(content);
- } else {
- $('#revisionlist').hide().html(content).fadeIn('fast');
- }
-};
-
-pad.fewerRevisions = function() {
- pad.shownRevisions -= pad.REVISIONCOUNT_STEP;
- pad.renderRevisionList();
-};
-
-pad.moreRevisions = function() {
- pad.shownRevisions += pad.REVISIONCOUNT_STEP;
- pad.renderRevisionList();
-};
-
-pad.saveRevision = function() {
- var mv = clientVars.accountPrivs.maxRevisions;
- if ((mv != -1) && (pad.revisionList.length >= mv)) {
- $('#savenow').hide();
- $('#nosaveprivs').fadeIn('fast');
- return;
- }
- $('#savenow').attr('disabled', true).val("Saving...");
- var savedBy = pad.myUserInfo.name || "unnamed";
- pad.collabClient.callWhenNotCommitting(doAjax);
- function doAjax() {
- $.ajax({
- type: 'post',
- url: '/ep/pad/saverevision',
- data: {
- padId: pad.padId,
- savedBy: savedBy,
- savedById: pad.myUserInfo.userId,
- revNum: pad.collabClient.getCurrentRevisionNumber()
- },
- success: success,
- error: error
- });
- }
- function success(text) {
- pad.revisionList = JSON.parse(text);
- if (pad.revisionList.length > 0) {
- pad.clientTimeOffset = +(new Date) - pad.revisionList[0].timestamp;
- }
- pad.renderRevisionList();
- pad.collabClient.sendClientMessage({
- type: 'newRevisionList',
- revisionList: pad.revisionList,
- savedBy: savedBy
- });
- $('#savenow').val("Save Now").removeAttr('disabled');
- }
- function error(e) {
- alert("Oops! The server failed to save the revision. Please try again later.");
- $('#savenow').val("Save Now").removeAttr('disabled');
- }
-};
-
-pad.restoreRevision = function(rnum) {
- var i = pad.revisionList.length - rnum;
- var rev = pad.revisionList[i];
- var warning = ("Restoring this revision will replace the current"
- + "pad with the text saved in revision \""
- + ""+rev.label+"\". Are you sure you want to continue?");
-
- if (confirm(warning)) {
- $.ajax({
- type: 'get',
- url: '/ep/pad/getrevisionatext',
- data: {padId: pad.padId, revId: rev.id},
- success: success,
- error: error
- });
- }
- function success(resultJson) {
- var result = JSON.parse(resultJson);
- pad.collabClient.addHistoricalAuthors(result.historicalAuthorData);
- pad.ace.importAText(result.atext, result.apool, true);
- }
- function error(e) {
- alert("Oops! There was an error retreiving the text (revNum= "+
- rev.revNum+"; padId="+pad.padId);
- }
-};
-
-pad.editRevisionLabel = function(rnum) {
- var i = pad.revisionList.length - rnum;
- var rev = pad.revisionList[i];
- $('#revisioninfo_'+rnum).html(
- '<p class="revlabelprompt">Enter a label for revision #'+rnum+' and press return.</p>'+
- '<input class="inputrevlabel"'+
- ' id="inputrevlabel'+rnum+'" type="text" />'
- );
- $('input#inputrevlabel'+rnum).val(rev.label).focus().select();
- pad.setOnEnterKey('#inputrevlabel'+rnum, function() {
- pad.saveRevisionLabel(rnum);
- });
-};
-
-pad.saveRevisionLabel = function(rnum) {
- var i = pad.revisionList.length - rnum;
- var rev = pad.revisionList[i];
- var newLabel = $('#inputrevlabel'+rnum).val();
- $.ajax({
- type: 'post',
- url: '/ep/pad/saverevisionlabel',
- data: {userId: pad.myUserInfo.userId,
- padId: pad.padId,
- revId: rev.id,
- newLabel: newLabel},
- success: success,
- error: error
- });
- function success(text) {
- pad.revisionList = JSON.parse(text);
- pad.renderRevisionList();
- pad.collabClient.sendClientMessage({
- type: 'revisionLabel',
- revisionList: pad.revisionList,
- savedBy: pad.myUserInfo.name,
- newLabel: newLabel
- });
- }
- function error(e) {
- alert("Oops! There was an error saving that revision label. Please try again later.");
- }
-};
-
-//----------------------------------------------------------------
-// Feedback form.
-//----------------------------------------------------------------
-pad.submitfeedback = function() {
- var feedback = $('#feedbackarea').val();
- $('#feedbackarea').val('');
- $.ajax({
- type: 'post',
- url: '/ep/pad/feedback',
- data: {feedback: feedback, padId: pad.padId, username: pad.myUserInfo.name},
- success: success,
- error: error
- });
-
- $('#feedbackresult #feedbackemail').html('feedback'+'@'+'etherpad'+'.com');
- $('#feedbackbox').fadeOut('fast', function() {
- $('#feedbackresult').fadeIn('slow', function() {
- setTimeout(function() {
- $('#feedbackresult').fadeOut('slow', function() {
- $('#feedbackbox').fadeIn('fast');
- });
- }, 10000);
- });
- });
-
- function success(msg) {};
- function error(e) {
- alert("Oops! There was an error submitting the feedback. Please try again later.");
- }
-};
-
-//----------------------------------------------------------------
-// UA Display
-//----------------------------------------------------------------
-
-pad.uaDisplay = function(ua) {
- var m;
-
- function clean(a) {
- var maxlen = 16;
- a = a.replace(/[^a-zA-Z0-9\.]/g, '');
- if (a.length > maxlen) {
- a = a.substr(0,maxlen);
- }
- return a;
- }
-
- function checkver(name) {
- var m = ua.match(RegExp(name + '\\/([\\d\\.]+)'));
- if (m && m.length > 1) {
- return clean(name+m[1]);
- }
- return null;
- }
-
- // firefox
- if (checkver('Firefox')) { return checkver('Firefox'); }
-
- // misc browsers, including IE
- m = ua.match(/compatible; ([^;]+);/);
- if (m && m.length > 1) {
- return clean(m[1]);
- }
-
- // iphone
- if (ua.match(/\(iPhone;/)) {
- return 'iPhone';
- }
-
- // chrome
- if (checkver('Chrome')) { return checkver('Chrome'); }
-
- // safari
- m = ua.match(/Safari\/[\d\.]+/);
- if (m) {
- var v = '?';
- m = ua.match(/Version\/([\d\.]+)/);
- if (m && m.length > 1) {
- v = m[1];
- }
- return clean('Safari'+v);
- }
-
- // everything else
- var x = ua.split(' ')[0];
- return clean(x);
-};
-
-//----------------------------------------------------------------
-// invitemoreClick
-//----------------------------------------------------------------
-
-pad.invitemoreShow = function() {
- $('#invitemorelink').hide();
- $('#inviteinstructions').fadeIn('fast');
- $('#invite_email').focus();
-};
-
-pad.invitemoreHide = function() {
- $('#inviteinstructions').fadeOut('fast');
- $('#invitemorelink').show();
-};
-
-pad.invitemoreSendEmail = function() {
- function msg(m) {
- $('#invite_email_status').hide().html(m).fadeIn('fast');
- }
- var email = $('#invite_email').val();
- if (!pad.validEmail(email)) {
- msg("That doesn't look like a valid email address.");
- return;
- }
- $('#invite_email_submit').attr('disabled', true).val('Sending...');
- $.ajax({
- type: 'post',
- url: '/ep/pad/emailinvite',
- data: {email: email,
- padId: pad.padId,
- username: (pad.myUserInfo.name || "someone")
- },
- success: function() {
- $('#invite_email').val('');
- msg("Email sent to "+email+".");
- $('#invite_email_submit').val('Send').removeAttr('disabled');
- },
- error: function() {
- msg("Oops! There was an error sending the invite. Please try again later.");
- $('#invite_email_submit').val('Send').removeAttr('disabled');
- }
- });
-};
-
-pad.validEmail = function(x) {
- return (x.length > 0 &&
- x.match(/^[\w\.\_\+\-]+\@[\w\_\-]+\.[\w\_\-\.]+$/));
-};
-
-/*
-pad.getQueryParam = function(name) {
- var params = {};
- var query = window.location.search.substr(1);
- var parts = query.split('&');
- for (var i = 0; i < parts.length; i++) {
- var subparts = parts[i].split('=');
- if (subparts.length == 2) {
- params[subparts[0]] = subparts[1];
- }
- }
- return params[name];
-};
-*/
-
-pad.timediff = function(d) {
- function format(n, word) {
- n = Math.round(n);
- return ('' + n + ' ' + word + (n != 1 ? 's' : '') + ' ago');
- }
- d = (+(new Date) - (+d) - pad.clientTimeOffset) / 1000;
- if (d < 60) { return format(d, 'second'); }
- d /= 60;
- if (d < 60) { return format(d, 'minute'); }
- d /= 60;
- if (d < 24) { return format(d, 'hour'); }
- d /= 24;
- return format(d, 'day');
-};
-
-//----------------------------------------------------------------
-
-pad.onClientMessage = function(m) {
- if (m.type == 'newRevisionList') {
- pad.revisionList = m.revisionList;
- pad.notify(pad.escapeHtml(m.savedBy) + " saved a new revision.");
- pad.renderRevisionList();
- }
- if (m.type == 'revisionLabel') {
- pad.revisionList = m.revisionList;
- pad.notify(pad.escapeHtml(m.savedBy) + ' labeled a revision, "'+pad.escapeHtml(m.newLabel)+'".');
- pad.renderRevisionList();
- }
- if (m.type == 'chat') {
- pad.receiveChat(m);
- }
- if (m.type == 'padtitle') {
- pad.title = m.title;
- pad.renderPadTitle();
- if (m.changedBy) {
- pad.notify(pad.escapeHtml(m.changedBy) + ' changed the pad title.');
- }
- }
- if (m.type == 'padpassword') {
- pad.password = m.password;
- pad.renderPadTitle();
- if (m.changedBy) {
- pad.notify(pad.escapeHtml(m.changedBy) + (
- m.password ? ' changed the pad password.' : ' removed password protection from this pad.'));
- }
- }
-};
-
-pad.onServerMessage = function(m) {
- if (m.type == 'NOTICE') {
- if (m.text) {
- $('#servermsg').hide().addClass('hidden');
- $('#servermsgdate').html((new Date()).toString());
- $('#servermsgtext').html(m.text);
- $('#servermsg').removeClass('hidden').fadeIn('fast', function() { pad.resizePage(); });
- pad.notify("Server Notice");
- }
- if (m.js) {
- eval(m.js);
- }
- }
-};
-
-pad.hideTopMsg = function(mn) {
- var x = $('#'+mn+'msg');
- x.fadeOut('fast', function() {
- x.addClass('hidden');
- pad.resizePage();
- });
-};
-
-//----------------------------------------------------------------
-
-pad.isSideBoxVisible = function(paneName) {
- var head = $('#head'+paneName);
- var box = $('#'+paneName);
- return head.hasClass('sh_uncollapsed');
-};
-
-pad.showSideBox = function(paneName) {
- var head = $('#head'+paneName);
- var box = $('#'+paneName);
- head.removeClass('sh_collapsed').addClass('sh_uncollapsed');
- box.fadeIn('fast', function() {});
- pad.sideBoxVisibility[paneName] = true;
- pad.saveCookie();
- if (paneName == "chatbox") {
- pad.onShowChatBox();
- }
-};
-
-pad.hideSideBox = function(paneName) {
- var head = $('#head'+paneName);
- var box = $('#'+paneName);
- box.fadeOut('fast', function() {
- head.removeClass('sh_uncollapsed').addClass('sh_collapsed');
- pad.sideBoxVisibility[paneName] = false;
- pad.saveCookie();
- });
-};
-
-//----------------------------------------------------------------
-
-pad.escapeHtml = function(x) {
- return x.replace(/\</g, '&lt;').replace(/\>/g, '&gt;');
-};
-
-//----------------------------------------------------------------
-// Chat
-//----------------------------------------------------------------
-
-pad.initChat = function() {
- pad.setOnEnterKey('#chatinput', function() {
- pad.sendChat();
- });
- pad.chatUserNums = {};
- pad.lastChatUserNum = 0;
- pad.numUnreadChatMessages = 0;
- pad.initChatHistory();
-};
-
-pad.sendChat = function() {
- var lineText = $('#chatinput').val();
- $('#chatinput').val('').focus();
- var msg = {
- type: 'chat',
- userId: pad.myUserInfo.userId,
- lineText: lineText
- };
- pad.collabClient.sendClientMessage(msg);
- pad.receiveChat(msg);
-};
-
-pad.updateChatHistoryForUser = function(userInfo) {
- if (!(pad.chatUserNums && pad.users)) {
- return;
- }
- var userNum = pad.chatUserNums[userInfo.userId];
- var bgcolor = '#fff';
- if (pad.users[userInfo.userId]) {
- // only color the chat if user is on the pad.
- bgcolor = clientVars.colorPalette[userInfo.colorId];
- }
- var name = pad.escapeHtml(pad.getUserDisplayName(userInfo));
- $('.chatusermessage'+userNum).css('background-color', bgcolor);
- $('.chatusername'+userNum).html(name);
-};
-
-pad.receiveChat = function(msg, quick) {
- var userInfo = pad.users[msg.userId];
- if (!userInfo) { return; }
-
- if (!pad.chatUserNums[userInfo.userId]) {
- pad.lastChatUserNum++;
- pad.chatUserNums[userInfo.userId] = pad.lastChatUserNum;
- userNum = pad.lastChatUserNum;
- }
- var userNum = pad.chatUserNums[userInfo.userId];
-
- pad.renderChatLine(userNum, '.', +(new Date), msg.lineText);
- pad.updateChatHistoryForUser(userInfo);
- pad.notifyNewChatMessage(userInfo, msg);
-};
-
-pad.renderChatLine = function(userNum, name, t, lineText) {
- function chatTime() {
- var x = '';
- var d = new Date(t);
- x += (d.getHours() < 10) ? ('0'+d.getHours()) : d.getHours();
- x += ':';
- x += (d.getMinutes() < 10) ? ('0'+d.getMinutes()) : d.getMinutes();
- return x;
- }
- var displayName;
- if (!name) {
- name = "unnamed";
- }
- $('#chatmessages').append([
- '<div class="chatmessage chatusermessage'+userNum+'">',
- '<span class="chatname chatusername'+userNum+'">'+pad.escapeHtml(name)+'</span>',
- '<span class="chattime">&nbsp;(', chatTime(t), ')</span>:&nbsp;',
- '<span class="chatline">', pad.escapeHtml(lineText), '</span>',
- '</div>'
- ].join(''));
-};
-
-pad.initChatHistory = function() {
- var chatHistory = clientVars.chatHistory;
- if (!chatHistory) { return; }
- for (var i = 0; i < chatHistory.length; i++) {
- var l = chatHistory[i];
- pad.renderChatLine(0, l.name, l.time, l.lineText);
- }
- pad.scrollChatBox();
-};
-
-pad.onShowChatBox = function() {
- $('#chatheadname').html('Chat');
- $('#headchatbox').removeClass('sh_hilited');
- pad.numUnreadChatMessages = 0;
- pad.scrollChatBox();
-};
-
-pad.scrollChatBox = function() {
- var messageBox = $('#chatmessages').get(0);
- messageBox.scrollTop = messageBox.scrollHeight;
-};
-
-pad.notifyNewChatMessage = function(userInfo, msg) {
- if (userInfo.userId != pad.myUserInfo.userId) {
- var name = pad.escapeHtml(pad.getUserDisplayName(userInfo));
- var text;
- if (msg.lineText.length <= 40) {
- text = msg.lineText;
- } else {
- text = (msg.lineText.substr(0, 37) + '...');
- }
- text = pad.escapeHtml(text);
- pad.notify("<i>"+name+" says</i>: "+text);
- }
- if ($('#headchatbox').hasClass('sh_collapsed')) {
- pad.numUnreadChatMessages++;
- var pluralS = (pad.numUnreadChatMessages > 1 ? 's' : '');
- $('#chatheadname').html('Chat <b>('+pad.numUnreadChatMessages+' unread message'+pluralS+')</b>');
- if (!$('#headchatbox').hasClass('sh_hilited')) {
- $('#headchatbox').addClass('sh_hilited');
- }
- }
- pad.scrollChatBox();
-};
-
-//----------------------------------------------------------------
-// Connection trouble
-//----------------------------------------------------------------
-
-pad.onConnectionTrouble = function(troubleStatus) {
- if (troubleStatus == "OK") {
- $('#savenow').removeAttr('disabled');
- pad.displayConnectionStatus('connected');
- if (pad.experiencingConnectionTrouble) {
- pad.notify("Connection re-established!");
- pad.experiencingConnectionTrouble = false;
- }
- } else if (troubleStatus == "SLOW") {
- $('#savenow').attr('disabled', true);
- pad.displayConnectionStatus('connecting');
- if (!pad.experiencingConnectionTrouble) {
- pad.experiencingConnectionTrouble = true;
- pad.notify("The network seems slow. Waiting to hear back from the server...", true);
- }
- }
-};
-
-//----------------------------------------------------------------
-// Connection Status Display
-//----------------------------------------------------------------
-
-pad.displayConnectionStatus = function(status) {
- var cs = $('#connectionstatus');
- cs.attr('class', status);
- if (status == "connecting") { cs.html("Connecting..."); }
- else if (status == "connected") { cs.html("Connected"); }
- else if (status == "disconnected") { cs.html("Disconnected"); }
- else { cs.html(status+'?'); }
-};
-
-//----------------------------------------------------------------
-
-pad.asyncSendDiagnosticInfo = function() {
- pad.diagnosticInfo.collabDiagnosticInfo = pad.collabClient.getDiagnosticInfo();
- setTimeout(function() {
- $.ajax({
- type: 'post',
- url: '/ep/pad/connection-diagnostic-info',
- data: {padId: pad.padId, diagnosticInfo: JSON.stringify(pad.diagnosticInfo)},
- success: function() {},
- error: function() {}
- });
- });
-};
-
-//----------------------------------------------------------------
-// Modal Dialogs
-//----------------------------------------------------------------
-
-pad.repositionModals = function() {
- var overlayNode = $("#modaloverlay");
- var pageHeight = pad.getCurrentPageHeight();
- overlayNode.height(pageHeight);
-
- var dialogNode = $("#modaldialog");
- var dialogHeight = dialogNode.outerHeight();
- dialogNode.css('top', Math.round((pageHeight - dialogHeight)/2)+"px");
-}
-
-//----------------------------------------------------------------
-// Import/Export
-//----------------------------------------------------------------
-
-pad.importClearTimeout = function() {
- if (pad.currentImport) {
- clearTimeout(pad.currentImport);
- delete pad.currentImport;
- }
-}
-
-pad.importApplicationSuccessful = function(data, textStatus) {
- if (data.substr(0, 2) == "ok") {
- if ($('.importmessage').is(':visible')) {
- $('.importmessage').hide();
- }
- $('#importmessagesuccess').html('<strong style="color: green">Import successful!</strong>').show();
- $('#importformfilediv').hide();
- setTimeout(function() {
- $('#importmessagesuccess').fadeOut("slow", function() { $('#importformfilediv').show() });
- }, 4000);
- } else if (data.substr(0, 4) == "fail") {
- pad.importErrorMessage("Couldn't update pad contents. Do you have \"cookies\" enabled in your web browser?");
- } else if (data.substr(0, 4) == "msg:") {
- pad.importErrorMessage(data.substr(4));
- }
- pad.importDone();
-}
-
-pad.importSuccessful = function(token) {
- $.ajax({
- type: 'post',
- url: '/ep/pad/impexp/import2',
- data: {token: token, padId: pad.padId},
- success: pad.importApplicationSuccessful,
- error: pad.importApplicationFailed,
- timeout: 25000 // 20 second timeout.
- });
- pad.addImportFrames();
-}
-
-pad.importApplicationFailed = function(xhr, textStatus, errorThrown) {
- pad.importErrorMessage("Error during conversion.");
- pad.importDone();
-}
-
-pad.importFailed = function(msg) {
- pad.importErrorMessage(msg);
- pad.importDone();
- pad.addImportFrames();
-}
-
-pad.importErrorMessage = function(msg) {
- function showError(fade) {
- $('#importmessagefail').html('<strong style="color: red">Import failed:</strong> '+
- (msg || 'Please try a different file.'))[(fade?"fadeIn":"show")]();
- }
-
- if ($('.importmessage').is(':visible')) {
- $('#importmessagesuccess').fadeOut("fast");
- $('#importmessagefail').fadeOut("fast", function() { showError(true) });
- } else {
- showError();
- }
-}
-
-pad.fileInputUpdated = function() {
- $('#importformfilediv').addClass('importformenabled');
- $('#importsubmitinput').removeAttr('disabled');
- $('#importmessagefail').fadeOut("fast");
- $('#importarrow').show();
- $('#importarrow').animate({paddingLeft:"0px"}, 500)
- .animate({paddingLeft:"10px"}, 150, 'swing')
- .animate({paddingLeft:"0px"}, 150, 'swing')
- .animate({paddingLeft:"10px"}, 150, 'swing')
- .animate({paddingLeft:"0px"}, 150, 'swing')
- .animate({paddingLeft:"10px"}, 150, 'swing')
- .animate({paddingLeft:"0px"}, 150, 'swing');
-}
-
-pad.importDone = function() {
- $('#importsubmitinput').removeAttr('disabled').val("Import Now");
- setTimeout(function() { $('#importfileinput').removeAttr('disabled'); }, 0);
- $('#importstatusball').hide();
- pad.importClearTimeout();
-}
-
-pad.fileInputSubmit = function() {
- $('#importmessagefail').fadeOut("fast");
- var ret = confirm("Importing a file will overwrite your existing document,"+
- " and cannot be undone. If you want to keep your current"+
- " document, download it or save a revision.\n\n"+
- "Are you sure you want to proceed?");
- if (ret) {
- pad.currentImport = setTimeout(function() {
- if (! pad.currentImport) {
- return;
- }
- delete pad.currentImport;
- pad.importFailed("Request timed out.");
- }, 25000); // 20 second timeout.
- $('#importsubmitinput').attr({disabled: true}).val("Importing...");
- setTimeout(function() { $('#importfileinput').attr({disabled: true}) }, 0);
- $('#importarrow').stop(true, true).hide();
- $('#importstatusball').show();
- }
- return ret;
-}
-
-pad.cantExport = function() {
- var type = $(this);
- if (type.hasClass("exporthrefpdf")) {
- type = "PDF";
- } else if (type.hasClass("exporthrefdoc")) {
- type = "Microsoft Word";
- } else if (type.hasClass("exporthrefodt")) {
- type = "OpenDocument";
- } else {
- type = "this file";
- }
- alert("Exporting as "+type+" format is disabled. Please contact your"+
- " system administrator for details.");
- return false;
-}
-
-// pad.exportDoNothingClickHandler = function() { return false; }
-// pad.exportDoLongClick = function() {
-// if ($(this).hasClass('exporthrefdoc')) {
-// pad.exportStartLong('doc');
-// } else if ($(this).hasClass('exporthrefpdf')) {
-// pad.exportStartLong('pdf');
-// } else {
-// return false;
-// }
-// setTimeout(pad.exportDisableOffice, 0);
-// return true;
-// }
-//
-// pad.exportDisableOffice = function() {
-// $('.requiresoffice').unbind('click', pad.exportDoLongClick);
-// $('.requiresoffice').click(pad.exportDoNothingClickHandler);
-// $('.requiresoffice').addClass('disabledexport');
-// }
-//
-// pad.exportEnableOffice = function() {
-// $('.exportspinner').hide();
-// $('.requiresoffice').removeClass('disabledexport');
-// $('.requiresoffice').unbind('click', pad.exportDoNothingClickHandler);
-// $('.requiresoffice').click(pad.exportDoLongClick);
-// }
-//
-// pad.exportMessage = function(msg, head) {
-// function showMessage(fade) {
-// head = head || '<strong style="color: red">Export failed:</strong> ';
-// msg = msg || 'Please try a different file type or try again later.';
-// $('#exportmessage').html(head+msg)[(fade?"fadeIn":"show")]();
-// }
-// if ($('#exportmessage').is(":visible")) {
-// $('#exportmessage').fadeOut("fast", function() { showMessage(true) });
-// } else {
-// showMessage();
-// }
-// }
-//
-// pad.exportDone = function(message) {
-// if (message == "ok") {
-// pad.exportMessage("downloading...", '<strong style="color: green">Conversion successful;</strong> ');
-// setTimeout(function() {
-// $('#exportmessage').fadeOut();
-// }, 4000);
-// } else if (message == "timeout") {
-// pad.exportMessage("Request timed out; please try a different file type or try again later.");
-// } else if (message == "nocookie") {
-// pad.exportMessage("Conversion in progress, please wait...", " ");
-// setTimeout(function() {
-// pad.exportDone("nocookie-delay");
-// }, 25000);
-// } else if (message == "nocookie-delay") {
-// pad.exportMessage("If your download hasn't started yet, then an error occurred; please try a different file type or try again later.", " ");
-// setTimeout(function() {
-// $('#exportmessage').fadeOut();
-// }, 10000);
-// } else {
-// pad.exportMessage("Error converting; please try a different file type or try again later.");
-// }
-// pad.exportEnableOffice();
-// if (! $.browser.opera) {
-// pad.addExportFrames();
-// }
-// }
-//
-// pad.exportHideMessages = function() {
-// $('#exportmessage').fadeOut();
-// }
-//
-// pad.exportStartLong = function(format) {
-// $('#exportspinner'+format).show();
-// $.ajax({
-// type: 'post',
-// url: '/ep/pad/impexp/exportsync',
-// data: { waiter: pad.exportSetCookie() },
-// success: function(data) { pad.exportDone(data); },
-// error: function(xhr, textStatus) { pad.exportDone(textStatus); },
-// timeout: 25000
-// });
-// }
-//
-// pad.exportSetCookie = function() {
-// var cookieValue = Math.round(Math.random()*1e20);
-// document.cookie = "EPexport="+cookieValue;
-//
-// if (!(document.cookie &&
-// (document.cookie.length > 0) &&
-// (document.cookie.indexOf('EPexport') >= 0))) {
-// return false;
-// }
-// return cookieValue;
-// }
-//
-// pad.addExportFrames = function() {
-// $('.exportframe').remove();
-// $('#importexport').append(
-// $('<iframe style="display: none;" name="exportofficeiframe" class="exportframe"></iframe>'));
-// $('#importexport').append(
-// $('<iframe style="display: none;" name="exportiframe" class="exportframe"></iframe>'));
-// }
-
-pad.addImportFrames = function() {
- $('.importframe').remove();
- $('#importexport').append(
- $('<iframe style="display: none;" name="importiframe" class="importframe"></iframe>'));
-}
-
-//----------------------------------------------------------------
-// Rich text
-//----------------------------------------------------------------
-
-pad.isTopToolbarEnabled = function() {
- return ! $("#toptoolbar").hasClass('disabledtoolbar');
-}
-
-pad.isBotToolbarEnabled = function() {
- return ! $("#bottoolbar").hasClass('disabledtoolbar');
-}
-
-pad.toolbarClick = function(which) {
- if (pad.isTopToolbarEnabled()) {
- pad.ace.execCommand(which);
- }
- pad.ace.focus();
-}
-
-//----------------------------------------------------------------
-// View bar
-//----------------------------------------------------------------
-
-pad.setViewZoom = function(percent) {
- if (! (percent >= 50 && percent <= 1000)) {
- // percent is out of sane range or NaN (which fails comparisons)
- return;
- }
-
- pad.viewZoom = percent;
- $("#viewzoommenu").val('z'+percent);
- pad.updateAceFontAndSize();
- pad.saveCookie(); // does nothing if we were called from init > initViewBar
-}
-
-pad.setViewFont = function(font) {
- pad.viewFont = font;
- $("#viewfontmenu").val(font);
- pad.updateAceFontAndSize();
- pad.saveCookie();
-}
-
-pad.updateAceFontAndSize = function() {
- var baseSize = 12;
- pad.ace.setProperty('textsize', Math.round(baseSize * pad.viewZoom / 100));
-
- var face = "sans-serif";
- if (pad.viewFont == 'code') {
- face = "monospace";
- }
- pad.ace.setProperty('textface', face);
-}
-
-//----------------------------------------------------------------
-// Pad title
-//----------------------------------------------------------------
-
-pad.renderPadTitle = function() {
- if (pad.title) {
- var theTitle = (pad.isEditingTitle ? "-" : pad.title);
-
- $("#padtitle").css('display', 'block');
-
- var padtitleWidth = $("#toptoolbar").width() - $("#toptoolbar .toptoolbarbutton:last").position().left - 80;
- $("#padtitle").css('width', padtitleWidth+"px");
-
- var shownLength = theTitle.length;
- $("#padtitletitle").html(pad.escapeHtml(theTitle));
-
- // while it wraps, shorten the displayed title
- while ($("#padtitle .editlink").offset().top > $("#padtitle .padtitlepad").offset().top +
- $("#padtitle .padtitlepad").height()) {
- shownLength--;
- $("#padtitletitle").html(pad.escapeHtml(theTitle.substring(0, shownLength)+"..."));
- }
-
- var titlePos = $("#padtitletitle").position();
- var titleHeight = $("#padtitletitle").height();
- var inputBox = $("#padtitleedit");
- var inputWidth = $("#toptoolbar").width() - titlePos.left - 70;
- inputBox.css({left: titlePos.left, top: titlePos.top, height: titleHeight,
- width: inputWidth});
- $("#toptoolbar .oklink").css({ top: 5, left: titlePos.left + inputWidth + 15 });
- }
- else {
- $("#padtitle").css('display', 'none');
- }
-
- if (clientVars.isProPad) {
- if (pad.password) {
- $("#passwordlock").attr('title','Change password...').get(0).className = 'passwordlocked';
- }
- else {
- $("#passwordlock").attr('title','Password protect...').get(0).className = 'passwordnone';
- }
- }
-};
-
-pad.editTitle = function() {
- $("#padtitleedit").val(pad.title).show().focus().select();
- $("#padtitle .oklink").show();
- $("#padtitle .editlink").hide();
-
- pad.isEditingTitle = true;
- pad.renderPadTitle();
-}
-
-pad.submitTitle = function(acceptChanges) {
- if (acceptChanges) {
- var newTitle = $("#padtitleedit").val();
- if (newTitle) {
- newTitle = newTitle.substring(0, 80);
- pad.title = newTitle;
-
- pad.collabClient.sendClientMessage({
- type: 'padtitle',
- title: newTitle,
- changedBy: pad.myUserInfo.name || "unnamed"
- });
- }
- }
-
- $("#padtitleedit").hide();
- $("#padtitle .oklink").hide();
- $("#padtitle .editlink").show();
-
- pad.isEditingTitle = false;
- pad.renderPadTitle();
-};
-
-pad.passwordClick = function() {
- var oldPassword = pad.password;
-
- var msg = (oldPassword ? "Enter a new password for this pad, or "+
- "make blank to remove password protection:" :
- "Choose a password that will be required to view this pad:");
-
- var result = window.prompt(msg, oldPassword || '');
- if ((typeof result) == "string") {
- pad.password = (result || null); // empty string --> null
- if (pad.password !== oldPassword) {
- pad.collabClient.sendClientMessage({
- type: 'padpassword',
- password: pad.password,
- changedBy: pad.myUserInfo.name || "unnamed"
- });
- pad.renderPadTitle();
- }
- }
- else {
- // user canceled
- }
-}; \ No newline at end of file
diff --git a/etherpad/src/static/js/plugins.js b/etherpad/src/static/js/plugins.js
index d1d6b14..f7a5990 100644
--- a/etherpad/src/static/js/plugins.js
+++ b/etherpad/src/static/js/plugins.js
@@ -1,13 +1,14 @@
plugins = {
callHook: function (hookName, args) {
- if (clientVars.hooks[hookName] === undefined)
+ var hook = clientVars.hooks[hookName];
+ if (hook === undefined)
return [];
var res = [];
- for (i = 0; i < clientVars.hooks[hookName].length; i++) {
- var plugin = clientVars.hooks[hookName][i];
+ for (var i = 0, N=hook.length; i < N; i++) {
+ var plugin = hook[i];
var pluginRes = eval(plugin.plugin)[plugin.original || hookName](args);
if (pluginRes != undefined && pluginRes != null)
- res = res.concat(pluginRes);
+ res = res.concat(pluginRes);
}
return res;
},
diff --git a/etherpad/src/static/js/store.js b/etherpad/src/static/js/store.js
index 96a6487..5750f42 100644
--- a/etherpad/src/static/js/store.js
+++ b/etherpad/src/static/js/store.js
@@ -74,7 +74,7 @@ store.eepnetTrial.submit = function() {
$('#dlsignup').hide();
$('#processingmsg').fadeIn('fast');
- // first stubmit to etherpad.com...
+ // first submit...
var data = {};
$(".signupData").each(function() {
data[$(this).attr("id")] = $(this).val();
diff --git a/etherpad/src/templates/admin/pluginmanager.ejs b/etherpad/src/templates/admin/pluginmanager.ejs
deleted file mode 100644
index 077d10a..0000000
--- a/etherpad/src/templates/admin/pluginmanager.ejs
+++ /dev/null
@@ -1,147 +0,0 @@
-<% /* 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. */ %>
-<%
- helpers.setHtmlTitle("EtherPad: Manage plugins");
-/*
- helpers.includeCss("plugins/twitterStyleTags/tagBrowser.css");
- helpers.includeCss("plugins/twitterStyleTags/pad.css"); */
- helpers.setBodyId("padbody");
- helpers.addBodyClass("limwidth nonpropad nonprouser");
- helpers.includeCss("pad2_ejs.css");
- helpers.includeCss("admin/pluginmanager.css");
- helpers.includeJs("undo-xpopup.js");
- helpers.includeCometJs();
- helpers.includeJQuery();
- helpers.includeJs("json2.js");
- helpers.includeJs("colorutils.js");
- helpers.includeJs("ace.js");
- helpers.includeJs("collab_client.js");
- helpers.includeJs("draggable.js");
- helpers.includeJs("pad_utils.js");
- helpers.includeJs("pad_cookie.js");
- helpers.includeJs("pad_editor.js");
- helpers.includeJs("pad_userlist.js");
- helpers.includeJs("pad_editbar.js");
- helpers.includeJs("pad_chat.js");
- helpers.includeJs("pad_docbar.js");
- helpers.includeJs("pad_impexp.js");
- helpers.includeJs("pad_savedrevs.js");
- helpers.includeJs("pad_connectionstatus.js");
- helpers.includeJs("pad_modals.js");
- helpers.includeJs("pad2.js");
- helpers.suppressGA();
- helpers.setRobotsPolicy({index: false, follow: false});
-
- function inArray(item, arr) {
- for (var i = 0; i < arr.length; i++)
- if (arr[i] == item)
- return true;
- return false;
- }
-%>
-
-<div id="padpage">
- <div id="padtop">
- <div id="topbar">
- <div id="topbarleft"><!-- --></div>
- <div id="topbarright"><!-- --></div>
- <div id="topbarcenter"><a href="/" id="topbaretherpad">EtherPad</a></div>
- <% if (isProAccountHolder) { %>
- <div id="accountnav"><%= toHTML(account.email) %><a href="/ep/account/sign-out">(sign out)</a></div>
- <% } else if (isPro) { %>
- <div id="accountnav"><a href="<%= signinUrl %>">sign in</a></div>
- <% } %>
- </div>
- <div id="docbar" class="docbar-public">
- <div id="docbar">
- <table border="0" cellpadding="0" cellspacing="0" width="100%" id="docbartable">
- <tr>
- <td><img src="/static/img/jun09/pad/roundcorner_left.gif"></td>
- <td id="docbarpadtitle"><span>Plugin manager</span></td>
- <td width="100%">&nbsp;</td>
- <%
- plugins.callHookStr('docbarItemsAll', {}, '', '<td class="docbarbutton" nowrap>', '</td>');
- plugins.callHookStr('docbarItemsPluginManager', {}, '', '<td class="docbarbutton" nowrap>', '</td>');
- %>
- <td><img src="/static/img/jun09/pad/roundcorner_right.gif"></td>
- </tr>
- </table>
-
- </div>
- </div>
- <div id="padmain">
-
- <div id="padsidebar">
- <div id="padusers">
- </div>
-
- <div id="hdraggie"><!-- --></div>
-
- <div id="padchat"></div>
- </div> <!-- /padsidebar -->
-
- <div id="padeditor">
- <div id="editbar" class="enabledtoolbar">
- <div id="editbarleft"><!-- --></div>
- <div id="editbarright"><!-- --></div>
-
- <div id="editbarinner"></div>
- </div>
- <div id="editorcontainerbox">
- <div id="editorcontainer">
- <table>
- <tr>
- <th>Module name</th>
- <th>Status</th>
- <th></th>
- </tr>
- <% for (var plugin in plugins.pluginModules) { %>
- <tr>
- <td class="mousover_parent">
- <%= plugin %>
- <div class="mouseover_child">
- <%= plugins.pluginModules[plugin].description %>
- </div>
- </td>
- <td>
- <% if (plugins.plugins[plugin] !== undefined) { %>
- Installed
- <% } else { %>
- Not installed
- <% } %>
- </td>
- <td>
- <% if (plugins.plugins[plugin] !== undefined) { %>
- <a href="/ep/admin/pluginmanager/?plugin=<%= plugin %>&action=uninstall">Uninstall</a>
- <a href="/ep/admin/pluginmanager/?plugin=<%= plugin %>&action=reinstall">Reinstall</a>
- <% if (plugins.plugins[plugin].configLink !== undefined) { %>
- <a href="<%= plugins.plugins[plugin].configLink %>">Configure</a>
- <% } %>
- <% } else { %>
- <a href="/ep/admin/pluginmanager/?plugin=<%= plugin %>&action=install">Install</a>
- <% } %>
- </td>
- </tr>
- <% } %>
- </table>
- </div>
- </div>
- </div><!-- /padeditor -->
-
- <div id="bottomarea">
- <div id="widthprefcheck" class="widthprefunchecked"><!-- --></div>
- <div id="sidebarcheck" class="sidebarchecked"><!-- --></div>
- </div>
- </div>
-</div>
diff --git a/etherpad/src/templates/pad/pad_body2.ejs b/etherpad/src/templates/pad/pad_body2.ejs
deleted file mode 100644
index 0eb9029..0000000
--- a/etherpad/src/templates/pad/pad_body2.ejs
+++ /dev/null
@@ -1,576 +0,0 @@
-<% /*
-Copyright 2009 Google Inc.
-Copyright 2010 Pita, Peter Martischka
-
-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. */ %>
-<% helpers.setHtmlTitle("EtherPad: "+pageTitle); %>
-<% helpers.setBodyId("padbody") %>
-<% helpers.addBodyClass(bodyClass) %>
-<% helpers.includeCss("pad2_ejs.css") %>
-<% helpers.includeJs("undo-xpopup.js") %>
-<% helpers.includeCometJs() %>
-<% helpers.includeJQuery(); %>
-<% helpers.includeJs("json2.js") %>
-<% helpers.includeJs("colorutils.js") %>
-<% helpers.includeJs("ace.js") %>
-<% helpers.includeJs("collab_client.js") %>
-<% helpers.includeJs("draggable.js") %>
-<% helpers.includeJs("pad_utils.js") %>
-<% helpers.includeJs("pad_cookie.js") %>
-<% helpers.includeJs("pad_editor.js") %>
-<% helpers.includeJs("pad_userlist.js") %>
-<% helpers.includeJs("pad_editbar.js") %>
-<% helpers.includeJs("pad_chat.js") %>
-<% helpers.includeJs("pad_docbar.js") %>
-<% helpers.includeJs("pad_impexp.js") %>
-<% helpers.includeJs("pad_savedrevs.js") %>
-<% helpers.includeJs("pad_connectionstatus.js") %>
-<% helpers.includeJs("pad_modals.js") %>
-<% helpers.includeJs("pad2.js") %>
-<% helpers.suppressGA() %>
-<% helpers.setRobotsPolicy({index: false, follow: false}) %>
-<%
- var padUrlAttrValue = request.url.split("?", 1)[0].replace(/\"/g, '&quot;'); //"
-%>
-
-<%
- function exportLink(type, n, label, requiresOffice, url, title) {
- url = url || '/ep/pad/export/'+localPadId+'/latest?format='+type;
- var classes = ["exportlink", "exporthref"+type, "n"+n];
- if (requiresOffice && !hasOffice) {
- classes.push("disabledexport");
- }
- else {
- classes.push("requiresoffice");
- }
- var pieces = ['<a'];
- pieces.push(' class="', classes.join(' '), '"');
- pieces.push(' target="_blank"');
- pieces.push(' href="', url, '"');
- if (title) {
- pieces.push(' title="', title.replace(/\"/g, "&quot;"), '"'); //"
- }
- pieces.push('>', label);
- /* if (title) {
- pieces.push('<sup>?</sup>');
- }*/
- pieces.push('</a>');
- return pieces.join('');
- }
-%>
-
-<div id="padpage">
-
-<div id="padtop">
- <div id="topbar">
- <% /* floated left */ %>
- <div id="topbarleft"><!-- --></div>
- <% /* <a href="#" id="topbarnewpad">New Pad</a> */ %>
- <% /* floated right */ %>
- <div id="topbarright"><!-- --></div>
- <% /* <a href="#" id="topbarfullwidth">Toggle Width</a> */ %>
- <% /* non-floated */ %>
- <div id="topbarcenter">
- <a href="/" id="topbaretherpad">EtherPad</a>
- </div>
-<% if (isProAccountHolder) { %>
- <a id="backtoprosite" href="/ep/padlist/">Return to pad list</a>
- <div id="accountnav"><%= toHTML(account.email) %>
- <a href="/ep/account/sign-out">(sign out)</a>
- </div>
-<% } else if (isPro) { %>
- <div id="accountnav">
- <a href="<%= signinUrl %>">sign in</a>
- </div>
-<% } %>
- <div id="specialkeyarea"><!-- --></div>
- </div>
- <div id="alertbar">
- <div id="servermsg">
- <h3>Server Notice<span id="servermsgdate"><!-- --></span>:</h3>
- <a id="hidetopmsg" href="javascript: void pad.hideServerMessage()">hide</a>
- <p id="servermsgtext"><!-- --></p>
- </div>
- </div>
-
- <div id="docbar">
- <table border="0" cellpadding="0" cellspacing="0" width="100%" id="docbartable">
- <tr>
- <td><img src="/static/img/jun09/pad/roundcorner_left.gif"></td>
- <td id="docbarpadtitle"><span><%= initialTitle %></span></td>
- <td width="100%">&nbsp;</td>
- <%
- plugins.callHookStr('docbarItemsAll', {}, '', '<td class="docbarbutton">', '</td>');
- plugins.callHookStr('docbarItemsPad', {}, '', '<td class="docbarbutton">', '</td>');
- %>
- <% if (isProAccountHolder) { %>
- <td id="docbarsecurity-outer" class="docbarbutton">
- <a href="javascript:void(0)" id="docbarsecurity">
- <img src="/static/img/jun09/pad/icon_security.gif">Security
- </a>
- </td>
- <% } /* isProAccountHolder */ %>
- <td id="docbaroptions-outer" class="docbarbutton">
- <a href="javascript:void(0)" id="docbaroptions">
- <img src="/static/img/jun09/pad/icon_pad_options.gif">Pad&nbsp;Options</a>
- </td>
- <td id="docbarimpexp-outer" class="docbarbutton">
- <a href="javascript:void(0)" id="docbarimpexp">
- <img src="/static/img/jun09/pad/icon_import_export.gif">Import/Export</a>
- </td>
- <td id="docbarsavedrevs-outer" class="docbarbutton">
- <a href="javascript:void(0)" id="docbarsavedrevs">
- <img src="/static/img/jun09/pad/icon_saved_revisions.gif">Saved&nbsp;revisions</a>
- </td>
- <td id="docbarslider-outer" class="docbarbutton highlight">
- <a target="_blank" href="/ep/pad/view/<%= localPadId %>/latest" id="docbarslider">
- <img src="/static/img/jun09/pad/icon_time_slider.gif">Time&nbsp;Slider</a>
- </td>
- <td><img src="/static/img/jun09/pad/roundcorner_right_orange.gif"></td>
- </tr>
- </table>
- <% if (isProAccountHolder) { %>
- <div id="docbarrenamelink">
- <a href="javascript:void(0)">(rename)</a>
- </div>
- <% } /* isProAccountHolder */ %>
- <input type="text" id="padtitleedit"/>
- <div id="padtitlebuttons">
- <a id="padtitlesave" href="javascript:void(0)">Save</a>
- <a id="padtitlecancel" href="javascript:void(0)">Cancel</a>
- </div>
- <div id="impexp-wrapper" class="dbpanel-wrapper">
- <div id="impexp-panel" class="dbpanel-panel">
- <div class="dbpanel-leftedge"><!-- --></div>
- <div class="dbpanel-rightedge"><!-- --></div>
- <div class="dbpanel-botleftcorner"><!-- --></div>
- <div class="dbpanel-botrightcorner"><!-- --></div>
- <div class="dbpanel-middle">
- <div class="dbpanel-inner">
- <div class="dbpanel-top"><!-- --></div>
- </div>
- <div class="dbpanel-bottom"><!-- --></div>
- <div id="importexport">
- <div id="impexp-import">
- <div id="impexp-importlabel"><b>Import</b> from text file, HTML, Word, or RTF:</div>
- <form id="importform" method="post" action="/ep/pad/impexp/import"
- target="importiframe" enctype="multipart/form-data">
- <div class="importformdiv" id="importformfilediv">
- <input type="file" name="file" size="20" id="importfileinput" />
- <div class="importmessage" id="importmessagefail"></div>
- </div>
- <div class="importmessage" id="importmessagesuccess">Successful!</div>
- <div class="importformdiv" id="importformsubmitdiv">
- <input type="hidden" name="padId" value="<%= encodeURIComponent(localPadId) %>" />
- <span class="nowrap">
- <input type="submit" name="submit" value="Import Now" disabled="disabled" id="importsubmitinput" />
- <img alt="" id="importstatusball" src="/static/img/misc/status-ball.gif" align="top" />
- <img alt="" id="importarrow" src="/static/img/may09/leftarrow2.gif" align="top" />
- </span>
- </div>
- </form>
- </div><!-- /impexp-import -->
- <div id="impexp-export">
- <div id="impexp-exportlabel"><b>Export</b> current pad as:</div>
- <div id="exportlinks">
- <%= exportLink('html', 1, 'HTML', false) %>
- <%= exportLink('txt', 2, 'Plain text', false) %>
- <%= exportLink('link', 3, 'Bookmark file', false, '/ep/pad/linkfile?padId='+localPadId, 'This will save a file that, when opened, takes you to this pad.') %>
- <%= exportLink('doc', 4, 'Microsoft Word', true) %>
- <%= exportLink('pdf', 5, 'PDF', true) %>
- <%= exportLink('odt', 6, 'OpenDocument', true) %>
- </div>
- </div><!-- /impexp-export -->
- <div id="impexp-divider"><!-- --></div>
- <div id="impexp-disabled-clickcatcher"><!-- --></div>
- <a id="impexp-close" href="javascript:void(0)">Hide</a>
- </div><!-- /importexport -->
- </div>
- </div>
- </div>
- <div id="savedrevs-wrapper" class="dbpanel-wrapper">
- <div id="savedrevs-panel" class="dbpanel-panel">
- <div class="dbpanel-leftedge"><!-- --></div>
- <div class="dbpanel-rightedge"><!-- --></div>
- <div class="dbpanel-botleftcorner"><!-- --></div>
- <div class="dbpanel-botrightcorner"><!-- --></div>
- <div class="dbpanel-middle">
- <div class="dbpanel-inner">
- <div class="dbpanel-top"><!-- --></div>
- </div>
- <div class="dbpanel-bottom"><!-- --></div>
- </div>
- <div id="savedrevisions">
- <a href="javascript:void(0)" id="savedrevs-savenow">
- Save Now
- </a>
- <div id="savedrevs-scrolly">
- <div id="savedrevs-scrollleft" class="disabledscrollleft"><!-- --></div>
- <div id="savedrevs-scrollright" class="disabledscrollright"><!-- --></div>
- <div id="savedrevs-scrollouter">
- <div id="savedrevs-scrollinner">
- <!-- -->
- </div>
- </div>
- </div>
- <a id="savedrevs-close" href="javascript:void(0)">Hide</a>
- </div><!-- /savedrevs close -->
- </div>
- </div><!-- /savedrevs-wrapper -->
- <div id="revision-notifier"><span class="label">Saved:</span> <span class="name">Revision 1</span></div>
- <div id="options-wrapper" class="dbpanel-wrapper">
- <div id="options-panel" class="dbpanel-panel">
- <div class="dbpanel-leftedge"><!-- --></div>
- <div class="dbpanel-rightedge"><!-- --></div>
- <div class="dbpanel-botleftcorner"><!-- --></div>
- <div class="dbpanel-botrightcorner"><!-- --></div>
- <div class="dbpanel-middle">
- <div class="dbpanel-inner">
- <div class="dbpanel-top"><!-- --></div>
- </div>
- <div class="dbpanel-bottom"><!-- --></div>
- </div>
- <div id="padoptions">
- <div id="options-viewhead">Shared view options:</div>
- <input type="checkbox" id="options-colorscheck" />
- <label for="options-colorscheck" id="options-colorslabel">Authorship colors</label>
- <input type="checkbox" id="options-linenoscheck" />
- <label for="options-linenoscheck" id="options-linenoslabel">Line numbers</label>
- <div id="options-fontlabel">Display font:</div>
- <select id="viewfontmenu"><option value="normal">Normal</option><option value="monospace">Monospaced</option></select>
- <div id="options-viewexplain">These options affect everyone's view of the pad.</div>
- <a id="options-close" href="javascript:void(0)">Hide</a>
- </div>
- </div>
- </div><!-- /options-wrapper -->
-<% if (isProAccountHolder) { %>
- <div id="security-wrapper" class="dbpanel-wrapper">
- <div id="security-panel" class="dbpanel-panel">
- <div class="dbpanel-leftedge"><!-- --></div>
- <div class="dbpanel-rightedge"><!-- --></div>
- <div class="dbpanel-botleftcorner"><!-- --></div>
- <div class="dbpanel-botrightcorner"><!-- --></div>
- <div class="dbpanel-middle">
- <div class="dbpanel-inner">
- <div class="dbpanel-top"><!-- --></div>
- </div>
- <div class="dbpanel-bottom"><!-- --></div>
- </div>
- <div id="padsecurity">
- <div id="security-access">
- <div id="security-accesshead">Pad Access:</div>
- <input type="radio" name="padaccess" id="access-private" value="deny"/>
- <label for="access-private" id="access-private-label"><strong>Private</strong> (Team account-holders only)</label>
- <input type="radio" name="padaccess" id="access-public" value="allow"/>
- <label for="access-public" id="access-public-label"><strong>Public</strong> (Allow Internet guests)</label>
- </div>
- <div id="security-password">
- <div id="security-passhead">Password:</div>
- <div id="security-passbody">
- <div class="nopassword" id="password-nonedit">
- <div id="password-display">None</div>
- <a href="javascript:void(0)" id="password-setlink">Set...</a>
- <a href="javascript:void(0)" id="password-clearlink">Clear</a>
- </div>
- <div id="password-inedit">
- <a href="javascript:void(0)" id="password-savelink">Save</a>
- <a href="javascript:void(0)" id="password-cancellink">Cancel</a>
- <input type="text" id="security-passwordedit" maxlength="31" />
- </div>
- </div>
- </div>
- <a id="security-close" href="javascript:void(0)">Hide</a>
- </div>
- </div>
- </div><!-- /security-wrapper -->
-<% } /* isProAccountHolder */ %>
- </div><!-- /docbar -->
-</div>
-
-<div id="padmain">
- <div id="padsidebar">
- <div id="padusers">
- <div id="connectionbox" class="cboxconnecting">
- <div id="connectionboxinner">
- <div class="connecting">
- Connecting...
- </div>
- <div class="reconnecting">
- Reestablishing connection...
- </div>
- <div class="disconnected">
- <h2 class="h2_disconnect">Disconnected.</h2>
- <h2 class="h2_userdup">Opened in another window.</h2>
- <h2 class="h2_unauth">No Authorization.</h2>
- <div id="disconnected_looping">
- <p><b>We're having trouble talking to the EtherPad synchronization server.</b>
- You may be connecting through an incompatible firewall or proxy server.</p>
- </div>
- <div id="disconnected_initsocketfail">
- <p><b>We were unable to connect to the EtherPad synchronization server.</b>
- This may be due to an incompatibility with your web
- browser or internet connection.</p>
- </div>
- <div id="disconnected_userdup">
- <p><b>You seem to have opened this pad in another browser window.</b>
- If you'd like to use this window instead, you can reconnect.</p>
- </div>
- <div id="disconnected_unknown">
- <p><b>Lost connection with the EtherPad synchronization
- server.</b> This may be due to a loss of network connectivity.</p>
- </div>
- <div id="disconnected_slowcommit">
- <p><b>Server not responding.</b> This may be due to network connectivity issues or high load on the server.</p>
- </div>
- <div id="disconnected_unauth">
- <p>Your browser's credentials or permissions have changed while viewing this pad. Try reconnecting.</p>
- </div>
- <div id="reconnect_advise">
- <p>If this continues to happen, please <a target="_blank" href="/ep/support">let us know</a>
- (opens in new window).</p>
- </div>
- <div id="reconnect_form">
- <button id="forcereconnect">Reconnect Now</button>
- </div>
- </div>
- </div>
- </div>
-
- <div id="connectionstatus">
- <!-- -->
- </div>
-
- <div id="myuser">
- <div id="mycolorpicker">
- <div>
- <div class="pickerswatchouter n1"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n2"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n3"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n4"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n5"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n6"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n7"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n8"><div class="pickerswatch"><!-- --></div></div>
- </div><div>
- <div class="pickerswatchouter n9"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n10"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n11"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n12"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n13"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n14"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n15"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n16"><div class="pickerswatch"><!-- --></div></div>
- </div><div>
- <div class="pickerswatchouter n17"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n18"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n19"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n20"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n21"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n22"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n23"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n24"><div class="pickerswatch"><!-- --></div></div>
- </div><div>
- <div class="pickerswatchouter n25"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n26"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n27"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n28"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n29"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n30"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n31"><div class="pickerswatch"><!-- --></div></div>
- <div class="pickerswatchouter n32"><div class="pickerswatch"><!-- --></div></div>
- </div>
- <div id="mycolorpickersave">Save</div>
- <div id="mycolorpickercancel">Cancel</div>
- </div>
- <div id="myswatchbox"><div id="myswatch"><!-- --></div></div>
- <div id="myusernameform"><input type="text" id="myusernameedit" disabled="disabled" /></div>
- <div id="mystatusform"><input type="text" id="mystatusedit" disabled="disabled" /></div>
- </div>
- <div id="otherusers">
- <div id="guestprompts"><!-- --></div>
- <table id="otheruserstable" cellspacing="0" cellpadding="0" border="0">
- <tr><td></td></tr>
- </table>
- <div id="nootherusers"><a href="javascript:void(0)">Invite</a> other users and they will show up here.</div>
- </div>
- <div id="userlistbuttonarea">
- <a href="javascript:void(0)" id="sharebutton">Share</a>
- </div>
- </div> <!-- /padusers -->
-
- <div id="hdraggie"><!-- --></div>
-
- <div id="padchat">
-<!-- <div id="chattop"><a href="#">View chat logs...</a></div> -->
- <div id="chatlines">
- <a href="javascript:void(0)" id="chatloadmore">Load more history...</a>
- <div id="chatloadingmore">Loading history...</div>
- </div>
- <div id="chatbottom">
- <div id="chatprompt">Chat:</div>
- <div id="chatentryform"><input type="text" id="chatentrybox"/></div>
- </div>
- </div>
- </div> <!-- /padsidebar -->
-
- <div id="padeditor">
- <div id="editbar" class="disabledtoolbar">
- <% /* floated left */ %>
- <div id="editbarleft"><!-- --></div>
- <% /* floated right */ %>
- <div id="editbarright"><!-- --></div>
- <% /* non-floated */ %>
- <div id="editbarinner">
- <table cellpadding="0" cellspacing="0" border = "0" id="editbartable"><tr>
- <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
- <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('bold'));" title="Bold (ctrl-B)"><img src="/static/img/jun09/pad/editbar_bold.gif"></a></td>
- <td class="editbarbutton"> <a href="javascript:void (window.pad&&pad.editbarClick('italic'));" title="Italics (ctrl-I)"><img src="/static/img/jun09/pad/editbar_italic.gif"></a></td>
- <td class="editbarbutton"> <a href="javascript:void (window.pad&&pad.editbarClick('underline'));" title="Underline (ctrl-U)"><img src="/static/img/jun09/pad/editbar_underline.gif"></a></td>
- <td class="editbarbutton"> <a href="javascript:void (window.pad&&pad.editbarClick('strikethrough'));" title="Strikethrough"><img src="/static/img/jun09/pad/editbar_strikethrough.gif"></a></td>
- <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
-
- <td>&nbsp;&nbsp;</td>
-
- <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
- <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('insertunorderedlist'));" title="Toggle Bullet List"><img src="/static/img/jun09/pad/editbar_insertunorderedlist.gif"></a></td>
- <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
-
- <td>&nbsp;&nbsp;</td>
-
- <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
- <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('indent'));" title="Indent List"><img src="/static/img/jun09/pad/editbar_indent.gif"></a></td>
- <td class="editbarbutton"><a href="javascript:void (window.pad&&pad.editbarClick('outdent'));" title="Unindent List"><img src="/static/img/jun09/pad/editbar_outdent.gif"></a></td>
- <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
-
- <td>&nbsp;&nbsp;</td>
-
- <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
- <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('clearauthorship'));" title="Clear Authorship Colors"><img src="/static/img/jun09/pad/editbar_clearauthorship.gif"></a></td>
- <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
-
- <td>&nbsp;&nbsp;</td>
-
- <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
- <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('undo'));" title="Undo (ctrl-Z)"><img src="/static/img/jun09/pad/editbar_undo.gif"></a></td>
- <td class="editbarbutton"><a href="javascript:void (window.pad&&pad.editbarClick('redo'));" title="Redo (ctrl-Y)"><img src="/static/img/jun09/pad/editbar_redo.gif"></a></td>
- <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
-
- <td width="100%">&nbsp;</td>
- </tr></table>
- <table cellpadding="0" cellspacing="0" border = "0" id="editbarsavetable">
- <tr>
- <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
- <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('save'));" title="Save Revision"><img src="/static/img/jun09/pad/editbar_save.gif"></a></td>
- <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
- </tr>
- </table>
- </div>
- </div>
- <div id="editorcontainerbox">
- <div id="editorloadingbox">Loading...</div>
- <div id="editorcontainer"><!-- --></div>
- </div>
- </div><!-- /padeditor -->
-
- <div id="bottomarea">
- <div id="viewbarcontents">
- <div id="viewzoomtitle">Zoom:</div>
- <select id="viewzoommenu"><option value="z85">85%</option><option value="z100">100%</option><option value="z115">115%</option><option value="z150">150%</option><option value="z200">200%</option><option value="z300">300%</option></select>
- </div>
-
- <div id="widthprefcheck"
- class="<%= (prefs.isFullWidth?'widthprefchecked':'widthprefunchecked') %>"
- ><!-- --></div>
- <div id="sidebarcheck"
- class="<%= (prefs.hideSidebar?'sidebarunchecked':'sidebarchecked') %>"
- ><!-- --></div>
- </div>
-
-</div><!-- /padmain -->
-
-</div><!-- /padpage -->
-
-<div id="modaloverlay"><div id="modaloverlay-inner"><!-- --></div></div>
-<div id="mainmodals">
- <div id="feedbackbox">
- <div id="feedbackbox-tl"><!-- --></div>
- <div id="feedbackbox-tr"><!-- --></div>
- <div id="feedbackbox-bl"><!-- --></div>
- <div id="feedbackbox-br"><!-- --></div>
- <div id="feedbackbox-back"><!-- --></div>
-<%/* <a href="javascript:void(0)" id="feedbackbox-send"><!-- --></a>
- <input type="text" id="feedbackbox-email" class="modalfield" />
- <textarea id="feedbackbox-message" rows="6" cols="40" class="modalfield"></textarea>
- <div id="feedbackbox-response"><!-- --></div>*/%>
- <div id="feedbackbox-contents">
- <div id="feedbackbox-contentsinner">
- <p><strong>Great, we love feedback! What kind?</strong></p>
- <ul id="uservoicelinks">
- <li><a href="http://uservoice.etherpad.com/pages/17280-feature-requests" target="_blank">Feature Request</a></li>
- <li><a href="http://uservoice.etherpad.com/pages/17285-bugs-and-problems" target="_blank">Bug Report</a></li>
- <li><a href="http://uservoice.etherpad.com/pages/22732-how-are-you-using-etherpad-" target="_blank">How I'm Using It</a></li>
- <li><a href="http://uservoice.etherpad.com/pages/22751-general-questions" target="_blank">Other Question</a></li>
- <li><a href="http://uservoice.etherpad.com/pages/22733-general-feedback" target="_blank">Other Feedback</a></li>
- </ul>
- <p>These links will open UserVoice in a new window.</p>
- <p id="feedbackemails">You can also send email to <a href="feedback"><tt>feedback</tt></a>, <a href="support"><tt>support</tt></a>, or <a href="bugs"><tt>bugs</tt></a> at <tt>etherpad.com</tt>.</p>
- </div>
- </div>
- <a href="javascript:void(0)" id="feedbackbox-hide"><!-- --></a>
- </div>
- <div id="sharebox">
- <div id="sharebox-inner">
- <a href="javascript:void(0)" id="sharebox-hide"><!-- --></a>
- <div id="sharebox-stripe" class="sharebox-stripe-private">
- <div class="public">
- <strong>Public Pad:</strong> This pad is accessible to anyone who
- visits its URL. To make it private, <a href="javascript:void(0)" class="setsecurity">change security settings</a>.
- </div>
- <div class="private">
- <strong>Private Pad:</strong> This pad is only accessible to team account-holders. To allow anyone to access it, <a href="javascript:void(0)" class="setsecurity">change security settings</a>.
- </div>
- </div>
- <div id="sharebox-forms">
- <div id="sharebox-pastelink">Paste link over email or IM:</div>
- <div id="sharebox-orsend">or send an email invitation...</div>
- <a href="javascript:void(0)" id="sharebox-send"><!-- --></a>
- <input id="sharebox-url" type="text" readonly="readonly" value="<%=padUrlAttrValue%>"/>
- <input type="text" id="sharebox-to" class="modalfield" />
- <input type="text" id="sharebox-subject" class="modalfield" />
- <textarea id="sharebox-message" rows="6" cols="40" class="modalfield"></textarea>
- <div id="sharebox-fieldname-to">To</div>
- <div id="sharebox-fieldname-subject">Subject</div>
- <div id="sharebox-fieldname-message">Message</div>
- <div id="sharebox-dislink"><!-- --></div>
- </div>
- <div id="sharebox-shownwhenexpanded">
- <div id="sharebox-response"><!-- --></div>
- </div>
- </div>
- </div>
-</div>
-
-<% if (request.params.djs) { %>
- <div id="djs"><!-- --></div>
-<% } %>
-
-<form id="reconnectform"
- method="post"
- action="/ep/pad/reconnect"
- accept-charset="UTF-8"
- style="display: none;">
- <input type="hidden" class="padId" name="padId" />
- <input type="hidden" class="diagnosticInfo"
- name="diagnosticInfo" />
- <input type="hidden" class="missedChanges" name="missedChanges" />
-</form>
diff --git a/etherpad/src/templates/500_body.ejs b/etherpad/src/themes/default/templates/500_body.ejs
index 291e0fd..291e0fd 100644
--- a/etherpad/src/templates/500_body.ejs
+++ b/etherpad/src/themes/default/templates/500_body.ejs
diff --git a/etherpad/src/themes/default/templates/admin/pluginmanager.ejs b/etherpad/src/themes/default/templates/admin/pluginmanager.ejs
new file mode 100644
index 0000000..cc47928
--- /dev/null
+++ b/etherpad/src/themes/default/templates/admin/pluginmanager.ejs
@@ -0,0 +1,74 @@
+<% /* 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. */ %>
+<%
+ template.inherit('page.ejs');
+ helpers.setHtmlTitle("EtherPad: Manage plugins");
+ helpers.includeCss("admin/pluginmanager.css");
+
+ function inArray(item, arr) {
+ for (var i = 0; i < arr.length; i++)
+ if (arr[i] == item)
+ return true;
+ return false;
+ }
+%>
+
+<% template.define('docBarTitle', function() { var ejs_data=''; %>
+ <td id="docbarpadtitle"><span>Plugin manager</span></td>
+<% return ejs_data; }); %>
+
+
+<% template.define('docBarItems', function() { var ejs_data=''; %>
+ <%: plugins.callHookStr('docbarItemsPluginManager', {}, '', '<td class="docbarbutton">', '</td>'); %>
+<% return ejs_data; }); %>
+
+<% template.define('contentArea', function() { var ejs_data=''; %>
+ <div id="editorcontainer">
+ <table>
+ <tr>
+ <th>Module name</th>
+ <th>Status</th>
+ <th></th>
+ </tr>
+ <% for (var plugin in plugins.pluginModules) { %>
+ <tr>
+ <td class="mousover_parent">
+ <%= plugin %>
+ <div class="mouseover_child">
+ <%= plugins.pluginModules[plugin].description %>
+ </div>
+ </td>
+ <td>
+ <% if (plugins.plugins[plugin] !== undefined) { %>
+ Installed
+ <% } else { %>
+ Not installed
+ <% } %>
+ </td>
+ <td>
+ <% if (plugins.plugins[plugin] !== undefined) { %>
+ <a href="/ep/admin/pluginmanager/?plugin=<%= plugin %>&action=uninstall">Uninstall</a>
+ <a href="/ep/admin/pluginmanager/?plugin=<%= plugin %>&action=reinstall">Reinstall</a>
+ <% if (plugins.plugins[plugin].configLink !== undefined) { %>
+ <a href="<%= plugins.plugins[plugin].configLink %>">Configure</a>
+ <% } %>
+ <% } else { %>
+ <a href="/ep/admin/pluginmanager/?plugin=<%= plugin %>&action=install">Install</a>
+ <% } %>
+ </td>
+ </tr>
+ <% } %>
+ </table>
+ </div>
+<% return ejs_data; }); %>
diff --git a/etherpad/src/templates/email/padinvite.ejs b/etherpad/src/themes/default/templates/email/padinvite.ejs
index c6467b8..c6467b8 100644
--- a/etherpad/src/templates/email/padinvite.ejs
+++ b/etherpad/src/themes/default/templates/email/padinvite.ejs
diff --git a/etherpad/src/templates/framed/framedfooter.ejs b/etherpad/src/themes/default/templates/framed/framedfooter.ejs
index 7994e38..7994e38 100644
--- a/etherpad/src/templates/framed/framedfooter.ejs
+++ b/etherpad/src/themes/default/templates/framed/framedfooter.ejs
diff --git a/etherpad/src/templates/framed/framedheader-pro.ejs b/etherpad/src/themes/default/templates/framed/framedheader-pro.ejs
index 73b0e99..73b0e99 100644
--- a/etherpad/src/templates/framed/framedheader-pro.ejs
+++ b/etherpad/src/themes/default/templates/framed/framedheader-pro.ejs
diff --git a/etherpad/src/templates/framed/framedheader.ejs b/etherpad/src/themes/default/templates/framed/framedheader.ejs
index d6c25cb..d6c25cb 100644
--- a/etherpad/src/templates/framed/framedheader.ejs
+++ b/etherpad/src/themes/default/templates/framed/framedheader.ejs
diff --git a/etherpad/src/templates/framed/framedpage-pro.ejs b/etherpad/src/themes/default/templates/framed/framedpage-pro.ejs
index b3acb07..b3acb07 100644
--- a/etherpad/src/templates/framed/framedpage-pro.ejs
+++ b/etherpad/src/themes/default/templates/framed/framedpage-pro.ejs
diff --git a/etherpad/src/templates/framed/framedpage.ejs b/etherpad/src/themes/default/templates/framed/framedpage.ejs
index b1590f8..b1590f8 100644
--- a/etherpad/src/templates/framed/framedpage.ejs
+++ b/etherpad/src/themes/default/templates/framed/framedpage.ejs
diff --git a/etherpad/src/templates/html.ejs b/etherpad/src/themes/default/templates/html.ejs
index 056d7a7..056d7a7 100644
--- a/etherpad/src/templates/html.ejs
+++ b/etherpad/src/themes/default/templates/html.ejs
diff --git a/etherpad/src/templates/main/home.ejs b/etherpad/src/themes/default/templates/main/home.ejs
index aa5d934..aa5d934 100644
--- a/etherpad/src/templates/main/home.ejs
+++ b/etherpad/src/themes/default/templates/main/home.ejs
diff --git a/etherpad/src/templates/main/pro_signup_body.ejs b/etherpad/src/themes/default/templates/main/pro_signup_body.ejs
index e984878..e984878 100644
--- a/etherpad/src/templates/main/pro_signup_body.ejs
+++ b/etherpad/src/themes/default/templates/main/pro_signup_body.ejs
diff --git a/etherpad/src/templates/misc/pad_default.ejs b/etherpad/src/themes/default/templates/misc/pad_default.ejs
index 96b7e25..96b7e25 100644
--- a/etherpad/src/templates/misc/pad_default.ejs
+++ b/etherpad/src/themes/default/templates/misc/pad_default.ejs
diff --git a/etherpad/src/templates/notice.ejs b/etherpad/src/themes/default/templates/notice.ejs
index 311694f..311694f 100644
--- a/etherpad/src/templates/notice.ejs
+++ b/etherpad/src/themes/default/templates/notice.ejs
diff --git a/etherpad/src/templates/pad/create_body.ejs b/etherpad/src/themes/default/templates/pad/create_body.ejs
index 5fec49a..5fec49a 100644
--- a/etherpad/src/templates/pad/create_body.ejs
+++ b/etherpad/src/themes/default/templates/pad/create_body.ejs
diff --git a/etherpad/src/themes/default/templates/pad/pad_body2.ejs b/etherpad/src/themes/default/templates/pad/pad_body2.ejs
new file mode 100644
index 0000000..5c886fb
--- /dev/null
+++ b/etherpad/src/themes/default/templates/pad/pad_body2.ejs
@@ -0,0 +1,505 @@
+<% /*
+Copyright 2009 Google Inc.
+Copyright 2010 Pita, Peter Martischka
+
+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. */ %>
+
+<%
+ template.inherit('page.ejs');
+
+ helpers.setHtmlTitle("EtherPad: "+pageTitle);
+ helpers.includeJs("ace.js");
+ helpers.includeJs("collab_client.js");
+ helpers.includeJs("pad_userlist.js");
+ helpers.includeJs("pad_chat.js");
+ helpers.includeJs("pad_impexp.js");
+ helpers.includeJs("pad_savedrevs.js");
+ helpers.includeJs("pad_connectionstatus.js");
+
+ var padUrlAttrValue = request.url.split("?", 1)[0].replace(/\"/g, '&quot;');
+
+ function exportLink(type, n, label, requiresOffice, url, title) {
+ url = url || '/ep/pad/export/'+localPadId+'/latest?format='+type;
+ var classes = ["exportlink", "exporthref"+type, "n"+n];
+ if (requiresOffice && !hasOffice) {
+ classes.push("disabledexport");
+ }
+ else {
+ classes.push("requiresoffice");
+ }
+ var pieces = ['<a'];
+ pieces.push(' class="', classes.join(' '), '"');
+ pieces.push(' target="_blank"');
+ pieces.push(' href="', url, '"');
+ if (title) {
+ pieces.push(' title="', title.replace(/\"/g, "&quot;"), '"'); //"
+ }
+ pieces.push('>', label);
+ /* if (title) {
+ pieces.push('<sup>?</sup>');
+ }*/
+ pieces.push('</a>');
+ return pieces.join('');
+ }
+%>
+
+
+<% template.define('docBarTitle', function() { var ejs_data=''; %>
+ <td id="docbarpadtitle"><span><%= initialTitle %></span></td>
+<% return ejs_data; }); %>
+
+
+<% template.define('docBarTitleEditor', function() { var ejs_data=''; %>
+ <% if (isProAccountHolder) { %>
+ <div id="docbarrenamelink">
+ <a href="javascript:void(0)">(rename)</a>
+ </div>
+ <% } /* isProAccountHolder */ %>
+ <input type="text" id="padtitleedit"/>
+ <div id="padtitlebuttons">
+ <a id="padtitlesave" href="javascript:void(0)">Save</a>
+ <a id="padtitlecancel" href="javascript:void(0)">Cancel</a>
+ </div>
+<% return ejs_data; }); %>
+
+
+<% template.define('docBarItems', function() { var ejs_data=''; %>
+ <%: plugins.callHookStr('docbarItemsPad', {}, '', '<td class="docbarbutton">', '</td>'); %>
+ <% if (isProAccountHolder) { %>
+ <td id="docbarsecurity-outer" class="docbarbutton">
+ <a href="javascript:void(0)" id="docbarsecurity">
+ <img src="/static/img/jun09/pad/icon_security.gif">Security
+ </a>
+ </td>
+ <% } /* isProAccountHolder */ %>
+ <td id="docbaroptions-outer" class="docbarbutton">
+ <a href="javascript:void(0)" id="docbaroptions">
+ <img src="/static/img/jun09/pad/icon_pad_options.gif">Pad&nbsp;Options</a>
+ </td>
+ <td id="docbarimpexp-outer" class="docbarbutton">
+ <a href="javascript:void(0)" id="docbarimpexp">
+ <img src="/static/img/jun09/pad/icon_import_export.gif">Import/Export</a>
+ </td>
+ <td id="docbarsavedrevs-outer" class="docbarbutton">
+ <a href="javascript:void(0)" id="docbarsavedrevs">
+ <img src="/static/img/jun09/pad/icon_saved_revisions.gif">Saved&nbsp;revisions</a>
+ </td>
+ <td id="docbarslider-outer" class="docbarbutton highlight">
+ <a target="_blank" href="/ep/pad/view/<%= localPadId %>/latest" id="docbarslider">
+ <img src="/static/img/jun09/pad/icon_time_slider.gif">Time&nbsp;Slider</a>
+ </td>
+<% return ejs_data; }); %>
+
+
+<% template.define('docBarDropdowns', function() { var ejs_data=''; %>
+ <div id="impexp-wrapper" class="dbpanel-wrapper">
+ <div id="impexp-panel" class="dbpanel-panel">
+ <div class="dbpanel-leftedge"><!-- --></div>
+ <div class="dbpanel-rightedge"><!-- --></div>
+ <div class="dbpanel-botleftcorner"><!-- --></div>
+ <div class="dbpanel-botrightcorner"><!-- --></div>
+ <div class="dbpanel-middle">
+ <div class="dbpanel-inner">
+ <div class="dbpanel-top"><!-- --></div>
+ </div>
+ <div class="dbpanel-bottom"><!-- --></div>
+ <div id="importexport">
+ <div id="impexp-import">
+ <div id="impexp-importlabel"><b>Import</b> from text file, HTML, Word, or RTF:</div>
+ <form id="importform" method="post" action="/ep/pad/impexp/import"
+ target="importiframe" enctype="multipart/form-data">
+ <div class="importformdiv" id="importformfilediv">
+ <input type="file" name="file" size="20" id="importfileinput" />
+ <div class="importmessage" id="importmessagefail"></div>
+ </div>
+ <div class="importmessage" id="importmessagesuccess">Successful!</div>
+ <div class="importformdiv" id="importformsubmitdiv">
+ <input type="hidden" name="padId" value="<%= encodeURIComponent(localPadId) %>" />
+ <span class="nowrap">
+ <input type="submit" name="submit" value="Import Now" disabled="disabled" id="importsubmitinput" />
+ <img alt="" id="importstatusball" src="/static/img/misc/status-ball.gif" align="top" />
+ <img alt="" id="importarrow" src="/static/img/may09/leftarrow2.gif" align="top" />
+ </span>
+ </div>
+ </form>
+ </div><!-- /impexp-import -->
+ <div id="impexp-export">
+ <div id="impexp-exportlabel"><b>Export</b> current pad as:</div>
+ <div id="exportlinks">
+ <%= exportLink('html', 1, 'HTML', false) %>
+ <%= exportLink('txt', 2, 'Plain text', false) %>
+ <%= exportLink('link', 3, 'Bookmark file', false, '/ep/pad/linkfile?padId='+localPadId, 'This will save a file that, when opened, takes you to this pad.') %>
+ <%= exportLink('doc', 4, 'Microsoft Word', true) %>
+ <%= exportLink('pdf', 5, 'PDF', true) %>
+ <%= exportLink('odt', 6, 'OpenDocument', true) %>
+ </div>
+ </div><!-- /impexp-export -->
+ <div id="impexp-divider"><!-- --></div>
+ <div id="impexp-disabled-clickcatcher"><!-- --></div>
+ <a id="impexp-close" href="javascript:void(0)">Hide</a>
+ </div><!-- /importexport -->
+ </div>
+ </div>
+ </div>
+ <div id="savedrevs-wrapper" class="dbpanel-wrapper">
+ <div id="savedrevs-panel" class="dbpanel-panel">
+ <div class="dbpanel-leftedge"><!-- --></div>
+ <div class="dbpanel-rightedge"><!-- --></div>
+ <div class="dbpanel-botleftcorner"><!-- --></div>
+ <div class="dbpanel-botrightcorner"><!-- --></div>
+ <div class="dbpanel-middle">
+ <div class="dbpanel-inner">
+ <div class="dbpanel-top"><!-- --></div>
+ </div>
+ <div class="dbpanel-bottom"><!-- --></div>
+ </div>
+ <div id="savedrevisions">
+ <a href="javascript:void(0)" id="savedrevs-savenow">
+ Save Now
+ </a>
+ <div id="savedrevs-scrolly">
+ <div id="savedrevs-scrollleft" class="disabledscrollleft"><!-- --></div>
+ <div id="savedrevs-scrollright" class="disabledscrollright"><!-- --></div>
+ <div id="savedrevs-scrollouter">
+ <div id="savedrevs-scrollinner">
+ <!-- -->
+ </div>
+ </div>
+ </div>
+ <a id="savedrevs-close" href="javascript:void(0)">Hide</a>
+ </div><!-- /savedrevs close -->
+ </div>
+ </div><!-- /savedrevs-wrapper -->
+ <div id="revision-notifier"><span class="label">Saved:</span> <span class="name">Revision 1</span></div>
+ <div id="options-wrapper" class="dbpanel-wrapper">
+ <div id="options-panel" class="dbpanel-panel">
+ <div class="dbpanel-leftedge"><!-- --></div>
+ <div class="dbpanel-rightedge"><!-- --></div>
+ <div class="dbpanel-botleftcorner"><!-- --></div>
+ <div class="dbpanel-botrightcorner"><!-- --></div>
+ <div class="dbpanel-middle">
+ <div class="dbpanel-inner">
+ <div class="dbpanel-top"><!-- --></div>
+ </div>
+ <div class="dbpanel-bottom"><!-- --></div>
+ </div>
+ <div id="padoptions">
+ <div id="options-viewhead">Shared view options:</div>
+ <input type="checkbox" id="options-colorscheck" />
+ <label for="options-colorscheck" id="options-colorslabel">Authorship colors</label>
+ <input type="checkbox" id="options-linenoscheck" />
+ <label for="options-linenoscheck" id="options-linenoslabel">Line numbers</label>
+ <div id="options-fontlabel">Display font:</div>
+ <select id="viewfontmenu"><option value="normal">Normal</option><option value="monospace">Monospaced</option></select>
+ <div id="options-viewexplain">These options affect everyone's view of the pad.</div>
+ <a id="options-close" href="javascript:void(0)">Hide</a>
+ </div>
+ </div>
+ </div><!-- /options-wrapper -->
+ <% if (isProAccountHolder) { %>
+ <div id="security-wrapper" class="dbpanel-wrapper">
+ <div id="security-panel" class="dbpanel-panel">
+ <div class="dbpanel-leftedge"><!-- --></div>
+ <div class="dbpanel-rightedge"><!-- --></div>
+ <div class="dbpanel-botleftcorner"><!-- --></div>
+ <div class="dbpanel-botrightcorner"><!-- --></div>
+ <div class="dbpanel-middle">
+ <div class="dbpanel-inner">
+ <div class="dbpanel-top"><!-- --></div>
+ </div>
+ <div class="dbpanel-bottom"><!-- --></div>
+ </div>
+ <div id="padsecurity">
+ <div id="security-access">
+ <div id="security-accesshead">Pad Access:</div>
+ <input type="radio" name="padaccess" id="access-private" value="deny"/>
+ <label for="access-private" id="access-private-label"><strong>Private</strong> (Team account-holders only)</label>
+ <input type="radio" name="padaccess" id="access-public" value="allow"/>
+ <label for="access-public" id="access-public-label"><strong>Public</strong> (Allow Internet guests)</label>
+ </div>
+ <div id="security-password">
+ <div id="security-passhead">Password:</div>
+ <div id="security-passbody">
+ <div class="nopassword" id="password-nonedit">
+ <div id="password-display">None</div>
+ <a href="javascript:void(0)" id="password-setlink">Set...</a>
+ <a href="javascript:void(0)" id="password-clearlink">Clear</a>
+ </div>
+ <div id="password-inedit">
+ <a href="javascript:void(0)" id="password-savelink">Save</a>
+ <a href="javascript:void(0)" id="password-cancellink">Cancel</a>
+ <input type="text" id="security-passwordedit" maxlength="31" />
+ </div>
+ </div>
+ </div>
+ <a id="security-close" href="javascript:void(0)">Hide</a>
+ </div>
+ </div>
+ </div><!-- /security-wrapper -->
+ <% } /* isProAccountHolder */ %>
+<% return ejs_data; }); %>
+
+
+<% template.define('sideBar', function() { var ejs_data=''; %>
+ <div id="padusers">
+ <div id="connectionbox" class="cboxconnecting">
+ <div id="connectionboxinner">
+ <div class="connecting">
+ Connecting...
+ </div>
+ <div class="reconnecting">
+ Reestablishing connection...
+ </div>
+ <div class="disconnected">
+ <h2 class="h2_disconnect">Disconnected.</h2>
+ <h2 class="h2_userdup">Opened in another window.</h2>
+ <h2 class="h2_unauth">No Authorization.</h2>
+ <div id="disconnected_looping">
+ <p><b>We're having trouble talking to the EtherPad synchronization server.</b>
+ You may be connecting through an incompatible firewall or proxy server.</p>
+ </div>
+ <div id="disconnected_initsocketfail">
+ <p><b>We were unable to connect to the EtherPad synchronization server.</b>
+ This may be due to an incompatibility with your web
+ browser or internet connection.</p>
+ </div>
+ <div id="disconnected_userdup">
+ <p><b>You seem to have opened this pad in another browser window.</b>
+ If you'd like to use this window instead, you can reconnect.</p>
+ </div>
+ <div id="disconnected_unknown">
+ <p><b>Lost connection with the EtherPad synchronization
+ server.</b> This may be due to a loss of network connectivity.</p>
+ </div>
+ <div id="disconnected_slowcommit">
+ <p><b>Server not responding.</b> This may be due to network connectivity issues or high load on the server.</p>
+ </div>
+ <div id="disconnected_unauth">
+ <p>Your browser's credentials or permissions have changed while viewing this pad. Try reconnecting.</p>
+ </div>
+ <div id="reconnect_advise">
+ <p>If this continues to happen, please <a target="_blank" href="/ep/support">let us know</a>
+ (opens in new window).</p>
+ </div>
+ <div id="reconnect_form">
+ <button id="forcereconnect">Reconnect Now</button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div id="connectionstatus">
+ <!-- -->
+ </div>
+
+ <div id="myuser">
+ <div id="mycolorpicker">
+ <div>
+ <div class="pickerswatchouter n1"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n2"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n3"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n4"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n5"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n6"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n7"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n8"><div class="pickerswatch"><!-- --></div></div>
+ </div><div>
+ <div class="pickerswatchouter n9"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n10"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n11"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n12"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n13"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n14"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n15"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n16"><div class="pickerswatch"><!-- --></div></div>
+ </div><div>
+ <div class="pickerswatchouter n17"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n18"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n19"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n20"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n21"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n22"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n23"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n24"><div class="pickerswatch"><!-- --></div></div>
+ </div><div>
+ <div class="pickerswatchouter n25"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n26"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n27"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n28"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n29"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n30"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n31"><div class="pickerswatch"><!-- --></div></div>
+ <div class="pickerswatchouter n32"><div class="pickerswatch"><!-- --></div></div>
+ </div>
+ <div id="mycolorpickersave">Save</div>
+ <div id="mycolorpickercancel">Cancel</div>
+ </div>
+ <div id="myswatchbox"><div id="myswatch"><!-- --></div></div>
+ <div id="myusernameform"><input type="text" id="myusernameedit" disabled="disabled" /></div>
+ <div id="mystatusform"><input type="text" id="mystatusedit" disabled="disabled" /></div>
+ </div>
+ <div id="otherusers">
+ <div id="guestprompts"><!-- --></div>
+ <table id="otheruserstable" cellspacing="0" cellpadding="0" border="0">
+ <tr><td></td></tr>
+ </table>
+ <div id="nootherusers"><a href="javascript:void(0)">Invite</a> other users and they will show up here.</div>
+ </div>
+ <div id="userlistbuttonarea">
+ <a href="javascript:void(0)" id="sharebutton">Share</a>
+ </div>
+ </div> <!-- /padusers -->
+
+ <div id="hdraggie"><!-- --></div>
+
+ <div id="padchat">
+ <!-- <div id="chattop"><a href="#">View chat logs...</a></div> -->
+ <div id="chatlines">
+ <a href="javascript:void(0)" id="chatloadmore">Load more history...</a>
+ <div id="chatloadingmore">Loading history...</div>
+ </div>
+ <div id="chatbottom">
+ <div id="chatprompt">Chat:</div>
+ <div id="chatentryform"><input type="text" id="chatentrybox"/></div>
+ </div>
+ </div>
+<% return ejs_data; }); %>
+
+
+<% template.define('editBarItemsLeft', function() { var ejs_data=''; %>
+ <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
+ <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('bold'));" title="Bold (ctrl-B)"><img src="/static/img/jun09/pad/editbar_bold.gif"></a></td>
+ <td class="editbarbutton"> <a href="javascript:void (window.pad&&pad.editbarClick('italic'));" title="Italics (ctrl-I)"><img src="/static/img/jun09/pad/editbar_italic.gif"></a></td>
+ <td class="editbarbutton"> <a href="javascript:void (window.pad&&pad.editbarClick('underline'));" title="Underline (ctrl-U)"><img src="/static/img/jun09/pad/editbar_underline.gif"></a></td>
+ <td class="editbarbutton"> <a href="javascript:void (window.pad&&pad.editbarClick('strikethrough'));" title="Strikethrough"><img src="/static/img/jun09/pad/editbar_strikethrough.gif"></a></td>
+ <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
+
+ <td>&nbsp;&nbsp;</td>
+
+ <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
+ <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('insertunorderedlist'));" title="Toggle Bullet List"><img src="/static/img/jun09/pad/editbar_insertunorderedlist.gif"></a></td>
+ <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
+
+ <td>&nbsp;&nbsp;</td>
+
+ <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
+ <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('indent'));" title="Indent List"><img src="/static/img/jun09/pad/editbar_indent.gif"></a></td>
+ <td class="editbarbutton"><a href="javascript:void (window.pad&&pad.editbarClick('outdent'));" title="Unindent List"><img src="/static/img/jun09/pad/editbar_outdent.gif"></a></td>
+ <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
+
+ <td>&nbsp;&nbsp;</td>
+
+ <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
+ <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('clearauthorship'));" title="Clear Authorship Colors"><img src="/static/img/jun09/pad/editbar_clearauthorship.gif"></a></td>
+ <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
+
+ <td>&nbsp;&nbsp;</td>
+
+ <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
+ <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('undo'));" title="Undo (ctrl-Z)"><img src="/static/img/jun09/pad/editbar_undo.gif"></a></td>
+ <td class="editbarbutton"><a href="javascript:void (window.pad&&pad.editbarClick('redo'));" title="Redo (ctrl-Y)"><img src="/static/img/jun09/pad/editbar_redo.gif"></a></td>
+ <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
+<% return ejs_data; }); %>
+
+
+<% template.define('editBarItemsRight', function() { var ejs_data=''; %>
+ <td><img src="/static/img/jun09/pad/editbar_groupleft.gif" width="2" height="24"></td>
+ <td class="editbarbutton editbargroupsfirst"><a href="javascript:void (window.pad&&pad.editbarClick('save'));" title="Save Revision"><img src="/static/img/jun09/pad/editbar_save.gif"></a></td>
+ <td><img src="/static/img/jun09/pad/editbar_groupright.gif" width="2" height="24"></td>
+<% return ejs_data; }); %>
+
+
+<% template.define('contentArea', function() { var ejs_data=''; %>
+ <div id="editorloadingbox">Loading...</div>
+ <div id="editorcontainer"><!-- --></div>
+<% return ejs_data; }); %>
+
+
+<% template.define('modals', function() { var ejs_data=''; %>
+ <div id="modaloverlay"><div id="modaloverlay-inner"><!-- --></div></div>
+
+ <div id="mainmodals">
+ <div id="feedbackbox">
+ <div id="feedbackbox-tl"><!-- --></div>
+ <div id="feedbackbox-tr"><!-- --></div>
+ <div id="feedbackbox-bl"><!-- --></div>
+ <div id="feedbackbox-br"><!-- --></div>
+ <div id="feedbackbox-back"><!-- --></div>
+ <%/* <a href="javascript:void(0)" id="feedbackbox-send"><!-- --></a>
+ <input type="text" id="feedbackbox-email" class="modalfield" />
+ <textarea id="feedbackbox-message" rows="6" cols="40" class="modalfield"></textarea>
+ <div id="feedbackbox-response"><!-- --></div>*/%>
+ <div id="feedbackbox-contents">
+ <div id="feedbackbox-contentsinner">
+ <p><strong>Great, we love feedback! What kind?</strong></p>
+ <ul id="uservoicelinks">
+ <li><a href="http://uservoice.etherpad.com/pages/17280-feature-requests" target="_blank">Feature Request</a></li>
+ <li><a href="http://uservoice.etherpad.com/pages/17285-bugs-and-problems" target="_blank">Bug Report</a></li>
+ <li><a href="http://uservoice.etherpad.com/pages/22732-how-are-you-using-etherpad-" target="_blank">How I'm Using It</a></li>
+ <li><a href="http://uservoice.etherpad.com/pages/22751-general-questions" target="_blank">Other Question</a></li>
+ <li><a href="http://uservoice.etherpad.com/pages/22733-general-feedback" target="_blank">Other Feedback</a></li>
+ </ul>
+ <p>These links will open UserVoice in a new window.</p>
+ <p id="feedbackemails">You can also send email to <a href="feedback"><tt>feedback</tt></a>, <a href="support"><tt>support</tt></a>, or <a href="bugs"><tt>bugs</tt></a> at <tt>etherpad.com</tt>.</p>
+ </div>
+ </div>
+ <a href="javascript:void(0)" id="feedbackbox-hide"><!-- --></a>
+ </div>
+ <div id="sharebox">
+ <div id="sharebox-inner">
+ <a href="javascript:void(0)" id="sharebox-hide"><!-- --></a>
+ <div id="sharebox-stripe" class="sharebox-stripe-private">
+ <div class="public">
+ <strong>Public Pad:</strong> This pad is accessible to anyone who
+ visits its URL. To make it private, <a href="javascript:void(0)" class="setsecurity">change security settings</a>.
+ </div>
+ <div class="private">
+ <strong>Private Pad:</strong> This pad is only accessible to team account-holders. To allow anyone to access it, <a href="javascript:void(0)" class="setsecurity">change security settings</a>.
+ </div>
+ </div>
+ <div id="sharebox-forms">
+ <div id="sharebox-pastelink">Paste link over email or IM:</div>
+ <div id="sharebox-orsend">or send an email invitation...</div>
+ <a href="javascript:void(0)" id="sharebox-send"><!-- --></a>
+ <input id="sharebox-url" type="text" readonly="readonly" value="<%=padUrlAttrValue%>"/>
+ <input type="text" id="sharebox-to" class="modalfield" />
+ <input type="text" id="sharebox-subject" class="modalfield" />
+ <textarea id="sharebox-message" rows="6" cols="40" class="modalfield"></textarea>
+ <div id="sharebox-fieldname-to">To</div>
+ <div id="sharebox-fieldname-subject">Subject</div>
+ <div id="sharebox-fieldname-message">Message</div>
+ <div id="sharebox-dislink"><!-- --></div>
+ </div>
+ <div id="sharebox-shownwhenexpanded">
+ <div id="sharebox-response"><!-- --></div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <% if (request.params.djs) { %>
+ <div id="djs"><!-- --></div>
+ <% } %>
+
+ <form id="reconnectform"
+ method="post"
+ action="/ep/pad/reconnect"
+ accept-charset="UTF-8"
+ style="display: none;">
+ <input type="hidden" class="padId" name="padId" />
+ <input type="hidden" class="diagnosticInfo"
+ name="diagnosticInfo" />
+ <input type="hidden" class="missedChanges" name="missedChanges" />
+ </form>
+
+<% return ejs_data; }); %>
diff --git a/etherpad/src/templates/pad/pad_iphone_body.ejs b/etherpad/src/themes/default/templates/pad/pad_iphone_body.ejs
index 96279ce..96279ce 100644
--- a/etherpad/src/templates/pad/pad_iphone_body.ejs
+++ b/etherpad/src/themes/default/templates/pad/pad_iphone_body.ejs
diff --git a/etherpad/src/templates/pad/padview_body.ejs b/etherpad/src/themes/default/templates/pad/padview_body.ejs
index 75c38fe..75c38fe 100644
--- a/etherpad/src/templates/pad/padview_body.ejs
+++ b/etherpad/src/themes/default/templates/pad/padview_body.ejs
diff --git a/etherpad/src/themes/default/templates/page.ejs b/etherpad/src/themes/default/templates/page.ejs
new file mode 100644
index 0000000..3d1632a
--- /dev/null
+++ b/etherpad/src/themes/default/templates/page.ejs
@@ -0,0 +1,135 @@
+<% /*
+Copyright 2009 Google Inc.
+Copyright 2010 Pita, Peter Martischka
+
+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. */ %>
+<%
+ helpers.setBodyId("padbody");
+ helpers.addBodyClass(bodyClass);
+ helpers.includeCss("pad2_ejs.css");
+ helpers.includeJs("undo-xpopup.js");
+ helpers.includeCometJs();
+ helpers.includeJQuery();;
+ helpers.includeJs("json2.js");
+ helpers.includeJs("colorutils.js");
+ helpers.includeJs("draggable.js");
+ helpers.includeJs("pad_utils.js");
+ helpers.includeJs("pad_cookie.js");
+ helpers.includeJs("pad_editor.js");
+ helpers.includeJs("pad_editbar.js");
+ helpers.includeJs("pad_docbar.js");
+ helpers.includeJs("pad_modals.js");
+ helpers.includeJs("pad2.js");
+ helpers.suppressGA();
+ helpers.setRobotsPolicy({index: false, follow: false});
+
+%>
+
+<% template.define('body', function() { var ejs_data=''; %>
+ <div id="padpage">
+ <div id="padtop">
+ <div id="topbar">
+ <% /* floated left */ %>
+ <div id="topbarleft"><!-- --></div>
+ <% /* <a href="#" id="topbarnewpad">New Pad</a> */ %>
+ <% /* floated right */ %>
+ <div id="topbarright"><!-- --></div>
+ <% /* <a href="#" id="topbarfullwidth">Toggle Width</a> */ %>
+ <% /* non-floated */ %>
+ <div id="topbarcenter">
+ <a href="/" id="topbaretherpad">EtherPad</a>
+ </div>
+ <% if (isProAccountHolder) { %>
+ <a id="backtoprosite" href="/ep/padlist/">Return to pad list</a>
+ <div id="accountnav"><%= toHTML(account.email) %>
+ <a href="/ep/account/sign-out">(sign out)</a>
+ </div>
+ <% } else if (isPro) { %>
+ <div id="accountnav">
+ <a href="<%= signinUrl %>">sign in</a>
+ </div>
+ <% } %>
+ <div id="specialkeyarea"><!-- --></div>
+ </div>
+ <div id="alertbar">
+ <div id="servermsg">
+ <h3>Server Notice<span id="servermsgdate"><!-- --></span>:</h3>
+ <a id="hidetopmsg" href="javascript: void pad.hideServerMessage()">hide</a>
+ <p id="servermsgtext"><!-- --></p>
+ </div>
+ </div>
+
+ <div id="docbar">
+ <table border="0" cellpadding="0" cellspacing="0" width="100%" id="docbartable">
+ <tr>
+ <td><img src="/static/img/jun09/pad/roundcorner_left.gif"></td>
+ <%: template.use('docBarTitle'); %>
+ <td width="100%">&nbsp;</td>
+ <%: template.use('docBarItems'); %>
+ <%: plugins.callHookStr('docbarItemsAll', {}, '', '', ''); %>
+ <td><img src="/static/img/jun09/pad/roundcorner_right_orange.gif"></td>
+ </tr>
+ </table>
+ <%: template.use('docBarTitleEditor'); %>
+ <%: template.use('docBarDropdowns'); %>
+ </div><!-- /docbar -->
+ </div>
+
+ <div id="padmain">
+ <div id="padsidebar"><%: template.use('sideBar'); %></div>
+
+ <div id="padeditor">
+ <div id="editbar" class="disabledtoolbar">
+ <% /* floated left */ %>
+ <div id="editbarleft"><!-- --></div>
+ <% /* floated right */ %>
+ <div id="editbarright"><!-- --></div>
+ <% /* non-floated */ %>
+ <div id="editbarinner">
+ <table cellpadding="0" cellspacing="0" border = "0" id="editbartable">
+ <tr>
+ <%: template.use('editBarItemsLeft'); %>
+ <td width="100%">&nbsp;</td>
+ </tr>
+ </table>
+ <table cellpadding="0" cellspacing="0" border = "0" id="editbarsavetable">
+ <tr>
+ <%: template.use('editBarItemsRight'); %>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <div id="editorcontainerbox"><%: template.use('contentArea'); %></div>
+ </div><!-- /padeditor -->
+
+ <div id="bottomarea">
+ <div id="viewbarcontents">
+ <div id="viewzoomtitle">Zoom:</div>
+ <select id="viewzoommenu"><option value="z85">85%</option><option value="z100">100%</option><option value="z115">115%</option><option value="z150">150%</option><option value="z200">200%</option><option value="z300">300%</option></select>
+ </div>
+
+ <div id="widthprefcheck"
+ class="<%= (prefs.isFullWidth?'widthprefchecked':'widthprefunchecked') %>"
+ ><!-- --></div>
+ <div id="sidebarcheck"
+ class="<%= (prefs.hideSidebar?'sidebarunchecked':'sidebarchecked') %>"
+ ><!-- --></div>
+ </div>
+
+ </div><!-- /padmain -->
+
+ </div><!-- /padpage -->
+
+ <%: template.use('modals'); %>
+
+<% return ejs_data; }); %>
diff --git a/etherpad/src/templates/pro-account/recover.ejs b/etherpad/src/themes/default/templates/pro-account/recover.ejs
index 686fe3b..686fe3b 100644
--- a/etherpad/src/templates/pro-account/recover.ejs
+++ b/etherpad/src/themes/default/templates/pro-account/recover.ejs
diff --git a/etherpad/src/templates/pro-account/sign-in.ejs b/etherpad/src/themes/default/templates/pro-account/sign-in.ejs
index 470bbc4..470bbc4 100644
--- a/etherpad/src/templates/pro-account/sign-in.ejs
+++ b/etherpad/src/themes/default/templates/pro-account/sign-in.ejs
diff --git a/etherpad/src/templates/pro-help/main.ejs b/etherpad/src/themes/default/templates/pro-help/main.ejs
index 428d7f7..428d7f7 100644
--- a/etherpad/src/templates/pro-help/main.ejs
+++ b/etherpad/src/themes/default/templates/pro-help/main.ejs
diff --git a/etherpad/src/templates/pro-help/pro-help-template.ejs b/etherpad/src/themes/default/templates/pro-help/pro-help-template.ejs
index 9cc8205..9cc8205 100644
--- a/etherpad/src/templates/pro-help/pro-help-template.ejs
+++ b/etherpad/src/themes/default/templates/pro-help/pro-help-template.ejs
diff --git a/etherpad/src/templates/pro/account/account-welcome-email.ejs b/etherpad/src/themes/default/templates/pro/account/account-welcome-email.ejs
index 25af6f8..25af6f8 100644
--- a/etherpad/src/templates/pro/account/account-welcome-email.ejs
+++ b/etherpad/src/themes/default/templates/pro/account/account-welcome-email.ejs
diff --git a/etherpad/src/templates/pro/account/forgot-password-email.ejs b/etherpad/src/themes/default/templates/pro/account/forgot-password-email.ejs
index 4595cee..4595cee 100644
--- a/etherpad/src/templates/pro/account/forgot-password-email.ejs
+++ b/etherpad/src/themes/default/templates/pro/account/forgot-password-email.ejs
diff --git a/etherpad/src/templates/pro/account/forgot-password.ejs b/etherpad/src/themes/default/templates/pro/account/forgot-password.ejs
index bbc78dd..bbc78dd 100644
--- a/etherpad/src/templates/pro/account/forgot-password.ejs
+++ b/etherpad/src/themes/default/templates/pro/account/forgot-password.ejs
diff --git a/etherpad/src/templates/pro/account/my-account.ejs b/etherpad/src/themes/default/templates/pro/account/my-account.ejs
index 9634285..9634285 100644
--- a/etherpad/src/templates/pro/account/my-account.ejs
+++ b/etherpad/src/themes/default/templates/pro/account/my-account.ejs
diff --git a/etherpad/src/templates/pro/account/signin.ejs b/etherpad/src/themes/default/templates/pro/account/signin.ejs
index c67bea6..c67bea6 100644
--- a/etherpad/src/templates/pro/account/signin.ejs
+++ b/etherpad/src/themes/default/templates/pro/account/signin.ejs
diff --git a/etherpad/src/templates/pro/admin/account-manager.ejs b/etherpad/src/themes/default/templates/pro/admin/account-manager.ejs
index f1b443f..f1b443f 100644
--- a/etherpad/src/templates/pro/admin/account-manager.ejs
+++ b/etherpad/src/themes/default/templates/pro/admin/account-manager.ejs
diff --git a/etherpad/src/templates/pro/admin/admin-template.ejs b/etherpad/src/themes/default/templates/pro/admin/admin-template.ejs
index e1a7736..e1a7736 100644
--- a/etherpad/src/templates/pro/admin/admin-template.ejs
+++ b/etherpad/src/themes/default/templates/pro/admin/admin-template.ejs
diff --git a/etherpad/src/templates/pro/admin/delete-account.ejs b/etherpad/src/themes/default/templates/pro/admin/delete-account.ejs
index 3de2122..3de2122 100644
--- a/etherpad/src/templates/pro/admin/delete-account.ejs
+++ b/etherpad/src/themes/default/templates/pro/admin/delete-account.ejs
diff --git a/etherpad/src/templates/pro/admin/manage-account.ejs b/etherpad/src/themes/default/templates/pro/admin/manage-account.ejs
index 72529b4..72529b4 100644
--- a/etherpad/src/templates/pro/admin/manage-account.ejs
+++ b/etherpad/src/themes/default/templates/pro/admin/manage-account.ejs
diff --git a/etherpad/src/templates/pro/admin/new-account.ejs b/etherpad/src/themes/default/templates/pro/admin/new-account.ejs
index 2f2cccf..2f2cccf 100644
--- a/etherpad/src/templates/pro/admin/new-account.ejs
+++ b/etherpad/src/themes/default/templates/pro/admin/new-account.ejs
diff --git a/etherpad/src/templates/pro/padlist/pro-padlist.ejs b/etherpad/src/themes/default/templates/pro/padlist/pro-padlist.ejs
index b762679..b762679 100644
--- a/etherpad/src/templates/pro/padlist/pro-padlist.ejs
+++ b/etherpad/src/themes/default/templates/pro/padlist/pro-padlist.ejs
diff --git a/etherpad/src/templates/pro/pro_home.ejs b/etherpad/src/themes/default/templates/pro/pro_home.ejs
index 8d92139..8d92139 100644
--- a/etherpad/src/templates/pro/pro_home.ejs
+++ b/etherpad/src/themes/default/templates/pro/pro_home.ejs
diff --git a/infrastructure/ace/www/ace2_outer.js b/infrastructure/ace/www/ace2_outer.js
index e6d430d..f947534 100644
--- a/infrastructure/ace/www/ace2_outer.js
+++ b/infrastructure/ace/www/ace2_outer.js
@@ -168,7 +168,7 @@ function Ace2Editor() {
var iframeHTML = ["'"+doctype+"<html><head>'"];
- top.plugins.callHook(
+ plugins.callHook(
"aceInitInnerdocbodyHead", {iframeHTML:iframeHTML});
// these lines must conform to a specific format because they are passed by the build script:
@@ -203,6 +203,18 @@ function Ace2Editor() {
'\x3cscript>', outerScript, '\x3c/script>',
'</head><body id="outerdocbody"><div id="sidediv"><!-- --></div><div id="linemetricsdiv">x</div><div id="overlaysdiv"><!-- --></div></body></html>'];
+
+ if (!Array.prototype.map) Array.prototype.map = function(fun) { //needed for IE
+ if (typeof fun != "function") throw new TypeError();
+ var len = this.length;
+ var res = new Array(len);
+ var thisp = arguments[1];
+ for (var i = 0; i < len; i++) {
+ if (i in this) res[i] = fun.call(thisp, this[i], i, this);
+ }
+ return res;
+ };
+
var outerFrame = document.createElement("IFRAME");
outerFrame.frameBorder = 0; // for IE
info.frame = outerFrame;
diff --git a/infrastructure/ace/www/domline.js b/infrastructure/ace/www/domline.js
index 90e9943..f1d19e4 100644
--- a/infrastructure/ace/www/domline.js
+++ b/infrastructure/ace/www/domline.js
@@ -101,7 +101,14 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument) {
var extraOpenTags = "";
var extraCloseTags = "";
- (function () { try { return top.plugins; } catch (e) { return plugins; }; })().callHook(
+ var plugins_;
+ if (typeof(plugins)!='undefined') {
+ plugins_ = plugins;
+ } else {
+ plugins_ = parent.parent.plugins;
+ }
+
+ plugins_.callHook(
"aceCreateDomLine", {domline:domline, cls:cls}
).map(function (modifier) {
cls = modifier.cls;
diff --git a/infrastructure/ace/www/linestylefilter.js b/infrastructure/ace/www/linestylefilter.js
index c163120..196cb63 100644
--- a/infrastructure/ace/www/linestylefilter.js
+++ b/infrastructure/ace/www/linestylefilter.js
@@ -238,7 +238,14 @@ linestylefilter.textAndClassFuncSplitter = function(func, splitPointsOpt) {
linestylefilter.getFilterStack = function(lineText, textAndClassFunc, browser) {
var func = linestylefilter.getURLFilter(lineText, textAndClassFunc);
- var hookFilters = (function () { try { return top.plugins; } catch (e) { return plugins; }; })().callHook(
+ var plugins_;
+ if (typeof(plugins)!='undefined') {
+ plugins_ = plugins;
+ } else {
+ plugins_ = parent.parent.plugins;
+ }
+
+ var hookFilters = plugins_.callHook(
"aceGetFilterStack", {linestylefilter:linestylefilter, browser:browser});
hookFilters.map(function (hookFilter) {
func = hookFilter(lineText, func);
diff --git a/infrastructure/com.etherpad/licensing.scala b/infrastructure/com.etherpad/licensing.scala
index 9318f78..68019f5 100644
--- a/infrastructure/com.etherpad/licensing.scala
+++ b/infrastructure/com.etherpad/licensing.scala
@@ -134,7 +134,7 @@ object Licensing {
println("Done.");
}
case "genmainkey" => {
- println("Generating key for etherpad.com...");
+ println("Generating main key...");
config.values("licenseGeneratorKey") = args(1);
val out = new PrintWriter(new FileOutputStream(args(2)));
out.print(generateKey("etherpad", "AppJet", -1, 0, -1, 0, 0, 0))
diff --git a/infrastructure/framework-src/modules/ejs.js b/infrastructure/framework-src/modules/ejs.js
index bf14ed3..58c67bc 100644
--- a/infrastructure/framework-src/modules/ejs.js
+++ b/infrastructure/framework-src/modules/ejs.js
@@ -33,6 +33,7 @@
import("jsutils.*");
import("funhtml");
+import("etherpad.log");
jimport("java.lang.System.out.println");
jimport("net.appjet.ajstdlib.execution.executeCodeInNewScope");
@@ -75,12 +76,13 @@ var EjsScanner = function(source, left, right) {
this.double_left = left+'%%';
this.double_right = '%%'+right;
this.left_equal = left+'%=';
+ this.left_colon = left+'%:';
this.left_comment = left+'%#';
if(left=='[') {
- this.SplitRegexp = /(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/;
+ this.SplitRegexp = /(\[%%)|(%%\])|(\[%:)|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/;
}
else {
- this.SplitRegexp = new RegExp('('+this.double_left+')|(%%'+this.double_right+')|('+this.left_equal+')|('+this.left_comment+')|('+this.left_delimiter+')|('+this.right_delimiter+'\n)|('+this.right_delimiter+')|(\n)')
+ this.SplitRegexp = new RegExp('('+this.double_left+')|(%%'+this.double_right+')|('+this.left_equal+')|('+this.left_colon+')|('+this.left_equal+')|('+this.left_comment+')|('+this.left_delimiter+')|('+this.right_delimiter+'\n)|('+this.right_delimiter+')|(\n)')
}
this.source = source;
@@ -178,7 +180,7 @@ EjsBuffer.prototype = {
/* Adaptation from the Compiler of erb.rb */
EjsCompiler = function(source, left) {
- this.pre_cmd = ['var ___ejsO = "";'];
+ this.pre_cmd = ['var ejs_data = "";'];
this.post_cmd = new Array();
this.source = ' ';
if (source != null)
@@ -217,7 +219,7 @@ EjsCompiler.prototype = {
compile: function(options) {
options = options || {};
this.out = '';
- var put_cmd = "___ejsO += ";
+ var put_cmd = "ejs_data += ";
var insert_cmd = put_cmd;
var buff = new EjsBuffer(this.pre_cmd, this.post_cmd);
var content = '';
@@ -241,6 +243,7 @@ EjsCompiler.prototype = {
break;
case scanner.left_delimiter:
case scanner.left_equal:
+ case scanner.left_colon:
case scanner.left_comment:
scanner.stag = token;
if (content.length > 0)
@@ -277,6 +280,9 @@ EjsCompiler.prototype = {
case scanner.left_equal:
buff.push(insert_cmd + "(EjsScanner.to_text(" + content + "))");
break;
+ case scanner.left_colon:
+ buff.push(insert_cmd + content);
+ break;
}
scanner.stag = null;
content = '';
@@ -302,7 +308,7 @@ EjsCompiler.prototype = {
' with(_VIEW) {',
' with (_CONTEXT) {',
this.out,
- ' return ___ejsO;',
+ ' return ejs_data;',
' }',
' }',
'};'