Merge branch 'develop' into fix/list-removal

This commit is contained in:
Matthias Bartelmeß 2012-04-07 03:42:16 +02:00
commit 8be1deda6f
17 changed files with 318 additions and 237 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ bin/convertSettings.json
src/static/js/jquery.js
npm-debug.log
*.DS_Store
.ep_initialized

View File

@ -6,27 +6,27 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//serve index.html under /
args.app.get('/', function(req, res)
{
res.send(eejs.require("ep_etherpad-lite/templates/index.html"), { maxAge: exports.maxAge });
res.send(eejs.require("ep_etherpad-lite/templates/index.html"));
});
//serve robots.txt
args.app.get('/robots.txt', function(req, res)
{
var filePath = path.normalize(__dirname + "/../../../static/robots.txt");
res.sendfile(filePath, { maxAge: exports.maxAge });
res.sendfile(filePath);
});
//serve favicon.ico
args.app.get('/favicon.ico', function(req, res)
{
var filePath = path.normalize(__dirname + "/../../../static/custom/favicon.ico");
res.sendfile(filePath, { maxAge: exports.maxAge }, function(err)
res.sendfile(filePath, function(err)
{
//there is no custom favicon, send the default favicon
if(err)
{
filePath = path.normalize(__dirname + "/../../../static/favicon.ico");
res.sendfile(filePath, { maxAge: exports.maxAge });
res.sendfile(filePath);
}
});
});
@ -34,13 +34,13 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//serve pad.html under /p
args.app.get('/p/:pad', function(req, res, next)
{
res.send(eejs.require("ep_etherpad-lite/templates/pad.html"), { maxAge: exports.maxAge });
res.send(eejs.require("ep_etherpad-lite/templates/pad.html"));
});
//serve timeslider.html under /p/$padname/timeslider
args.app.get('/p/:pad/timeslider', function(req, res, next)
{
res.send(eejs.require("ep_etherpad-lite/templates/timeslider.html"), { maxAge: exports.maxAge });
res.send(eejs.require("ep_etherpad-lite/templates/timeslider.html"));
});
}

View File

@ -51,10 +51,6 @@ console.log("Report bugs at https://github.com/Pita/etherpad-lite/issues")
var serverName = "Etherpad-Lite " + version + " (http://j.mp/ep-lite)";
//cache 6 hours, by default
var hour = 60*60;
exports.maxAge = settings.maxAge || 6 * hour;
//set loglevel
log4js.setGlobalLogLevel(settings.loglevel);
@ -92,7 +88,12 @@ async.waterfall([
//let the server listen
app.listen(settings.port, settings.ip);
console.log("Server is listening at " + settings.ip + ":" + settings.port);
if(settings.adminHttpAuth){
console.log("Plugin admin page listening at " + settings.ip + ":" + settings.port + "/admin/plugins");
}
else{
console.log("Admin username and password not set in settings.json. To access admin please uncomment and edit adminHttpAuth in settings.json");
}
callback(null);
}
]);

View File

