Merge branch 'develop' into timeslider_authors

Conflicts:
	src/static/css/pad.css
	src/templates/timeslider.html
This commit is contained in:
Matthias Bartelmeß 2012-04-05 21:47:59 +02:00
commit 9e042ee942
50 changed files with 1605 additions and 1819 deletions

View file

@ -24,7 +24,7 @@ a img
}
/* menu */
#editbar ul
.toolbar ul
{
position: relative;
list-style: none;
@ -35,19 +35,22 @@ a img
}
#editbar
.toolbar
{
background: #f7f7f7;
background: linear-gradient(#f7f7f7, #f1f1f1 80%);
border-bottom: 1px solid #ccc;
height: 32px;
overflow: hidden;
padding-top: 3px;
width: 100%;
white-space: nowrap;
position: absolute;
left: 0;
right: 0;
height: 32px;
}
#editbar ul li
.toolbar ul li
{
background: #fff;
background: linear-gradient(#fff, #f0f0f0);
@ -62,52 +65,52 @@ a img
width: 18px;
}
#editbar ul li a
.toolbar ul li a
{
text-decoration: none;
color: #ccc;
position: absolute;
}
#editbar ul li a span
.toolbar ul li a span
{
position: relative;
top:-2px
}
#editbar ul li:hover {
.toolbar ul li:hover {
background: #fff;
background: linear-gradient(#f4f4f4, #e4e4e4);
}
#editbar ul li:active {
.toolbar ul li:active {
background: #eee;
background: linear-gradient(#ddd, #fff);
box-shadow: 0 0 8px rgba(0,0,0,.1) inset;
}
#editbar ul li.separator
.toolbar ul li.separator
{
border: inherit;
background: inherit;
visibility:hidden;
width: 0px;
}
#editbar ul li a
.toolbar ul li a
{
display: block;
}
#editbar ul li a img
.toolbar ul li a img
{
padding: 1px;
}
#editbar ul
.toolbar ul
{
float: left;
}
#editbar ul#menu_right
.toolbar ul.menu_right
{
float: right;
}
@ -320,7 +323,7 @@ a#hidetopmsg { position: absolute; right: 5px; bottom: 5px; }
z-index: 10;
}
#editbarsavetable
.toolbarsavetable
{
position:absolute;
top: 6px;
@ -328,7 +331,7 @@ a#hidetopmsg { position: absolute; right: 5px; bottom: 5px; }
height: 24px;
}
#editbarsavetable td, #editbartable td
.toolbarsavetable td, .toolbartable td
{
white-space: nowrap;
}
@ -686,14 +689,15 @@ a#topbarmaximize {
background: url(static/img/maximize_maximized.png);
}
#editbarinner h1 {
.toolbarinner h1 {
line-height: 29px;
font-size: 16px;
padding-left: 6pt;
margin-top: 0;
white-space: nowrap;
}
#editbarinner h1 a {
.toolbarinner h1 a {
font-size: 12px;
}
@ -1032,6 +1036,9 @@ margin-top: 1px;
background-position: 0px -183px;
display: inline-block;
}
.buttonicon-savedRevision {
background-position: 0px -493px
}
#usericon
{
@ -1171,13 +1178,13 @@ input[type=checkbox] {
}
@media screen and (max-width: 600px) {
#editbar ul li {
.toolbar ul li {
padding: 4px 1px;
}
}
@media only screen and (min-device-width: 320px) and (max-device-width: 720px) {
#editbar ul li {
.toolbar ul li {
padding: 4px 3px;
}
#users {
@ -1192,7 +1199,7 @@ input[type=checkbox] {
#editorcontainer {
margin-bottom: 33px;
}
#editbar ul#menu_right {
.toolbar ul.menu_right {
background: #f7f7f7;
background: linear-gradient(#f7f7f7, #f1f1f1 80%);
width: 100%;
@ -1202,7 +1209,7 @@ input[type=checkbox] {
bottom: 0;
border-top: 1px solid #ccc;
}
#editbar ul#menu_right li:last-child {
.toolbar ul.menu_right li:last-child {
height: 24px;
border-radius: 0;
margin-top: 0;
@ -1224,7 +1231,7 @@ input[type=checkbox] {
border-top-right-radius: 0;
border-right: none;
}
#editbar ul li a span {
.toolbar ul li a span {
top: -3px;
}
#usericonback {
@ -1233,10 +1240,10 @@ input[type=checkbox] {
#qrcode {
display: none;
}
#editbar ul#menu_right li:not(:last-child) {
.toolbar ul.menu_right li:not(:last-child) {
display: block;
}
#editbar ul#menu_right > li {
.toolbar ul.menu_right > li {
background: none;
border: none;
margin-top: 4px;
@ -1265,4 +1272,4 @@ input[type=checkbox] {
#online_count {
line-height: 24px;
}
}
}

View file

@ -45,10 +45,10 @@
#leftstar, #rightstar, #leftstep, #rightstep
{background:url(../../static/img/stepper_buttons.png) 0 0 no-repeat; height:21px; overflow:hidden; position:absolute;}
#leftstar {background-position:0 44px; right:34px; top:8px; width:30px;}
#rightstar {background-position:29px 44px; right:5px; top:8px; width:29px;}
#leftstep {background-position:0 22px; right:34px; top:20px; width:30px;}
#rightstep {background-position:29px 22px; right:5px; top:20px; width:29px;}
#leftstar {background-position:0 -44px; right:34px; top:8px; width:30px;}
#rightstar {background-position:-29px -44px; right:5px; top:8px; width:29px;}
#leftstep {background-position:0 -22px; right:34px; top:20px; width:30px;}
#rightstep {background-position:-29px -22px; right:5px; top:20px; width:29px;}
#timeslider .star {
background-image:url(../../static/img/star.png);
@ -75,8 +75,11 @@
#padmain {top:0px !important;}
#editbarright {float:right;}
#returnbutton {color:#222; font-size:16px; line-height:29px; margin-top:0; padding-right:6px;}
#importexport {top:118px;}
#importexport .popup {width:185px;}
#importexport{
top:118px;
width:185px;
}
.timeslider-bar

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Before After
Before After

BIN
src/static/img/star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -1,161 +0,0 @@
<!doctype html>
<html>
<title>Etherpad Lite</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<style>
body {
margin: 0;
height: 100%;
color: #333;
font: 14px helvetica, sans-serif;
background: #ddd;
background: -webkit-radial-gradient(circle,#aaa,#eee 60%) center fixed;
background: -moz-radial-gradient(circle,#aaa,#eee 60%) center fixed;
background: -ms-radial-gradient(circle,#aaa,#eee 60%) center fixed;
background: -o-radial-gradient(circle,#aaa,#eee 60%) center fixed;
border-top: 8px solid rgba(51,51,51,.8);
}
#wrapper {
border-top: 1px solid #999;
margin-top: 160px;
padding: 15px;
background: #eee;
background: -webkit-linear-gradient(#fff,#ccc);
background: -moz-linear-gradient(#fff,#ccc);
background: -ms-linear-gradient(#fff,#ccc);
background: -o-linear-gradient(#fff,#ccc);
opacity: .9;
box-shadow: 0px 1px 8px rgba(0,0,0,0.3);
}
#inner {
width: 300px;
margin: 0 auto;
}
#button {
margin: 0 auto;
border-radius: 3px;
text-align: center;
font: 36px verdana,arial,sans-serif;
color: white;
text-shadow: 0 -1px 0 rgba(0,0,0,.8);
height: 70px;
line-height: 70px;
background: #555;
background: -webkit-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
background: -moz-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
background: -ms-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
background: -o-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
box-shadow: inset 0 1px 3px rgba(0,0,0,0.9);
}
#button:hover {
cursor: pointer;
background: #666;
background: -webkit-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
background: -moz-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
background: -ms-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
background: -o-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
}
#button:active {
box-shadow: inset 0 1px 12px rgba(0,0,0,0.9);
background: #444;
}
#label {
text-align: left;
text-shadow: 0 1px 1px #fff;
margin: 16px auto 0;
}
form {
height: 38px;
background: #fff;
border: 1px solid #bbb;
border-radius: 3px;
position: relative;
}
button, input {
font-weight: bold;
font-size: 15px;
}
input[type="text"] {
border-radius: 3px;
box-sizing: border-box;
-moz-box-sizing: border-box;
padding: 0 45px 0 10px;
*padding: 0; /* IE7 hack */
width: 100%;
height: 100%;
outline: none;
border: none;
position: absolute;
}
button[type="submit"] {
position: absolute;
right: 0;
width: 45px;
height: 38px;
}
@media only screen and (min-device-width: 320px) and (max-device-width: 720px) {
body {
background: #bbb;
background: -webkit-linear-gradient(#aaa,#eee 60%) center fixed;
background: -moz-linear-gradient(#aaa,#eee 60%) center fixed;
background: -ms-linear-gradient(#aaa,#eee 60%) center fixed;
}
#wrapper {
margin-top: 0;
}
#inner {
width: 95%;
}
#label {
text-align: center;
}
}
</style>
<link href="static/custom/index.css" rel="stylesheet">
<div id="wrapper">
<div id="inner">
<div id="button" onclick="go2Random()" class="translate">New Pad</div>
<div id="label" class="translate">or create/open a Pad with the name</div>
<form action="#" onsubmit="go2Name();return false;">
<input type="text" id="padname" autofocus x-webkit-speech>
<button type="submit">OK</button>
</form>
</div>
</div>
<script src="static/custom/index.js"></script>
<script>
function go2Name()
{
var padname = document.getElementById("padname").value;
padname.length > 0 ? window.location = "p/" + padname : alert("Please enter a name")
}
function go2Random()
{
window.location = "p/" + randomPadName();
}
function randomPadName()
{
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var string_length = 10;
var randomstring = '';
for (var i = 0; i < string_length; i++)
{
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum, rnum + 1);
}
return randomstring;
}
// start the custom js
if (typeof customStart == "function") customStart();
</script>
</html>

View file

@ -233,14 +233,16 @@ require.setGlobalKeyPath("require");\n\
iframeHTML.push(doctype);
iframeHTML.push("<html><head>");
iframeHTML.push('<script type="text/javascript" src="../static/js/jquery.js"></script>');
hooks.callAll("aceInitInnerdocbodyHead", {
iframeHTML: iframeHTML
});
// For compatability's sake transform in and out.
for (var i = 0, ii = iframeHTML.length; i < ii; i++) {
iframeHTML[i] = JSON.stringify(iframeHTML[i]);
}
hooks.callAll("aceInitInnerdocbodyHead", {
iframeHTML: iframeHTML
});
for (var i = 0, ii = iframeHTML.length; i < ii; i++) {
iframeHTML[i] = JSON.parse(iframeHTML[i]);
}
@ -262,6 +264,11 @@ require.setGlobalKeyPath("require");\n\
// Inject my plugins into my child.
iframeHTML.push('\
<script type="text/javascript">\
parent_req = require("./pluginfw/parent_require.js");\
parent_req.getRequirementFromParent(require, "ep_etherpad-lite/static/js/pluginfw/hooks");\
parent_req.getRequirementFromParent(require, "ep_etherpad-lite/static/js/pluginfw/plugins");\
parent_req.getRequirementFromParent(require, "./pluginfw/hooks");\
parent_req.getRequirementFromParent(require, "./pluginfw/plugins");\
require.define("/plugins", null);\n\
require.define("/plugins.js", function (require, exports, module) {\
module.exports = require("ep_etherpad-lite/static/js/plugins");\

View file

@ -844,7 +844,7 @@ function Ace2Inner(){
var cmdArgs = Array.prototype.slice.call(arguments, 1);
if (CMDS[cmd])
{
inCallStack(cmd, function()
inCallStackIfNecessary(cmd, function()
{
fastIncorp(9);
CMDS[cmd].apply(CMDS, cmdArgs);
@ -854,7 +854,7 @@ function Ace2Inner(){
function replaceRange(start, end, text)
{
inCallStack('replaceRange', function()
inCallStackIfNecessary('replaceRange', function()
{
fastIncorp(9);
performDocumentReplaceRange(start, end, text);
@ -1155,7 +1155,7 @@ function Ace2Inner(){
return;
}
inCallStack("idleWorkTimer", function()
inCallStackIfNecessary("idleWorkTimer", function()
{
var isTimeUp = newTimeLimit(250);
@ -2043,6 +2043,7 @@ function Ace2Inner(){
return [lineNum, col];
}
}
editorInfo.ace_getLineAndCharForPoint = getLineAndCharForPoint;
function createDomLineEntry(lineString)
{
@ -2328,6 +2329,7 @@ function Ace2Inner(){
var cs = builder.toString();
performDocumentApplyChangeset(cs);
}
editorInfo.ace_performDocumentApplyAttributesToRange = performDocumentApplyAttributesToRange;
function buildKeepToStartOfRange(builder, start)
{
@ -2853,6 +2855,7 @@ function Ace2Inner(){
currentCallStack.selectionAffected = true;
}
}
editorInfo.ace_performSelectionChange = performSelectionChange;
// Change the abstract representation of the document to have a different selection.
// Should not rely on the line representation. Should not affect the DOM.
@ -3280,7 +3283,7 @@ function Ace2Inner(){
function handleClick(evt)
{
inCallStack("handleClick", function()
inCallStackIfNecessary("handleClick", function()
{
idleWorkTimer.atMost(200);
});
@ -3602,7 +3605,7 @@ function Ace2Inner(){
var stopped = false;
inCallStack("handleKeyEvent", function()
inCallStackIfNecessary("handleKeyEvent", function()
{
if (type == "keypress" || (isTypeForSpecialKey && keyCode == 13 /*return*/ ))
@ -4689,7 +4692,7 @@ function Ace2Inner(){
}
// click below the body
inCallStack("handleOuterClick", function()
inCallStackIfNecessary("handleOuterClick", function()
{
// put caret at bottom of doc
fastIncorp(11);
@ -4726,6 +4729,54 @@ function Ace2Inner(){
else $(elem).removeClass(elem, className);
}
function setup()
{
doc = document; // defined as a var in scope outside
inCallStackIfNecessary("setup", function()
{
var body = doc.getElementById("innerdocbody");
root = body; // defined as a var in scope outside
if (browser.mozilla) addClass(root, "mozilla");
if (browser.safari) addClass(root, "safari");
if (browser.msie) addClass(root, "msie");
if (browser.msie)
{
// cache CSS background images
try
{
doc.execCommand("BackgroundImageCache", false, true);
}
catch (e)
{ /* throws an error in some IE 6 but not others! */
}
}
setClassPresence(root, "authorColors", true);
setClassPresence(root, "doesWrap", doesWrap);
initDynamicCSS();
enforceEditability();
// set up dom and rep
while (root.firstChild) root.removeChild(root.firstChild);
var oneEntry = createDomLineEntry("");
doRepLineSplice(0, rep.lines.length(), [oneEntry]);
insertDomLines(null, [oneEntry.domInfo], null);
rep.alines = Changeset.splitAttributionLines(
Changeset.makeAttribution("\n"), "\n");
bindTheEventHandlers();
});
scheduler.setTimeout(function()
{
parent.readyFunc(); // defined in code that sets up the inner iframe
}, 0);
isSetUp = true;
}
function focus()
{
window.focus();

View file

@ -465,7 +465,7 @@ if (!JSON)
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
throw new SyntaxError('JSON.parse: ' + text);
};
}
}());

View file

@ -31,7 +31,6 @@ require('./farbtastic');
require('./excanvas');
JSON = require('./json2');
require('./undo-xpopup');
require('./prefixfree');
var chat = require('./chat').chat;
var getCollabClient = require('./collab_client').getCollabClient;
@ -42,7 +41,7 @@ var padeditbar = require('./pad_editbar').padeditbar;
var padeditor = require('./pad_editor').padeditor;
var padimpexp = require('./pad_impexp').padimpexp;
var padmodals = require('./pad_modals').padmodals;
var padsavedrevs = require('./pad_savedrevs').padsavedrevs;
var padsavedrevs = require('./pad_savedrevs');
var paduserlist = require('./pad_userlist').paduserlist;
var padutils = require('./pad_utils').padutils;
@ -50,6 +49,50 @@ var createCookie = require('./pad_utils').createCookie;
var readCookie = require('./pad_utils').readCookie;
var randomString = require('./pad_utils').randomString;
var hooks = require('./pluginfw/hooks');
function createCookie(name, value, days, path)
{
if (days)
{
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
var expires = "; expires=" + date.toGMTString();
}
else var expires = "";
if(!path)
path = "/";
document.cookie = name + "=" + value + expires + "; path=" + path;
}
function readCookie(name)
{
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++)
{
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
function randomString()
{
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var string_length = 20;
var randomstring = '';
for (var i = 0; i < string_length; i++)
{
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum, rnum + 1);
}
return "t." + randomstring;
}
function getParams()
{
var params = getUrlVars()
@ -457,7 +500,7 @@ var pad = {
guestPolicy: pad.padOptions.guestPolicy
}, this);
padimpexp.init(this);
padsavedrevs.init(clientVars.initialRevisionList, this);
padsavedrevs.init(this);
padeditor.init(postAceInit, pad.padOptions.view || {}, this);
@ -491,6 +534,7 @@ var pad = {
if(padcookie.getPref("showAuthorshipColors") == false){
pad.changeViewOption('showAuthorColors', false);
}
hooks.aCallAll("postAceInit");
}
},
dispose: function()

View file

@ -449,7 +449,7 @@ var paddocbar = (function()
handleResizePage: function()
{
// Side-step circular reference. This should be injected.
var padsavedrevs = require('./pad_savedrevs').padsavedrevs;
var padsavedrevs = require('./pad_savedrevs');
padsavedrevs.handleResizePage();
},
hideLaterIfNoOtherInteraction: function()

View file

@ -22,7 +22,7 @@
var padutils = require('./pad_utils').padutils;
var padeditor = require('./pad_editor').padeditor;
var padsavedrevs = require('./pad_savedrevs').padsavedrevs;
var padsavedrevs = require('./pad_savedrevs');
function indexOf(array, value) {
for (var i = 0, ii = array.length; i < ii; i++) {
@ -131,7 +131,7 @@ var padeditbar = (function()
{
self.toogleDropDown("importexport");
}
else if (cmd == 'save')
else if (cmd == 'savedRevision')
{
padsavedrevs.saveNow();
}

View file

@ -87,8 +87,6 @@ var padeditor = (function()
return defaultValue;
}
self.ace.setProperty("showsauthorcolors", !settings.noColors);
self.ace.setProperty("rtlIsTrue", settings.rtlIsTrue);
var v;
@ -100,6 +98,8 @@ var padeditor = (function()
v = getOption('showAuthorColors', true);
self.ace.setProperty("showsauthorcolors", v);
padutils.setCheckbox($("#options-colorscheck"), v);
// Override from parameters
self.ace.setProperty("showsauthorcolors", !settings.noColors);
v = getOption('useMonospaceFont', false);
self.ace.setProperty("textface", (v ? "monospace" : "Arial, sans-serif"));

View file

@ -1,11 +1,5 @@
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
/**
* Copyright 2009 Google Inc.
* Copyright 2012 Peter 'Pita' Martischka
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,507 +14,13 @@
* limitations under the License.
*/
var padutils = require('./pad_utils').padutils;
var paddocbar = require('./pad_docbar').paddocbar;
var pad;
var padsavedrevs = (function()
{
exports.saveNow = function(){
pad.collabClient.sendMessage({"type": "SAVE_REVISION"});
alert("This revision is now marked as a saved revision");
}
function reversedCopy(L)
{
var L2 = L.slice();
L2.reverse();
return L2;
}
function makeRevisionBox(revisionInfo, rnum)
{
var box = $('<div class="srouterbox">' + '<div class="srinnerbox">' + '<a href="javascript:void(0)" class="srname"><!-- --></a>' + '<div class="sractions"><a class="srview" href="javascript:void(0)" target="_blank">view</a> | <a class="srrestore" href="javascript:void(0)">restore</a></div>' + '<div class="srtime"><!-- --></div>' + '<div class="srauthor"><!-- --></div>' + '<img class="srtwirly" src="static/img/misc/status-ball.gif">' + '</div></div>');
setBoxLabel(box, revisionInfo.label);
setBoxTimestamp(box, revisionInfo.timestamp);
box.find(".srauthor").html("by " + padutils.escapeHtml(revisionInfo.savedBy));
var viewLink = '/ep/pad/view/' + pad.getPadId() + '/' + revisionInfo.id;
box.find(".srview").attr('href', viewLink);
var restoreLink = 'javascript:void(require('+JSON.stringify(module.id)+').padsavedrevs.restoreRevision(' + JSON.stringify(rnum) + ');';
box.find(".srrestore").attr('href', restoreLink);
box.find(".srname").click(function(evt)
{
editRevisionLabel(rnum, box);
});
return box;
}
function setBoxLabel(box, label)
{
box.find(".srname").html(padutils.escapeHtml(label)).attr('title', label);
}
function setBoxTimestamp(box, timestamp)
{
box.find(".srtime").html(padutils.escapeHtml(
padutils.timediff(new Date(timestamp))));
}
function getNthBox(n)
{
return $("#savedrevisions .srouterbox").eq(n);
}
function editRevisionLabel(rnum, box)
{
var input = $('<input type="text" class="srnameedit"/>');
box.find(".srnameedit").remove(); // just in case
var label = box.find(".srname");
input.width(label.width());
input.height(label.height());
input.css('top', label.position().top);
input.css('left', label.position().left);
label.after(input);
label.css('opacity', 0);
function endEdit()
{
input.remove();
label.css('opacity', 1);
}
var rev = currentRevisionList[rnum];
var oldLabel = rev.label;
input.blur(function()
{
var newLabel = input.val();
if (newLabel && newLabel != oldLabel)
{
relabelRevision(rnum, newLabel);
}
endEdit();
});
input.val(rev.label).focus().select();
padutils.bindEnterAndEscape(input, function onEnter()
{
input.blur();
}, function onEscape()
{
input.val('').blur();
});
}
function relabelRevision(rnum, newLabel)
{
var rev = currentRevisionList[rnum];
$.ajax(
{
type: 'post',
url: '/ep/pad/saverevisionlabel',
data: {
userId: pad.getUserId(),
padId: pad.getPadId(),
revId: rev.id,
newLabel: newLabel
},
success: success,
error: error
});
function success(text)
{
var newRevisionList = JSON.parse(text);
self.newRevisionList(newRevisionList);
pad.sendClientMessage(
{
type: 'revisionLabel',
revisionList: reversedCopy(currentRevisionList),
savedBy: pad.getUserName(),
newLabel: newLabel
});
}
function error(e)
{
alert("Oops! There was an error saving that revision label. Please try again later.");
}
}
var currentRevisionList = [];
function setRevisionList(newRevisionList, noAnimation)
{
// deals with changed labels and new added revisions
for (var i = 0; i < currentRevisionList.length; i++)
{
var a = currentRevisionList[i];
var b = newRevisionList[i];
if (b.label != a.label)
{
setBoxLabel(getNthBox(i), b.label);
}
}
for (var j = currentRevisionList.length; j < newRevisionList.length; j++)
{
var newBox = makeRevisionBox(newRevisionList[j], j);
$("#savedrevs-scrollinner").append(newBox);
newBox.css('left', j * REVISION_BOX_WIDTH);
}
var newOnes = (newRevisionList.length > currentRevisionList.length);
currentRevisionList = newRevisionList;
if (newOnes)
{
setDesiredScroll(getMaxScroll());
if (noAnimation)
{
setScroll(desiredScroll);
}
if (!noAnimation)
{
var nameOfLast = currentRevisionList[currentRevisionList.length - 1].label;
displaySavedTip(nameOfLast);
}
}
}
function refreshRevisionList()
{
for (var i = 0; i < currentRevisionList.length; i++)
{
var r = currentRevisionList[i];
var box = getNthBox(i);
setBoxTimestamp(box, r.timestamp);
}
}
var savedTipAnimator = padutils.makeShowHideAnimator(function(state)
{
if (state == -1)
{
$("#revision-notifier").css('opacity', 0).css('display', 'block');
}
else if (state == 0)
{
$("#revision-notifier").css('opacity', 1);
}
else if (state == 1)
{
$("#revision-notifier").css('opacity', 0).css('display', 'none');
}
else if (state < 0)
{
$("#revision-notifier").css('opacity', 1);
}
else if (state > 0)
{
$("#revision-notifier").css('opacity', 1 - state);
}
}, false, 25, 300);
function displaySavedTip(text)
{
$("#revision-notifier .name").html(padutils.escapeHtml(text));
savedTipAnimator.show();
padutils.cancelActions("hide-revision-notifier");
var hideLater = padutils.getCancellableAction("hide-revision-notifier", function()
{
savedTipAnimator.hide();
});
window.setTimeout(hideLater, 3000);
}
var REVISION_BOX_WIDTH = 120;
var curScroll = 0; // distance between left of revisions and right of view
var desiredScroll = 0;
function getScrollWidth()
{
return REVISION_BOX_WIDTH * currentRevisionList.length;
}
function getViewportWidth()
{
return $("#savedrevs-scrollouter").width();
}
function getMinScroll()
{
return Math.min(getViewportWidth(), getScrollWidth());
}
function getMaxScroll()
{
return getScrollWidth();
}
function setScroll(newScroll)
{
curScroll = newScroll;
$("#savedrevs-scrollinner").css('right', newScroll);
updateScrollArrows();
}
function setDesiredScroll(newDesiredScroll, dontUpdate)
{
desiredScroll = Math.min(getMaxScroll(), Math.max(getMinScroll(), newDesiredScroll));
if (!dontUpdate)
{
updateScroll();
}
}
function updateScroll()
{
updateScrollArrows();
scrollAnimator.scheduleAnimation();
}
function updateScrollArrows()
{
$("#savedrevs-scrollleft").toggleClass("disabledscrollleft", desiredScroll <= getMinScroll());
$("#savedrevs-scrollright").toggleClass("disabledscrollright", desiredScroll >= getMaxScroll());
}
var scrollAnimator = padutils.makeAnimationScheduler(function()
{
setDesiredScroll(desiredScroll, true); // re-clamp
if (Math.abs(desiredScroll - curScroll) < 1)
{
setScroll(desiredScroll);
return false;
}
else
{
setScroll(curScroll + (desiredScroll - curScroll) * 0.5);
return true;
}
}, 50, 2);
var isSaving = false;
function setIsSaving(v)
{
isSaving = v;
rerenderButton();
}
function haveReachedRevLimit()
{
var mv = pad.getPrivilege('maxRevisions');
return (!(mv < 0 || mv > currentRevisionList.length));
}
function rerenderButton()
{
if (isSaving || (!pad.isFullyConnected()) || haveReachedRevLimit())
{
$("#savedrevs-savenow").css('opacity', 0.75);
}
else
{
$("#savedrevs-savenow").css('opacity', 1);
}
}
var scrollRepeatTimer = null;
var scrollStartTime = 0;
function setScrollRepeatTimer(dir)
{
clearScrollRepeatTimer();
scrollStartTime = +new Date;
scrollRepeatTimer = window.setTimeout(function f()
{
if (!scrollRepeatTimer)
{
return;
}
self.scroll(dir);
var scrollTime = (+new Date) - scrollStartTime;
var delay = (scrollTime > 2000 ? 50 : 300);
scrollRepeatTimer = window.setTimeout(f, delay);
}, 300);
$(document).bind('mouseup', clearScrollRepeatTimer);
}
function clearScrollRepeatTimer()
{
if (scrollRepeatTimer)
{
window.clearTimeout(scrollRepeatTimer);
scrollRepeatTimer = null;
}
$(document).unbind('mouseup', clearScrollRepeatTimer);
}
var pad = undefined;
var self = {
init: function(initialRevisions, _pad)
{
pad = _pad;
self.newRevisionList(initialRevisions, true);
$("#savedrevs-savenow").click(function()
{
self.saveNow();
});
$("#savedrevs-scrollleft").mousedown(function()
{
self.scroll('left');
setScrollRepeatTimer('left');
});
$("#savedrevs-scrollright").mousedown(function()
{
self.scroll('right');
setScrollRepeatTimer('right');
});
$("#savedrevs-close").click(function()
{
paddocbar.setShownPanel(null);
});
// update "saved n minutes ago" times
window.setInterval(function()
{
refreshRevisionList();
}, 60 * 1000);
},
restoreRevision: function(rnum)
{
var rev = currentRevisionList[rnum];
var warning = ("Restoring this revision will overwrite the current" + " text of the pad. " + "Are you sure you want to continue?");
var hidePanel = paddocbar.hideLaterIfNoOtherInteraction();
var box = getNthBox(rnum);
if (confirm(warning))
{
box.find(".srtwirly").show();
$.ajax(
{
type: 'get',
url: '/ep/pad/getrevisionatext',
data: {
padId: pad.getPadId(),
revId: rev.id
},
success: success,
error: error
});
}
function success(resultJson)
{
untwirl();
var result = JSON.parse(resultJson);
padeditor.restoreRevisionText(result);
window.setTimeout(function()
{
hidePanel();
}, 0);
}
function error(e)
{
untwirl();
alert("Oops! There was an error retreiving the text (revNum= " + rev.revNum + "; padId=" + pad.getPadId());
}
function untwirl()
{
box.find(".srtwirly").hide();
}
},
showReachedLimit: function()
{
alert("Sorry, you do not have privileges to save more than " + pad.getPrivilege('maxRevisions') + " revisions.");
},
newRevisionList: function(lst, noAnimation)
{
// server gives us list with newest first;
// we want chronological order
var L = reversedCopy(lst);
setRevisionList(L, noAnimation);
rerenderButton();
},
saveNow: function()
{
if (isSaving)
{
return;
}
if (!pad.isFullyConnected())
{
return;
}
if (haveReachedRevLimit())
{
self.showReachedLimit();
return;
}
setIsSaving(true);
var savedBy = pad.getUserName() || "unnamed";
pad.callWhenNotCommitting(submitSave);
function submitSave()
{
$.ajax(
{
type: 'post',
url: '/ep/pad/saverevision',
data: {
padId: pad.getPadId(),
savedBy: savedBy,
savedById: pad.getUserId(),
revNum: pad.getCollabRevisionNumber()
},
success: success,
error: error
});
}
function success(text)
{
setIsSaving(false);
var newRevisionList = JSON.parse(text);
self.newRevisionList(newRevisionList);
pad.sendClientMessage(
{
type: 'newRevisionList',
revisionList: newRevisionList,
savedBy: savedBy
});
}
function error(e)
{
setIsSaving(false);
alert("Oops! The server failed to save the revision. Please try again later.");
}
},
handleResizePage: function()
{
updateScrollArrows();
},
handleIsFullyConnected: function(isConnected)
{
rerenderButton();
},
scroll: function(dir)
{
var minScroll = getMinScroll();
var maxScroll = getMaxScroll();
if (dir == 'left')
{
if (desiredScroll > minScroll)
{
var n = Math.floor((desiredScroll - 1 - minScroll) / REVISION_BOX_WIDTH);
setDesiredScroll(Math.max(0, n) * REVISION_BOX_WIDTH + minScroll);
}
}
else if (dir == 'right')
{
if (desiredScroll < maxScroll)
{
var n = Math.floor((maxScroll - desiredScroll - 1) / REVISION_BOX_WIDTH);
setDesiredScroll(maxScroll - Math.max(0, n) * REVISION_BOX_WIDTH);
}
}
}
};
return self;
}());
exports.padsavedrevs = padsavedrevs;
exports.init = function(_pad){
pad = _pad;
}

View file

@ -10,12 +10,18 @@ if (plugins.isClient) {
_ = require("underscore");
}
exports.bubbleExceptions = true
var hookCallWrapper = function (hook, hook_name, args, cb) {
if (cb === undefined) cb = function (x) { return x; };
try {
if (exports.bubbleExceptions) {
return hook.hook_fn(hook_name, args, cb);
} catch (ex) {
console.error([hook_name, hook.part.full_name, ex.stack || ex]);
} else {
try {
return hook.hook_fn(hook_name, args, cb);
} catch (ex) {
console.error([hook_name, hook.part.full_name, ex.stack || ex]);
}
}
}
@ -36,6 +42,7 @@ exports.flatten = function (lst) {
}
exports.callAll = function (hook_name, args) {
if (!args) args = {};
if (plugins.hooks[hook_name] === undefined) return [];
return exports.flatten(_.map(plugins.hooks[hook_name], function (hook) {
return hookCallWrapper(hook, hook_name, args);
@ -43,26 +50,31 @@ exports.callAll = function (hook_name, args) {
}
exports.aCallAll = function (hook_name, args, cb) {
if (plugins.hooks[hook_name] === undefined) cb([]);
if (!args) args = {};
if (!cb) cb = function () {};
if (plugins.hooks[hook_name] === undefined) return cb(null, []);
async.map(
plugins.hooks[hook_name],
function (hook, cb) {
hookCallWrapper(hook, hook_name, args, function (res) { cb(null, res); });
},
function (err, res) {
cb(exports.flatten(res));
cb(null, exports.flatten(res));
}
);
}
exports.callFirst = function (hook_name, args) {
if (!args) args = {};
if (plugins.hooks[hook_name][0] === undefined) return [];
return exports.flatten(hookCallWrapper(plugins.hooks[hook_name][0], hook_name, args));
}
exports.aCallFirst = function (hook_name, args, cb) {
if (plugins.hooks[hook_name][0] === undefined) cb([]);
hookCallWrapper(plugins.hooks[hook_name][0], hook_name, args, function (res) { cb(exports.flatten(res)); });
if (!args) args = {};
if (!cb) cb = function () {};
if (plugins.hooks[hook_name][0] === undefined) return cb(null, []);
hookCallWrapper(plugins.hooks[hook_name][0], hook_name, args, function (res) { cb(null, exports.flatten(res)); });
}
exports.callAllStr = function(hook_name, args, sep, pre, post) {

View file

@ -0,0 +1,76 @@
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins");
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
var npm = require("npm");
var registry = require("npm/lib/utils/npm-registry-client/index.js");
var withNpm = function (npmfn, cb) {
npm.load({}, function (er) {
if (er) return cb({progress:1, error:er});
npm.on("log", function (message) {
cb({progress: 0.5, message:message.msg + ": " + message.pref});
});
npmfn(function (er, data) {
if (er) return cb({progress:1, error:er.code + ": " + er.path});
if (!data) data = {};
data.progress = 1;
data.message = "Done.";
cb(data);
});
});
}
// All these functions call their callback multiple times with
// {progress:[0,1], message:STRING, error:object}. They will call it
// with progress = 1 at least once, and at all times will either
// message or error be present, not both. It can be called multiple
// times for all values of propgress except for 1.
exports.uninstall = function(plugin_name, cb) {
withNpm(
function (cb) {
npm.commands.uninstall([plugin_name], function (er) {
if (er) return cb(er);
hooks.aCallAll("pluginUninstall", {plugin_name: plugin_name}, function (er, data) {
if (er) return cb(er);
plugins.update(cb);
});
});
},
cb
);
};
exports.install = function(plugin_name, cb) {
withNpm(
function (cb) {
npm.commands.install([plugin_name], function (er) {
if (er) return cb(er);
hooks.aCallAll("pluginInstall", {plugin_name: plugin_name}, function (er, data) {
if (er) return cb(er);
plugins.update(cb);
});
});
},
cb
);
};
exports.search = function(pattern, cb) {
withNpm(
function (cb) {
registry.get(
"/-/all", null, 600, false, true,
function (er, data) {
if (er) return cb(er);
var res = {};
for (key in data) {
if (key.indexOf(plugins.prefix) == 0 && key.indexOf(pattern) != -1)
res[key] = data[key];
}
cb(null, {results:res});
}
);
},
cb
);
};

View file

@ -0,0 +1,37 @@
/**
* This module allows passing require modules instances to
* embedded iframes in a page.
* For example, if a page has the "plugins" module initialized,
* it is important to use exactly the same "plugins" instance
* inside iframes as well. Otherwise, plugins cannot save any
* state.
*/
/**
* Instructs the require object that when a reqModuleName module
* needs to be loaded, that it iterates through the parents of the
* current window until it finds one who can execute "require"
* statements and asks it to perform require on reqModuleName.
*
* @params requireDefObj Require object which supports define
* statements. This object is accessible after loading require-kernel.
* @params reqModuleName Module name e.g. (ep_etherpad-lite/static/js/plugins)
*/
exports.getRequirementFromParent = function(requireDefObj, reqModuleName) {
requireDefObj.define(reqModuleName, function(require, exports, module) {
var t = parent;
var max = 0; // make sure I don't go up more than 10 times
while (typeof(t) != "undefined") {
max++;
if (max==10)
break;
if (typeof(t.require) != "undefined") {
module.exports = t.require(reqModuleName);
return;
}
t = t.parent;
}
});
}

View file

@ -4,7 +4,7 @@ var _;
if (!exports.isClient) {
var npm = require("npm/lib/npm.js");
var readInstalled = require("npm/lib/utils/read-installed.js");
var readInstalled = require("./read-installed.js");
var relativize = require("npm/lib/utils/relativize.js");
var readJson = require("npm/lib/utils/read-json.js");
var path = require("path");
@ -14,10 +14,9 @@ if (!exports.isClient) {
var util = require("util");
_ = require("underscore");
}else{
var $, jQuery
var $, jQuery;
$ = jQuery = require("ep_etherpad-lite/static/js/rjquery").$;
_ = require("ep_etherpad-lite/static/js/underscore");
}
exports.prefix = 'ep_';
@ -31,15 +30,15 @@ exports.ensure = function (cb) {
exports.update(cb);
else
cb();
}
};
exports.formatPlugins = function () {
return _.keys(exports.plugins).join(", ");
}
};
exports.formatParts = function () {
return _.map(exports.parts, function (part) { return part.full_name; }).join("\n");
}
};
exports.formatHooks = function () {
var res = [];
@ -49,33 +48,39 @@ exports.formatHooks = function () {
});
});
return res.join("\n");
}
};
exports.loadFn = function (path) {
exports.loadFn = function (path, hookName) {
var x = path.split(":");
var fn = require(x[0]);
_.each(x[1].split("."), function (name) {
var functionName = x[1] ? x[1] : hookName;
_.each(functionName.split("."), function (name) {
fn = fn[name];
});
return fn;
}
};
exports.extractHooks = function (parts, hook_set_name) {
var hooks = {};
_.each(parts,function (part) {
_.chain(part[hook_set_name] || {}).keys().each(function (hook_name) {
_.chain(part[hook_set_name] || {})
.keys()
.each(function (hook_name) {
if (hooks[hook_name] === undefined) hooks[hook_name] = [];
var hook_fn_name = part[hook_set_name][hook_name];
var hook_fn = exports.loadFn(part[hook_set_name][hook_name]);
var hook_fn = exports.loadFn(hook_fn_name, hook_name);
if (hook_fn) {
hooks[hook_name].push({"hook_name": hook_name, "hook_fn": hook_fn, "hook_fn_name": hook_fn_name, "part": part});
} else {
console.error("Unable to load hook function for " + part.full_name + " for hook " + hook_name + ": " + part.hooks[hook_name]);
console.error("Unable to load hook function for " + part.full_name + " for hook " + hook_name + ": " + part.hooks[hook_name]);
}
});
});
return hooks;
}
};
if (exports.isClient) {
@ -90,7 +95,7 @@ if (exports.isClient) {
console.error("Failed to load plugin-definitions: " + err);
cb();
});
}
};
} else {
exports.update = function (cb) {
@ -104,15 +109,15 @@ exports.update = function (cb) {
exports.loadPlugin(packages, plugin_name, plugins, parts, cb);
},
function (err) {
exports.plugins = plugins;
exports.plugins = plugins;
exports.parts = exports.sortParts(parts);
exports.hooks = exports.extractHooks(exports.parts, "hooks");
exports.loaded = true;
exports.loaded = true;
cb(err);
}
);
});
}
};
exports.getPackages = function (cb) {
// Load list of installed NPM packages, flatten it to a list, and filter out only packages with names that
@ -122,44 +127,50 @@ exports.getPackages = function (cb) {
var packages = {};
function flatten(deps) {
_.chain(deps).keys().each(function (name) {
if (name.indexOf(exports.prefix) == 0) {
packages[name] = deps[name];
}
if (deps[name].dependencies !== undefined)
flatten(deps[name].dependencies);
delete deps[name].dependencies;
if (name.indexOf(exports.prefix) === 0) {
packages[name] = _.clone(deps[name]);
// Delete anything that creates loops so that the plugin
// list can be sent as JSON to the web client
delete packages[name].dependencies;
delete packages[name].parent;
}
if (deps[name].dependencies !== undefined) flatten(deps[name].dependencies);
});
}
flatten([data]);
var tmp = {};
tmp[data.name] = data;
flatten(tmp);
cb(null, packages);
});
}
};
exports.loadPlugin = function (packages, plugin_name, plugins, parts, cb) {
exports.loadPlugin = function (packages, plugin_name, plugins, parts, cb) {
var plugin_path = path.resolve(packages[plugin_name].path, "ep.json");
fs.readFile(
plugin_path,
function (er, data) {
if (er) {
console.error("Unable to load plugin definition file " + plugin_path);
console.error("Unable to load plugin definition file " + plugin_path);
return cb();
}
try {
var plugin = JSON.parse(data);
plugin.package = packages[plugin_name];
plugins[plugin_name] = plugin;
_.each(plugin.parts, function (part) {
part.plugin = plugin_name;
part.full_name = plugin_name + "/" + part.name;
parts[part.full_name] = part;
});
plugin['package'] = packages[plugin_name];
plugins[plugin_name] = plugin;
_.each(plugin.parts, function (part) {
part.plugin = plugin_name;
part.full_name = plugin_name + "/" + part.name;
parts[part.full_name] = part;
});
} catch (ex) {
console.error("Unable to parse plugin definition file " + plugin_path + ": " + ex.toString());
console.error("Unable to parse plugin definition file " + plugin_path + ": " + ex.toString());
}
cb();
}
);
}
};
exports.partsToParentChildList = function (parts) {
var res = [];
@ -175,7 +186,7 @@ exports.partsToParentChildList = function (parts) {
}
});
return res;
}
};
// Used only in Node, so no need for _

View file

@ -0,0 +1,324 @@
// A copy of npm/lib/utils/read-installed.js
// that is hacked to not cache everything :)
// Walk through the file-system "database" of installed
// packages, and create a data object related to the
// installed versions of each package.
/*
This will traverse through all node_modules folders,
resolving the dependencies object to the object corresponding to
the package that meets that dep, or just the version/range if
unmet.
Assuming that you had this folder structure:
/path/to
+-- package.json { name = "root" }
`-- node_modules
+-- foo {bar, baz, asdf}
| +-- node_modules
| +-- bar { baz }
| `-- baz
`-- asdf
where "foo" depends on bar, baz, and asdf, bar depends on baz,
and bar and baz are bundled with foo, whereas "asdf" is at
the higher level (sibling to foo), you'd get this object structure:
{ <package.json data>
, path: "/path/to"
, parent: null
, dependencies:
{ foo :
{ version: "1.2.3"
, path: "/path/to/node_modules/foo"
, parent: <Circular: root>
, dependencies:
{ bar:
{ parent: <Circular: foo>
, path: "/path/to/node_modules/foo/node_modules/bar"
, version: "2.3.4"
, dependencies: { baz: <Circular: foo.dependencies.baz> }
}
, baz: { ... }
, asdf: <Circular: asdf>
}
}
, asdf: { ... }
}
}
Unmet deps are left as strings.
Extraneous deps are marked with extraneous:true
deps that don't meet a requirement are marked with invalid:true
to READ(packagefolder, parentobj, name, reqver)
obj = read package.json
installed = ./node_modules/*
if parentobj is null, and no package.json
obj = {dependencies:{<installed>:"*"}}
deps = Object.keys(obj.dependencies)
obj.path = packagefolder
obj.parent = parentobj
if name, && obj.name !== name, obj.invalid = true
if reqver, && obj.version !satisfies reqver, obj.invalid = true
if !reqver && parentobj, obj.extraneous = true
for each folder in installed
obj.dependencies[folder] = READ(packagefolder+node_modules+folder,
obj, folder, obj.dependencies[folder])
# walk tree to find unmet deps
for each dep in obj.dependencies not in installed
r = obj.parent
while r
if r.dependencies[dep]
if r.dependencies[dep].verion !satisfies obj.dependencies[dep]
WARN
r.dependencies[dep].invalid = true
obj.dependencies[dep] = r.dependencies[dep]
r = null
else r = r.parent
return obj
TODO:
1. Find unmet deps in parent directories, searching as node does up
as far as the left-most node_modules folder.
2. Ignore anything in node_modules that isn't a package folder.
*/
var npm = require("npm/lib/npm.js")
, fs = require("graceful-fs")
, path = require("path")
, asyncMap = require("slide").asyncMap
, semver = require("semver")
, readJson = require("npm/lib/utils/read-json.js")
, log = require("npm/lib/utils/log.js")
module.exports = readInstalled
function readInstalled (folder, cb) {
/* This is where we clear the cache, these three lines are all the
* new code there is */
rpSeen = {};
riSeen = [];
var fuSeen = [];
var d = npm.config.get("depth")
readInstalled_(folder, null, null, null, 0, d, function (er, obj) {
if (er) return cb(er)
// now obj has all the installed things, where they're installed
// figure out the inheritance links, now that the object is built.
resolveInheritance(obj)
cb(null, obj)
})
}
var rpSeen = {}
function readInstalled_ (folder, parent, name, reqver, depth, maxDepth, cb) {
//console.error(folder, name)
var installed
, obj
, real
, link
fs.readdir(path.resolve(folder, "node_modules"), function (er, i) {
// error indicates that nothing is installed here
if (er) i = []
installed = i.filter(function (f) { return f.charAt(0) !== "." })
next()
})
readJson(path.resolve(folder, "package.json"), function (er, data) {
obj = copy(data)
if (!parent) {
obj = obj || true
er = null
}
return next(er)
})
fs.lstat(folder, function (er, st) {
if (er) {
if (!parent) real = true
return next(er)
}
fs.realpath(folder, function (er, rp) {
//console.error("realpath(%j) = %j", folder, rp)
real = rp
if (st.isSymbolicLink()) link = rp
next(er)
})
})
var errState = null
, called = false
function next (er) {
if (errState) return
if (er) {
errState = er
return cb(null, [])
}
//console.error('next', installed, obj && typeof obj, name, real)
if (!installed || !obj || !real || called) return
called = true
if (rpSeen[real]) return cb(null, rpSeen[real])
if (obj === true) {
obj = {dependencies:{}, path:folder}
installed.forEach(function (i) { obj.dependencies[i] = "*" })
}
if (name && obj.name !== name) obj.invalid = true
obj.realName = name || obj.name
obj.dependencies = obj.dependencies || {}
// "foo":"http://blah" is always presumed valid
if (reqver
&& semver.validRange(reqver)
&& !semver.satisfies(obj.version, reqver)) {
obj.invalid = true
}
if (parent
&& !(name in parent.dependencies)
&& !(name in (parent.devDependencies || {}))) {
obj.extraneous = true
}
obj.path = obj.path || folder
obj.realPath = real
obj.link = link
if (parent && !obj.link) obj.parent = parent
rpSeen[real] = obj
obj.depth = depth
if (depth >= maxDepth) return cb(null, obj)
asyncMap(installed, function (pkg, cb) {
var rv = obj.dependencies[pkg]
if (!rv && obj.devDependencies) rv = obj.devDependencies[pkg]
readInstalled_( path.resolve(folder, "node_modules/"+pkg)
, obj, pkg, obj.dependencies[pkg], depth + 1, maxDepth
, cb )
}, function (er, installedData) {
if (er) return cb(er)
installedData.forEach(function (dep) {
obj.dependencies[dep.realName] = dep
})
// any strings here are unmet things. however, if it's
// optional, then that's fine, so just delete it.
if (obj.optionalDependencies) {
Object.keys(obj.optionalDependencies).forEach(function (dep) {
if (typeof obj.dependencies[dep] === "string") {
delete obj.dependencies[dep]
}
})
}
return cb(null, obj)
})
}
}
// starting from a root object, call findUnmet on each layer of children
var riSeen = []
function resolveInheritance (obj) {
if (typeof obj !== "object") return
if (riSeen.indexOf(obj) !== -1) return
riSeen.push(obj)
if (typeof obj.dependencies !== "object") {
obj.dependencies = {}
}
Object.keys(obj.dependencies).forEach(function (dep) {
findUnmet(obj.dependencies[dep])
})
Object.keys(obj.dependencies).forEach(function (dep) {
resolveInheritance(obj.dependencies[dep])
})
}
// find unmet deps by walking up the tree object.
// No I/O
var fuSeen = []
function findUnmet (obj) {
if (fuSeen.indexOf(obj) !== -1) return
fuSeen.push(obj)
//console.error("find unmet", obj.name, obj.parent && obj.parent.name)
var deps = obj.dependencies = obj.dependencies || {}
//console.error(deps)
Object.keys(deps)
.filter(function (d) { return typeof deps[d] === "string" })
.forEach(function (d) {
//console.error("find unmet", obj.name, d, deps[d])
var r = obj.parent
, found = null
while (r && !found && typeof deps[d] === "string") {
// if r is a valid choice, then use that.
found = r.dependencies[d]
if (!found && r.realName === d) found = r
if (!found) {
r = r.link ? null : r.parent
continue
}
if ( typeof deps[d] === "string"
&& !semver.satisfies(found.version, deps[d])) {
// the bad thing will happen
log.warn(obj.path + " requires "+d+"@'"+deps[d]
+"' but will load\n"
+found.path+",\nwhich is version "+found.version
,"unmet dependency")
found.invalid = true
}
deps[d] = found
}
})
log.verbose([obj._id], "returning")
return obj
}
function copy (obj) {
if (!obj || typeof obj !== 'object') return obj
if (Array.isArray(obj)) return obj.map(copy)
var o = {}
for (var i in obj) o[i] = copy(obj[i])
return o
}
if (module === require.main) {
var util = require("util")
console.error("testing")
var called = 0
readInstalled(process.cwd(), function (er, map) {
console.error(called ++)
if (er) return console.error(er.stack || er.message)
cleanup(map)
console.error(util.inspect(map, true, 10, true))
})
var seen = []
function cleanup (map) {
if (seen.indexOf(map) !== -1) return
seen.push(map)
for (var i in map) switch (i) {
case "_id":
case "path":
case "extraneous": case "invalid":
case "dependencies": case "name":
continue
default: delete map[i]
}
var dep = map.dependencies
// delete map.dependencies
if (dep) {
// map.dependencies = dep
for (var i in dep) if (typeof dep[i] === "object") {
cleanup(dep[i])
}
}
return map
}
}

View file

@ -1,419 +0,0 @@
/**
* StyleFix 1.0.2
* @author Lea Verou
* MIT license
*/
(function(){
if(!window.addEventListener) {
return;
}
var self = window.StyleFix = {
link: function(link) {
try {
// Ignore stylesheets with data-noprefix attribute as well as alternate stylesheets
if(link.rel !== 'stylesheet' || link.hasAttribute('data-noprefix')) {
return;
}
}
catch(e) {
return;
}
var url = link.href || link.getAttribute('data-href'),
base = url.replace(/[^\/]+$/, ''),
parent = link.parentNode,
xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
var css = xhr.responseText;
if(css && link.parentNode) {
css = self.fix(css, true, link);
// Convert relative URLs to absolute, if needed
if(base) {
css = css.replace(/url\(('?|"?)(.+?)\1\)/gi, function($0, quote, url) {
if(!/^([a-z]{3,10}:|\/|#)/i.test(url)) { // If url not absolute & not a hash
// May contain sequences like /../ and /./ but those DO work
return 'url("' + base + url + '")';
}
return $0;
});
// behavior URLs shoudnt be converted (Issue #19)
css = css.replace(RegExp('\\b(behavior:\\s*?url\\(\'?"?)' + base, 'gi'), '$1');
}
var style = document.createElement('style');
style.textContent = css;
style.media = link.media;
style.disabled = link.disabled;
style.setAttribute('data-href', link.getAttribute('href'));
parent.insertBefore(style, link);
parent.removeChild(link);
}
}
};
xhr.send(null);
link.setAttribute('data-inprogress', '');
},
styleElement: function(style) {
var disabled = style.disabled;
style.textContent = self.fix(style.textContent, true, style);
style.disabled = disabled;
},
styleAttribute: function(element) {
var css = element.getAttribute('style');
css = self.fix(css, false, element);
element.setAttribute('style', css);
},
process: function() {
// Linked stylesheets
$('link[rel="stylesheet"]:not([data-inprogress])').forEach(StyleFix.link);
// Inline stylesheets
$('style').forEach(StyleFix.styleElement);
// Inline styles
$('[style]').forEach(StyleFix.styleAttribute);
},
register: function(fixer, index) {
(self.fixers = self.fixers || [])
.splice(index === undefined? self.fixers.length : index, 0, fixer);
},
fix: function(css, raw) {
for(var i=0; i<self.fixers.length; i++) {
css = self.fixers[i](css, raw) || css;
}
return css;
},
camelCase: function(str) {
return str.replace(/-([a-z])/g, function($0, $1) { return $1.toUpperCase(); }).replace('-','');
},
deCamelCase: function(str) {
return str.replace(/[A-Z]/g, function($0) { return '-' + $0.toLowerCase() });
}
};
/**************************************
* Process styles
**************************************/
(function(){
setTimeout(function(){
$('link[rel="stylesheet"]').forEach(StyleFix.link);
}, 10);
document.addEventListener('DOMContentLoaded', StyleFix.process, false);
})();
function $(expr, con) {
return [].slice.call((con || document).querySelectorAll(expr));
}
})();
/**
* PrefixFree 1.0.4
* @author Lea Verou
* MIT license
*/
(function(root, undefined){
if(!window.StyleFix || !window.getComputedStyle) {
return;
}
var self = window.PrefixFree = {
prefixCSS: function(css, raw) {
var prefix = self.prefix;
function fix(what, before, after, replacement) {
what = self[what];
if(what.length) {
var regex = RegExp(before + '(' + what.join('|') + ')' + after, 'gi');
css = css.replace(regex, replacement);
}
}
fix('functions', '(\\s|:|,)', '\\s*\\(', '$1' + prefix + '$2(');
fix('keywords', '(\\s|:)', '(\\s|;|\\}|$)', '$1' + prefix + '$2$3');
fix('properties', '(^|\\{|\\s|;)', '\\s*:', '$1' + prefix + '$2:');
// Prefix properties *inside* values (issue #8)
if (self.properties.length) {
var regex = RegExp('\\b(' + self.properties.join('|') + ')(?!:)', 'gi');
fix('valueProperties', '\\b', ':(.+?);', function($0) {
return $0.replace(regex, prefix + "$1")
});
}
if(raw) {
fix('selectors', '', '\\b', self.prefixSelector);
fix('atrules', '@', '\\b', '@' + prefix + '$1');
}
// Fix double prefixing
css = css.replace(RegExp('-' + prefix, 'g'), '-');
return css;
},
// Warning: prefixXXX functions prefix no matter what, even if the XXX is supported prefix-less
prefixSelector: function(selector) {
return selector.replace(/^:{1,2}/, function($0) { return $0 + self.prefix })
},
prefixProperty: function(property, camelCase) {
var prefixed = self.prefix + property;
return camelCase? StyleFix.camelCase(prefixed) : prefixed;
}
};
/**************************************
* Properties
**************************************/
(function() {
var prefixes = {},
properties = [],
shorthands = {},
style = getComputedStyle(document.documentElement, null),
dummy = document.createElement('div').style;
// Why are we doing this instead of iterating over properties in a .style object? Cause Webkit won't iterate over those.
var iterate = function(property) {
if(property.charAt(0) === '-') {
properties.push(property);
var parts = property.split('-'),
prefix = parts[1];
// Count prefix uses
prefixes[prefix] = ++prefixes[prefix] || 1;
// This helps determining shorthands
while(parts.length > 3) {
parts.pop();
var shorthand = parts.join('-');
if(supported(shorthand) && properties.indexOf(shorthand) === -1) {
properties.push(shorthand);
}
}
}
},
supported = function(property) {
return StyleFix.camelCase(property) in dummy;
}
// Some browsers have numerical indices for the properties, some don't
if(style.length > 0) {
for(var i=0; i<style.length; i++) {
iterate(style[i])
}
}
else {
for(var property in style) {
iterate(StyleFix.deCamelCase(property));
}
}
// Find most frequently used prefix
var highest = {uses:0};
for(var prefix in prefixes) {
var uses = prefixes[prefix];
if(highest.uses < uses) {
highest = {prefix: prefix, uses: uses};
}
}
self.prefix = '-' + highest.prefix + '-';
self.Prefix = StyleFix.camelCase(self.prefix);
self.properties = [];
// Get properties ONLY supported with a prefix
for(var i=0; i<properties.length; i++) {
var property = properties[i];
if(property.indexOf(self.prefix) === 0) { // we might have multiple prefixes, like Opera
var unprefixed = property.slice(self.prefix.length);
if(!supported(unprefixed)) {
self.properties.push(unprefixed);
}
}
}
// IE fix
if(self.Prefix == 'Ms'
&& !('transform' in dummy)
&& !('MsTransform' in dummy)
&& ('msTransform' in dummy)) {
self.properties.push('transform', 'transform-origin');
}
self.properties.sort();
})();
/**************************************
* Values
**************************************/
(function() {
// Values that might need prefixing
var functions = {
'linear-gradient': {
property: 'backgroundImage',
params: 'red, teal'
},
'calc': {
property: 'width',
params: '1px + 5%'
},
'element': {
property: 'backgroundImage',
params: '#foo'
}
};
functions['repeating-linear-gradient'] =
functions['repeating-radial-gradient'] =
functions['radial-gradient'] =
functions['linear-gradient'];
var keywords = {
'initial': 'color',
'zoom-in': 'cursor',
'zoom-out': 'cursor',
'box': 'display',
'flexbox': 'display',
'inline-flexbox': 'display'
};
self.functions = [];
self.keywords = [];
var style = document.createElement('div').style;
function supported(value, property) {
style[property] = '';
style[property] = value;
return !!style[property];
}
for (var func in functions) {
var test = functions[func],
property = test.property,
value = func + '(' + test.params + ')';
if (!supported(value, property)
&& supported(self.prefix + value, property)) {
// It's supported, but with a prefix
self.functions.push(func);
}
}
for (var keyword in keywords) {
var property = keywords[keyword];
if (!supported(keyword, property)
&& supported(self.prefix + keyword, property)) {
// It's supported, but with a prefix
self.keywords.push(keyword);
}
}
})();
/**************************************
* Selectors and @-rules
**************************************/
(function() {
var
selectors = {
':read-only': null,
':read-write': null,
':any-link': null,
'::selection': null
},
atrules = {
'keyframes': 'name',
'viewport': null,
'document': 'regexp(".")'
};
self.selectors = [];
self.atrules = [];
var style = root.appendChild(document.createElement('style'));
function supported(selector) {
style.textContent = selector + '{}'; // Safari 4 has issues with style.innerHTML
return !!style.sheet.cssRules.length;
}
for(var selector in selectors) {
var test = selector + (selectors[selector]? '(' + selectors[selector] + ')' : '');
if(!supported(test) && supported(self.prefixSelector(test))) {
self.selectors.push(selector);
}
}
for(var atrule in atrules) {
var test = atrule + ' ' + (atrules[atrule] || '');
if(!supported('@' + test) && supported('@' + self.prefix + test)) {
self.atrules.push(atrule);
}
}
root.removeChild(style);
})();
// Properties that accept properties as their value
self.valueProperties = [
'transition',
'transition-property'
]
// Add class for current prefix
root.className += ' ' + self.prefix;
StyleFix.register(self.prefixCSS);
})(document.documentElement);

View file

@ -1,284 +0,0 @@
<!doctype html>
<html>
<title>Etherpad Lite</title>
<meta charset="utf-8">
<meta name="robots" content="noindex, nofollow">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<link href="../static/css/pad.css" rel="stylesheet">
<link href="../static/custom/pad.css" rel="stylesheet">
<style title="dynamicsyntax"></style>
<!-- head and body had been removed intentionally -->
<div id="editbar">
<ul id="menu_left">
<li id="bold" onClick="window.pad&amp;&amp;pad.editbarClick('bold');return false">
<a class="buttonicon buttonicon-bold" title="Bold (ctrl-B)"></a>
</li>
<li id="italic" onClick="window.pad&amp;&amp;pad.editbarClick('italic'); return false;">
<a class="buttonicon buttonicon-italic" title="Italics (ctrl-I)"></a>
</li>
<li id="underline" onClick="window.pad&amp;&amp;pad.editbarClick('underline');return false;" >
<a class="buttonicon buttonicon-underline" title="Underline (ctrl-U)"></a>
</li>
<li id="strikethrough" onClick="window.pad&amp;&amp;pad.editbarClick('strikethrough');return false;">
<a class="buttonicon buttonicon-strikethrough" title="Strikethrough"></a>
</li>
<li class="separator"></li>
<li id="oderedlist" onClick="window.pad&amp;&amp;pad.editbarClick('insertorderedlist');return false;">
<a class="buttonicon buttonicon-insertorderedlist" title="Toggle Ordered List"></a>
</li>
<li id="unoderedlist" onClick="window.pad&amp;&amp;pad.editbarClick('insertunorderedlist');return false;">
<a class="buttonicon buttonicon-insertunorderedlist" title="Toggle Bullet List"></a>
</li>
<li id="indent" onClick="window.pad&amp;&amp;pad.editbarClick('indent');return false;">
<a class="buttonicon buttonicon-indent" title="Indent"></a>
</li>
<li id="outdent" onClick="window.pad&amp;&amp;pad.editbarClick('outdent');return false;">
<a class="buttonicon buttonicon-outdent" title="Unindent"></a>
</li>
<li class="separator"></li>
<li id="undo" onClick="window.pad&amp;&amp;pad.editbarClick('undo');return false;">
<a class="buttonicon buttonicon-undo" title="Undo (ctrl-Z)"></a>
</li>
<li id="redo" onClick="window.pad&amp;&amp;pad.editbarClick('redo');return false;">
<a class="buttonicon buttonicon-redo" title="Redo (ctrl-Y)"></a>
</li>
<li class="separator"></li>
<li id="clearAuthorship" onClick="window.pad&amp;&amp;pad.editbarClick('clearauthorship');return false;">
<a class="buttonicon buttonicon-clearauthorship" title="Clear Authorship Colors"></a>
</li>
</ul>
<ul id="menu_right">
<li id="settingslink" onClick="window.pad&amp;&amp;pad.editbarClick('settings');return false;">
<a class="buttonicon buttonicon-settings" id="settingslink" title="Settings of this pad"></a>
</li>
<li id="importexportlink" onClick="window.pad&amp;&amp;pad.editbarClick('import_export');return false;">
<a class="buttonicon buttonicon-import_export" id="exportlink" title="Import/Export from/to different document formats"></a>
</li>
<li id="embedlink" onClick="window.pad&amp;&amp;pad.editbarClick('embed');return false;" >
<a class="buttonicon buttonicon-embed" id="embedlink" title="Share and Embed this pad"></a>
</li>
<li class="separator"></li>
<li id="timesliderlink" onClick="document.location = document.location.pathname+ '/timeslider'">
<a class="buttonicon buttonicon-history" title="Show the history of this pad"></a>
</li>
<li id="usericon" onClick="window.pad&amp;&amp;pad.editbarClick('showusers');return false;" title="Show connected users">
<span class="buttonicon buttonicon-showusers" id="usericonback"></span>
<span id="online_count">1</span>
</li>
</ul>
</div>
<div id="users">
<div id="connectionstatus"></div>
<div id="myuser">
<div id="mycolorpicker">
<div id="colorpicker"></div>
<button id="mycolorpickersave">Save</button>
<button id="mycolorpickercancel">Cancel</button>
<span id="mycolorpickerpreview" class="myswatchboxhoverable"></span>
</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"></div>
</div>
<div id="userlistbuttonarea"></div>
</div>
<div id="editorcontainerbox">
<div id="editorcontainer"></div>
<div id="editorloadingbox">Loading...</div>
</div>
<div id="settingsmenu" class="popup">
<h1>Pad settings</h1>
<div class="column">
<h2>My view</h2>
<p>
<input type="checkbox" id="options-stickychat" onClick="chat.stickToScreen();">
<label for="options-stickychat">Chat always on screen</label>
</p>
<p>
<input type="checkbox" id="options-colorscheck">
<label for="options-colorscheck">Authorship colors</label>
</p>
<p>
<input type="checkbox" id="options-linenoscheck" checked>
<label for="options-linenoscheck">Line numbers</label>
</p>
<p>
Font type:
<select id="viewfontmenu">
<option value="normal">Normal</option>
<option value="monospace">Monospaced</option>
</select>
</p>
</div>
<div class="column">
<h2>Global view</h2>
<p>Currently nothing.</p>
<p class="note">These options affect everyone viewing this pad.</p>
</div>
</div>
<div id="importexport" class="popup">
<div class="column">
<h2>Import from text file, HTML, PDF, Word, ODT or RTF</h2><br>
<form id="importform" method="post" action="" target="importiframe" enctype="multipart/form-data">
<div class="importformdiv" id="importformfilediv">
<input type="file" name="file" size="15" id="importfileinput">
<div class="importmessage" id="importmessagefail"></div>
</div>
<div id="import"></div>
<div class="importmessage" id="importmessagesuccess">Successful!</div>
<div class="importformdiv" id="importformsubmitdiv">
<input type="hidden" name="padId" value="blpmaXT35R">
<span class="nowrap">
<input type="submit" name="submit" value="Import Now" disabled="disabled" id="importsubmitinput">
<img alt="" id="importstatusball" src="../static/img/loading.gif" align="top">
<img alt="" id="importarrow" src="../static/img/leftarrow.png" align="top">
</span>
</div>
</form>
</div>
<div class="column">
<h2>Export current pad as</h2>
<a id="exporthtmla" target="_blank" class="exportlink"><div class="exporttype" id="exporthtml">HTML</div></a>
<a id="exportplaina" target="_blank" class="exportlink"><div class="exporttype" id="exportplain">Plain text</div></a>
<a id="exportworda" target="_blank" class="exportlink"><div class="exporttype" id="exportword">Microsoft Word</div></a>
<a id="exportpdfa" target="_blank" class="exportlink"><div class="exporttype" id="exportpdf">PDF</div></a>
<a id="exportopena" target="_blank" class="exportlink"><div class="exporttype" id="exportopen">OpenDocument</div></a>
<a id="exportdokuwikia" target="_blank" class="exportlink"><div class="exporttype" id="exportdokuwiki">DokuWiki text</div></a>
<a id="exportwordlea" target="_blank" onClick="padimpexp.export2Wordle();return false;" class="exportlink"><div class="exporttype" id="exportwordle">Wordle</div></a>
</div>
</div>
<div id="embed" class="popup">
<div id="embedreadonly" class="right">
<input type="checkbox" id="readonlyinput" onClick="padeditbar.setEmbedLinks();">
<label for="readonlyinput">Read only</label>
</div>
<h1>Share this pad</h1>
<div id="linkcode">
<h2>Link</h2>
<input id="linkinput" type="text" value="">
</div>
<br>
<div id="embedcode">
<h2>Embed URL</h2>
<input id="embedinput" type="text" value="">
</div>
<br>
<div id="qrcode">
<h2>QR code</h2>
<div id="qr_center"><img id="embedreadonlyqr"></div>
</div>
</div>
<div id="chatthrob"></div>
<div id="chaticon" title="Open the chat for this pad" onclick="chat.show();return false;">
<span id="chatlabel">Chat</span>
<span class="buttonicon buttonicon-chat"></span>
<span id="chatcounter">0</span>
</div>
<div id="chatbox">
<div id="titlebar"><span id ="titlelabel">Chat</span><a id="titlecross" onClick="chat.hide();return false;">-&nbsp;</a></div>
<div id="chattext" class="authorColors"></div>
<div id="chatinputbox">
<form>
<input id="chatinput" type="text" maxlength="140">
</form>
</div>
</div>
<div id="focusprotector">&nbsp;</div>
<div id="modaloverlay">
<div id="modaloverlay-inner"></div>
</div>
<div id="mainmodals">
<div id="connectionbox" class="modaldialog">
<div id="connectionboxinner" class="modaldialog-inner">
<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 lite 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 lite 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 lite 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="disconnected_deleted">
<p>This pad was deleted.</p>
</div>
<div id="reconnect_advise">
<p>If this continues to happen, please let us know</p>
</div>
<div id="reconnect_form">
<button id="forcereconnect">Reconnect Now</button>
</div>
</div>
</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>
</div>
</div>
<script type="text/javascript" src="../static/js/require-kernel.js"></script>
<script type="text/javascript" src="../static/js/jquery.js"></script>
<script type="text/javascript" src="../socket.io/socket.io.js"></script>
<script type="text/javascript" src="../javascripts/lib/ep_etherpad-lite/static/js/pad.js?callback=require.define"></script>
<script type="text/javascript">
var clientVars = {};
(function () {
require.setRootURI("../javascripts/src");
require.setLibraryURI("../javascripts/lib");
require.setGlobalKeyPath("require");
var plugins = require('ep_etherpad-lite/static/js/pluginfw/plugins');
plugins.update(function () {
require('ep_etherpad-lite/static/js/pad').init();
});
/* TODO: These globals shouldn't exist. */
pad = require('ep_etherpad-lite/static/js/pad').pad;
chat = require('ep_etherpad-lite/static/js/chat').chat;
padeditbar = require('ep_etherpad-lite/static/js/pad_editbar').padeditbar;
padimpexp = require('ep_etherpad-lite/static/js/pad_impexp').padimpexp;
}());
</script>
</html>

View file

@ -1,150 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="robots" content="noindex, nofollow">
<title>Etherpad Lite Timeslider</title>
<link rel="stylesheet" href="../../static/css/pad.css">
<link rel="stylesheet" href="../../static/css/timeslider.css">
<link rel="stylesheet" href="../../static/custom/timeslider.css">
<style type="text/css" title="dynamicsyntax"></style>
</head>
<body id="padbody" class="timeslider limwidth">
<div id="padpage">
<div id="padtop">
<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>
<div id="navigation"></div>
<div id="docbar" class="menu docbar">
<table border="0" cellpadding="0" cellspacing="0" width="100%" id="docbartable"
class="docbartable">
<tr>
<td><img src="../../static/img/roundcorner_left.gif" /></td>
<td id="docbarpadtitle" class="docbarpadtitle" title=
"Public Pad: Public Pad"><span>Public Pad</span></td>
<td width="100%">&nbsp;</td>
<td><img src="../../static/img/roundcorner_right.gif" /></td>
</tr>
</table>
</div><!-- /docbar -->
</div>
<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 class="timeslider-bar">
<div class="editbarright" 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>
<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="padmain">
<div id="padeditor">
<div id="editorcontainerbox">
<div id="padcontent">
</div>
</div>
</div><!-- /padeditor -->
</div><!-- /padmain -->
</div><!-- /padpage -->
<div id="modaloverlay">
<div id="modaloverlay-inner">
<!-- -->
</div>
</div>
<div id="mainmodals"></div>
<!-- export code -->
<div id="importexport">
<div id="export" class="popup">
Export current version as:
<a id="exporthtmla" target="_blank" class="exportlink"><div class="exporttype" id="exporthtml">HTML</div></a>
<a id="exportplaina" target="_blank" class="exportlink"><div class="exporttype" id="exportplain">Plain text</div></a>
<a id="exportworda" target="_blank" class="exportlink"><div class="exporttype" id="exportword">Microsoft Word</div></a>
<a id="exportpdfa" target="_blank" class="exportlink"><div class="exporttype" id="exportpdf">PDF</div></a>
<a id="exportopena" target="_blank" class="exportlink"><div class="exporttype" id="exportopen">OpenDocument</div></a>
<a id="exportdokuwikia" target="_blank" class="exportlink"><div class="exporttype" id="exportdokuwiki">DokuWiki text</div></a>
<a id="exportwordlea" target="_blank" onClick="padimpexp.export2Wordle();return false;" class="exportlink"><div class="exporttype" id="exportwordle">Wordle</div></a>
<form id="wordlepost" name="wall" action="http://wordle.net/advanced" method="POST" style="margin-left:0px;">
<div id="hidetext" style=""><textarea id="text" name="text" id="text" style="display:none;">Coming soon!</textarea></div>
</form>
</div>
</div>
<script type="text/javascript" src="../../../static/js/require-kernel.js"></script>
<script type="text/javascript" src="../../../static/js/jquery.js"></script>
<script type="text/javascript" src="../../../socket.io/socket.io.js"></script>
<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" >
var clientVars = {};
(function () {
require.setRootURI("../../../javascripts/src");
require.setLibraryURI("../../../javascripts/lib");
require.setGlobalKeyPath("require");
var plugins = require('ep_etherpad-lite/static/js/pluginfw/plugins');
plugins.update(function () {
require('ep_etherpad-lite/static/js/timeslider').init();
/* TODO: These globals shouldn't exist. */
padeditbar = require('ep_etherpad-lite/static/js/pad_editbar').padeditbar;
padimpexp = require('ep_etherpad-lite/static/js/pad_impexp').padimpexp;
});
})();
</script>
</body>
</html>