diff options
Diffstat (limited to '')
69 files changed, 1568 insertions, 3101 deletions
@@ -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%"> </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 <"+userInfo.userId+">"); - return; - } - var bgcolor = clientVars.colorPalette[userInfo.colorId]; - box.empty().html([ - '<div class="userinfowrap' + (isMe ? ' myuserwrap' : '') + '">', - '<div class="usercolor" style="background-color: ',bgcolor, '">', - ' </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+');">', - ' </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> | <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: '; - } - if (areFewer) { - content += '<a class="small_link" href="javascript:void pad.fewerRevisions();">fewer</a>'; - } - if (areMore && areFewer) { - content += ' | '; - } - 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, '<').replace(/\>/g, '>'); -}; - -//---------------------------------------------------------------- -// 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"> (', chatTime(t), ')</span>: ', - '<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%"> </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, '"'); //" -%> - -<% - 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, """), '"'); //" - } - 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%"> </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 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 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 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> </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> </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> </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> </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%"> </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, '"'); + + 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, """), '"'); //" + } + 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 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 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 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> </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> </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> </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> </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%"> </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%"> </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;', ' }', ' }', '};' |