@ -108,7 +108,7 @@ exports.minify = function(req, res, next)
date = new Date(date);
res.setHeader('last-modified', date.toUTCString());
res.setHeader('date', (new Date()).toUTCString());
if (settings.maxAge) {
if (settings.maxAge !== undefined) {
var expiresDate = new Date((new Date()).getTime()+settings.maxAge*1000);
res.setHeader('expires', expiresDate.toUTCString());
res.setHeader('cache-control', 'max-age=' + settings.maxAge);

49
src/static/css/admin.css Normal file
View File

@ -0,0 +1,49 @@
table {
border-collapse: collapse;
}
td, th {
border: 1px solid black;
padding-left: 10px;
padding-right: 10px;
padding-top: 2px;
padding-bottom: 2px;
}
.template {
display: none;
}
.dialog {
display: none;
position: absolute;
left: 50%;
top: 50%;
width: 700px;
height: 500px;
margin-left: -350px;
margin-top: -250px;
border: 3px solid #999999;
background: #eeeeee;
}
.dialog .title {
margin: 0;
padding: 2px;
border-bottom: 3px solid #999999;
font-size: 24px;
line-height: 24px;
height: 24px;
overflow: hidden;
}
.dialog .title .close {
float: right;
}
.dialog .history {
background: #222222;
color: #eeeeee;
position: absolute;
top: 41px;
bottom: 10px;
left: 10px;
right: 10px;
padding: 2px;
overflow: auto;
}

View File

@ -42,9 +42,8 @@ a img
border-bottom: 1px solid #ccc;
overflow: hidden;
padding-top: 3px;
position: absolute;
left: 0;
right: 0;
width: 100%;
white-space: nowrap;
height: 32px;
}
@ -177,7 +176,6 @@ a#backtoprosite { padding-left: 20px; left: 6px;
background: url(static/img/protop.gif) no-repeat -5px -6px; }
#accountnav { right: 30px; color: #fff; }
.propad a#topbaretherpad { background: url(static/img/protop.gif) no-repeat -397px -3px; }
#specialkeyarea { top: 5px; left: 250px; color: yellow; font-weight: bold;
font-size: 1.5em; position: absolute; }
@ -606,8 +604,6 @@ table#otheruserstable { display: none; }
text-align: left;
}
.nonprouser #sharebox-stripe { display: none; }
.sharebox-url {
width: 440px; height: 18px;
text-align: left;

View File

@ -1,4 +1,7 @@
#editorcontainerbox {overflow:auto; top:40px;}
#editorcontainerbox {
overflow:auto; top:40px;
position: static;
}
#padcontent {font-size:12px; padding:10px;}
@ -67,8 +70,9 @@
width:122px;
}
.topbarcenter, #docbar {display:none;}
#padmain {top:30px;}
#padmain {top:0px !important;}
#editbarright {float:right;}
#returnbutton {color:#222; font-size:16px; line-height:29px; margin-top:0; padding-right:6px;}
#importexport .popup {width:185px;}
@ -77,6 +81,53 @@
width:185px;
}
.timeslider-bar
{
background: #f7f7f7;
background: linear-gradient(#f7f7f7, #f1f1f1 80%);
border-bottom: 1px solid #ccc;
overflow: hidden;
padding-top: 3px;
width: 100%;
}
.timeslider-bar #editbar
{
border-bottom: none;
float: right;
width: 170px;
width: initial;
}
.timeslider-bar h1
{
margin: 5px;
}
.timeslider-bar p
{
margin: 5px;
}
#timeslider-top {
width: 100%;
position: fixed;
z-index: 1;
}
#authorsList .author {
padding-left: 0.4em;
padding-right: 0.4em;
}
#authorsList .author-anonymous {
padding-left: 0.6em;
padding-right: 0.6em;
}
#padeditor {
position: static;
}
/* lists */
.list-bullet2, .list-indent2, .list-number2 {margin-left:3em;}
.list-bullet3, .list-indent3, .list-number3 {margin-left:4.5em;}

View File

@ -2,28 +2,78 @@ var Changeset = require('./Changeset');
var ChangesetUtils = require('./ChangesetUtils');
var _ = require('./underscore');
var lineMarkerAttribute = 'lmkr';
// If one of these attributes are set to the first character of a
// line it is considered as a line attribute marker i.e. attributes
// set on this marker are applied to the whole line.
// The list attribute is only maintained for compatibility reasons
var lineAttributes = [lineMarkerAttribute,'list'];
/*
The Attribute manager builds changesets based on a document
representation for setting and removing range or line-based attributes.
@param rep the document representation to be used
@param applyChangesetCallback this callback will be called
once a changeset has been built.
*/
var AttributeManager = function(rep, applyChangesetCallback)
{
this.rep = rep;
this.applyChangesetCallback = applyChangesetCallback;
this.author = '';
// If the first char in a line has one of the following attributes
// it will be considered as a line marker
};
AttributeManager.prototype = _(AttributeManager.prototype).extend({
applyChangeset: function(changeset){
if(!this.applyChangesetCallback) return changeset;
var cs = changeset.toString();
if (!Changeset.isIdentity(cs))
{
this.applyChangesetCallback(cs);
}
return changeset;
},
/*
Sets attributes on a range
@param start [row, col] tuple pointing to the start of the range
@param end [row, col] tuple pointing to the end of the range
@param attribute: an array of attributes
*/
setAttributesOnRange: function(start, end, attribs)
{
var builder = Changeset.builder(this.rep.lines.totalWidth());
ChangesetUtils.buildKeepToStartOfRange(this.rep, builder, start);
ChangesetUtils.buildKeepRange(this.rep, builder, start, end, attribs, this.rep.apool);
return this.applyChangeset(builder);
},
/*
Returns if the line already has a line marker
@param lineNum: the number of the line
*/
lineHasMarker: function(lineNum){
// get "list" attribute of first char of line
return this.getAttributeOnLine(lineNum, 'list');
var that = this;
return _.find(lineAttributes, function(attribute){
return that.getAttributeOnLine(lineNum, attribute) != '';
}) !== undefined;
},
/*
Gets a specified attribute on a line
@param lineNum: the number of the line to set the attribute for
@param attributeKey: the name of the attribute to get, e.g. list
*/
getAttributeOnLine: function(lineNum, attributeName){
// get `attributeName` attribute of first char of line
var aline = this.rep.alines[lineNum];
@ -61,6 +111,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
builder.insert('*', [
['author', this.author],
['insertorder', 'first'],
[lineMarkerAttribute, '1'],
[attributeName, attributeValue]
], this.rep.apool);
}
@ -80,8 +131,6 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
var builder = Changeset.builder(this.rep.lines.totalWidth());
var hasMarker = this.lineHasMarker(lineNum);
// TODO
if(hasMarker){
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
ChangesetUtils.buildRemoveRange(this.rep, builder, loc, (loc = [lineNum, 1]));

View File

@ -22,6 +22,12 @@
* limitations under the License.
*/
/*
An AttributePool maintains a mapping from [key,value] Pairs called
Attributes to Numbers (unsigened integers) and vice versa. These numbers are
used to reference Attributes in Changesets.
*/
var AttributePool = function () {
this.numToAttrib = {}; // e.g. {0: ['foo','bar']}
this.attribToNum = {}; // e.g. {'foo,bar': 0}

View File

@ -35,6 +35,8 @@ var isNodeText = Ace2Common.isNodeText,
binarySearchInfinite = Ace2Common.binarySearchInfinite,
htmlPrettyEscape = Ace2Common.htmlPrettyEscape,
noop = Ace2Common.noop;
var hooks = require('./pluginfw/hooks');
function Ace2Inner(){
@ -2203,6 +2205,9 @@ function Ace2Inner(){
}
/*
Converts the position of a char (index in String) into a [row, col] tuple
*/
function lineAndColumnFromChar(x)
{
var lineEntry = rep.lines.atOffset(x);
@ -2269,32 +2274,17 @@ function Ace2Inner(){
function performDocumentApplyAttributesToCharRange(start, end, attribs)
{
if (end >= rep.alltext.length)
{
end = rep.alltext.length - 1;
}
performDocumentApplyAttributesToRange(lineAndColumnFromChar(start), lineAndColumnFromChar(end), attribs);
end = Math.min(end, rep.alltext.length - 1);
documentAttributeManager.setAttributesOnRange(lineAndColumnFromChar(start), lineAndColumnFromChar(end), attribs);
}
editorInfo.ace_performDocumentApplyAttributesToCharRange = performDocumentApplyAttributesToCharRange;
function performDocumentApplyAttributesToRange(start, end, attribs)
{
var builder = Changeset.builder(rep.lines.totalWidth());
ChangesetUtils.buildKeepToStartOfRange(rep, builder, start);
ChangesetUtils.buildKeepRange(rep, builder, start, end, attribs, rep.apool);
var cs = builder.toString();
performDocumentApplyChangeset(cs);
}
editorInfo.ace_performDocumentApplyAttributesToRange = performDocumentApplyAttributesToRange;
// TODO move to AttributeManager
function setAttributeOnSelection(attributeName, attributeValue)
{
if (!(rep.selStart && rep.selEnd)) return;
performDocumentApplyAttributesToRange(rep.selStart, rep.selEnd, [
documentAttributeManager.setAttributesOnRange(rep.selStart, rep.selEnd, [
[attributeName, attributeValue]
]);
}
@ -2355,13 +2345,13 @@ function Ace2Inner(){
if (selectionAllHasIt)
{
performDocumentApplyAttributesToRange(rep.selStart, rep.selEnd, [
documentAttributeManager.setAttributesOnRange(rep.selStart, rep.selEnd, [
[attributeName, '']
]);
}
else
{
performDocumentApplyAttributesToRange(rep.selStart, rep.selEnd, [
documentAttributeManager.setAttributesOnRange(rep.selStart, rep.selEnd, [
[attributeName, 'true']
]);
}
@ -2883,6 +2873,10 @@ function Ace2Inner(){
"ul": 1
};
_.each(hooks.callAll('aceRegisterBlockElements'), function(element){
_blockElems[element] = 1;
})
function isBlockElement(n)
{
return !!_blockElems[(n.tagName || "").toLowerCase()];
@ -3320,7 +3314,7 @@ function Ace2Inner(){
}
_.each(mods, function(mod){
setLineListType.apply(this, mod);
setLineListType(mod[0], mod[1]);
});
return true;
}
@ -4845,7 +4839,6 @@ function Ace2Inner(){
function setLineListType(lineNum, listType)
{
debugger;
if(listType == ''){
documentAttributeManager.removeAttributeOnLine(lineNum, listAttributeName);
}else{
@ -4977,7 +4970,7 @@ function Ace2Inner(){
}
_.each(mods, function(mod){
setLineListType.apply(this, mod);
setLineListType(mod[0], mod[1]);
});
}
@ -5401,8 +5394,8 @@ function Ace2Inner(){
// Init documentAttributeManager
documentAttributeManager = new AttributeManager(rep, performDocumentApplyChangeset);
editorInfo.ace_performDocumentApplyAttributesToRange = documentAttributeManager.setAttributesOnRange;
$(document).ready(function(){
doc = document; // defined as a var in scope outside
@ -5442,7 +5435,13 @@ function Ace2Inner(){
bindTheEventHandlers();
});
hooks.callAll('aceInitialized', {
editorInfo: editorInfo,
rep: rep,
documentAttributeManager: documentAttributeManager
});
scheduler.setTimeout(function()
{
parent.readyFunc(); // defined in code that sets up the inner iframe

View File

@ -170,41 +170,67 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
$('#error').show();
}
var fixPadHeight = _.throttle(function(){
var height = $('#timeslider-top').height();
$('#editorcontainerbox').css({marginTop: height});
}, 600);
function setAuthors(authors)
{
$("#authorstable").empty();
var authorsList = $("#authorsList");
authorsList.empty();
var numAnonymous = 0;
var numNamed = 0;
var colorsAnonymous = [];
_.each(authors, function(author)
{
var authorColor = clientVars.colorPalette[author.colorId] || author.colorId;
if (author.name)
{
if (numNamed !== 0) authorsList.append(', ');
$('<span />')
.text(author.name || "unnamed")
.css('background-color', authorColor)
.addClass('author')
.appendTo(authorsList);
numNamed++;
var tr = $('<tr></tr>');
var swatchtd = $('<td></td>');
var swatch = $('<div class="swatch"></div>');
swatch.css('background-color', clientVars.colorPalette[author.colorId]);
swatchtd.append(swatch);
tr.append(swatchtd);
var nametd = $('<td></td>');
nametd.text(author.name || "unnamed");
tr.append(nametd);
$("#authorstable").append(tr);
}
else
{
numAnonymous++;
if(authorColor) colorsAnonymous.push(authorColor);
}
});
if (numAnonymous > 0)
{
var html = "<tr><td colspan=\"2\" style=\"color:#999; padding-left: 10px\">" + (numNamed > 0 ? "...and " : "") + numAnonymous + " unnamed author" + (numAnonymous > 1 ? "s" : "") + "</td></tr>";
$("#authorstable").append($(html));
var anonymousAuthorString = numAnonymous + " unnamed author" + (numAnonymous > 1 ? "s" : "")
if (numNamed !== 0){
authorsList.append(' + ' + anonymousAuthorString);
} else {
authorsList.append(anonymousAuthorString);
}
if(colorsAnonymous.length > 0){
authorsList.append(' (');
_.each(colorsAnonymous, function(color, i){
if( i > 0 ) authorsList.append(' ');
$('<span /> ')
.css('background-color', color)
.addClass('author author-anonymous')
.appendTo(authorsList);
});
authorsList.append(')');
}
}
if (authors.length == 0)
{
$("#authorstable").append($("<tr><td colspan=\"2\" style=\"color:#999; padding-left: 10px\">No Authors</td></tr>"))
authorsList.append("No Authors");
}
fixPadHeight();
}
BroadcastSlider = {
@ -465,7 +491,6 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
{
if (clientVars.supportsSlider)
{
$("#padmain, #rightbars").css('top', "130px");
$("#timeslider").show();
setSliderLength(clientVars.totalRevs);
setSliderPosition(clientVars.revNum);

View File

@ -200,10 +200,11 @@ var padeditbar = (function()
else
{
var nth_child = indexOf(modules, moduleName) + 1;
if (nth_child > 0 && nth_child <= 3) {
if (nth_child > 0 && nth_child <= (modules.length-1)) {
$("#editbar ul#menu_right li:not(:nth-child(" + nth_child + "))").removeClass("selected");
$("#editbar ul#menu_right li:nth-child(" + nth_child + ")").toggleClass("selected");
}
if(modules[modules.length-1] === moduleName) $("#editbar ul#menu_right li").removeClass("selected");
//hide all modules that are not selected and show the selected one
for(var i=0;i<modules.length;i++)
{

View File

@ -98,6 +98,28 @@ if (exports.isClient) {
};
} else {
exports.callInit = function (cb) {
var hooks = require("./hooks");
async.map(
Object.keys(exports.plugins),
function (plugin_name, cb) {
var plugin = exports.plugins[plugin_name];
fs.stat(path.normalize(path.join(plugin.package.path, ".ep_initialized")), function (err, stats) {
if (err) {
async.waterfall([
function (cb) { fs.writeFile(path.normalize(path.join(plugin.package.path, ".ep_initialized")), 'done', cb); },
function (cb) { hooks.aCallAll("init_" + plugin_name, {}, cb); },
cb,
]);
} else {
cb();
}
});
},
function () { cb(); }
);
}
exports.update = function (cb) {
exports.getPackages(function (er, packages) {
var parts = [];
@ -109,11 +131,12 @@ exports.update = function (cb) {
exports.loadPlugin(packages, plugin_name, plugins, parts, cb);
},
function (err) {
exports.plugins = plugins;
if (err) cb(err);
exports.plugins = plugins;
exports.parts = exports.sortParts(parts);
exports.hooks = exports.extractHooks(exports.parts, "hooks");
exports.loaded = true;
cb(err);
exports.loaded = true;
exports.callInit(cb);
}
);
});

View File

@ -1,56 +1,7 @@
<html>
<head>
<title>Plugin manager</title>
<style>
table {
border-collapse: collapse;
}
td, th {
border: 1px solid black;
padding-left: 10px;
padding-right: 10px;
padding-top: 2px;
padding-bottom: 2px;
}
.template {
display: none;
}
.dialog {
display: none;
position: absolute;
left: 50%;
top: 50%;
width: 700px;
height: 500px;
margin-left: -350px;
margin-top: -250px;
border: 3px solid #999999;
background: #eeeeee;
}
.dialog .title {
margin: 0;
padding: 2px;
border-bottom: 3px solid #999999;
font-size: 24px;
line-height: 24px;
height: 24px;
overflow: hidden;
}
.dialog .title .close {
float: right;
}
.dialog .history {
background: #222222;
color: #eeeeee;
position: absolute;
top: 41px;
bottom: 10px;
left: 10px;
right: 10px;
padding: 2px;
overflow: auto;
}
</style>
<link href="../../static/css/admin.css" rel="stylesheet" type="text/css" />
<script src="../../static/js/jquery.js"></script>
<script src="../../socket.io/socket.io.js"></script>
<script>
@ -167,7 +118,7 @@
<td class="name"></td>
<td class="description"></td>
<td class="actions">
<input type="button" value="I" class="do-uninstall">
<input type="button" value="Uninstall" class="do-uninstall">
</td>
</tr>
</tbody>
@ -180,7 +131,7 @@
<h1>Search for plugins to install</h1>
<form>
<input type="text" name="search" value="" id="search-query">
<input type="button" value="S" id="do-search">
<input type="button" value="Search" id="do-search">
</form>
<table>
<thead>
@ -195,7 +146,7 @@
<td class="name"></td>
<td class="description"></td>
<td class="actions">
<input type="button" value="I" class="do-install">
<input type="button" value="Install" class="do-install">
</td>
</tr>
</tbody>

View File

@ -130,6 +130,7 @@
<script src="static/custom/index.js"></script>
<script>
document.domain = document.domain;
function go2Name()
{
var padname = document.getElementById("padname").value;

View File

@ -280,6 +280,7 @@
<script type="text/javascript" src="../javascripts/lib/ep_etherpad-lite/static/js/pad.js?callback=require.define"></script>
<% } %>
<script type="text/javascript">
document.domain = document.domain;
var clientVars = {};
(function () {
<% if (settings.minify) { %>

View File

@ -11,40 +11,14 @@
<style type="text/css" title="dynamicsyntax"></style>
</head>
<body id="padbody" class="timeslider limwidth nonpropad nonprouser">
<body id="padbody" class="timeslider limwidth">
<div id="padpage">
<div id="padtop">
<div class="topbar">
<div class="topbarleft">
<!-- -->
</div>
<div class="topbarright">
<!-- -->
</div>
<div class="topbarcenter">
<a href="/" class="topbarBrand">Etherpad v1.1</a> <a href="http://etherpad.org"
class="EtherpadLink">Etherpad is</a> <a href="../../static/LICENSE" class=
"Licensing">free software</a>
<div class="fullscreen" onclick="$('body').toggleClass('maximized');">
Full screen
</div><a href="javascript:void(0);" onclick=
"$('body').toggleClass('maximized');" class="topbarmaximize" title=
"Toggle maximization"></a>
</div>
<div class="specialkeyarea">
<!-- -->
</div>
</div>
<div id="alertbar">
<div id="servermsg">
<h3>Server Notice<span id="servermsgdate"><!-- --></span>:</h3><a id=
"hidetopmsg" href="javascript:%20void%20pad.hideServerMessage()" name=
"hidetopmsg">hide</a>
<p id="servermsgtext"><!-- --></p>
</div>
</div>
@ -67,104 +41,56 @@
</table>
</div><!-- /docbar -->
</div>
<div id="timeslider-wrapper">
<div id="error" style="display: none">
It looks like you're having connection troubles. <a href=
"/ep/pad/view/test/latest">Reconnect now</a>.
<div id="timeslider-top">
<div id="timeslider-wrapper">
<div id="timeslider" unselectable="on" style="display: none">
<div id="timeslider-left"></div>
<div id="timeslider-right"></div>
<div id="timer"></div>
<div id="timeslider-slider">
<div id="ui-slider-handle"></div>
<div id="ui-slider-bar"></div>
</div>
<div id="playpause_button">
<div id="playpause_button_icon" class=""></div>
</div>
<div id="steppers">
<div class="stepper" id="leftstep"></div>
<div class="stepper" id="rightstep"></div>
</div>
</div>
</div>
<div id="timeslider" unselectable="on" style="display: none">
<div id="timeslider-left"></div>
<div class="timeslider-bar">
<div class="editbarright toolbar" id="editbar">
<ul>
<li onClick="window.padeditbar.toolbarClick('import_export');return false;">
<a id="exportlink" title="Export to different document formats">
<div class="buttonicon buttonicon-import_export"></div>
</a>
</li>
</ul>
<a id="returnbutton">Return to pad</a>
</div>
<div id="timeslider-right"></div>
<div id="timer"></div>
<div id="timeslider-slider">
<div id="ui-slider-handle"></div>
<div id="ui-slider-bar"></div>
</div>
<div id="playpause_button">
<div id="playpause_button_icon" class=""></div>
</div>
<div id="steppers">
<div class="stepper" id="leftstep"></div>
<div class="stepper" id="rightstep"></div>
</div>
<div>
<h1>
<span id="revision_label"></span>
<span id="revision_date"></span>
</h1>
<p>Authors:
<span id="authorsList">
<span>No Authors</span>
</span> </p>
</div>
</div>
</div>
<!--<div id="rightbars" style="top: 95px;">
<div id="rightbar"><a href="/ep/pad/view/c6fg9GM51V/latest" id="viewlatest">Viewing latest content</a><br>
<a thref="/ep/pad/view/c6fg9GM51V/rev.%revision%" href="/ep/pad/view/c6fg9GM51V/rev.0" class="tlink">Link to this version</a>
<br><a thref="/ep/pad/view/ro.fw470Orpi4T/rev.%revision%" href="/ep/pad/view/ro.fw470Orpi4T/rev.0" class="tlink">Link to read-only page</a><br><a href="/c6fg9GM51V">Edit this pad</a>
<h2>Download as</h2>
<img src="../../static/img/may09/html.gif"><a thref="/ep/pad/export/c6fg9GM51V/rev.%revision%?format=html" href="/ep/pad/export/c6fg9GM51V/rev.0?format=html" class="tlink">HTML</a><br>
<img src="../../static/img/may09/txt.gif"><a thref="/ep/pad/export/c6fg9GM51V/rev.%revision%?format=txt" href="/ep/pad/export/c6fg9GM51V/rev.0?format=txt" class="tlink">Plain text</a><br>
<img src="../../static/img/may09/doc.gif"><a thref="/ep/pad/export/c6fg9GM51V/rev.%revision%?format=doc" href="/ep/pad/export/c6fg9GM51V/rev.0?format=doc" class="tlink">Microsoft Word</a><br>
<img src="../../static/img/may09/pdf.gif"><a thref="/ep/pad/export/c6fg9GM51V/rev.%revision%?format=pdf" href="/ep/pad/export/c6fg9GM51V/rev.0?format=pdf" class="tlink">PDF</a>
</div>
<div id="legend">
<h2>Authors</h2>
<table cellspacing="0" cellpadding="0" border="0" id="authorstable"><tbody><tr><td style="color:#999; padding-left: 10px" colspan="2">No Authors</td></tr></tbody></table>
</div>
</div>-->
<div id="padmain">
<div id="padeditor">
<div id="editbar" class="toolbar disabledtoolbar">
<div id="editbarinner" class="toolbarinner">
<div id="editbarleft" class="editbarleft">
<!-- -->
</div>
<div id="editbarright" class="editbarright">
<!-- termporary place holder-->
<ul>
<li onClick="window.padeditbar.toolbarClick('import_export');return false;">
<a id="exportlink" title="Export to different document formats">
<div class="buttonicon buttonicon-import_export"></div>
</a>
</li>
</ul>
<a id = "returnbutton">Return to pad</a>
</div>
<div id="editbarinner" class="editbarinner">
<table cellpadding="0" cellspacing="0" border="0" id="editbartable" class=
"editbartable">
<tr>
<td>
<h1>
<span id="revision_label"></span>
<span id="revision_date"></span>
</h1>
</td>
<td width="100%">&nbsp;</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" border="0" id="editbarsavetable"
class="editbarsavetable">
<tr>
<td></td>
</tr>
</table>
</div>
</div>
</div>
<div id="editorcontainerbox">
<div id="padcontent">
</div>
</div>
</div><!-- /padeditor -->
@ -203,6 +129,7 @@
<script type="text/javascript" src="../../../javascripts/lib/ep_etherpad-lite/static/js/timeslider.js?callback=require.define"></script>
<script type="text/javascript" src="../../../static/custom/timeslider.js"></script>
<script type="text/javascript" >
document.domain = document.domain;
var clientVars = {};
(function () {
require.setRootURI("../../../javascripts/src");