Merge branch 'develop' of https://github.com/Pita/etherpad-lite into develop

This commit is contained in:
johnyma22 2012-04-09 13:49:06 +01:00
commit baf215fae6
22 changed files with 581 additions and 387 deletions

1
.gitignore vendored
View file

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

View file

@ -24,6 +24,7 @@ var async = require("async");
var padManager = require("../db/PadManager"); var padManager = require("../db/PadManager");
var Changeset = require("ep_etherpad-lite/static/js/Changeset"); var Changeset = require("ep_etherpad-lite/static/js/Changeset");
var AttributePool = require("ep_etherpad-lite/static/js/AttributePool"); var AttributePool = require("ep_etherpad-lite/static/js/AttributePool");
var AttributeManager = require("ep_etherpad-lite/static/js/AttributeManager");
var authorManager = require("../db/AuthorManager"); var authorManager = require("../db/AuthorManager");
var readOnlyManager = require("../db/ReadOnlyManager"); var readOnlyManager = require("../db/ReadOnlyManager");
var settings = require('../utils/Settings'); var settings = require('../utils/Settings');
@ -31,6 +32,7 @@ var securityManager = require("../db/SecurityManager");
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins.js"); var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins.js");
var log4js = require('log4js'); var log4js = require('log4js');
var messageLogger = log4js.getLogger("message"); var messageLogger = log4js.getLogger("message");
var _ = require('underscore');
/** /**
* A associative array that translates a session to a pad * A associative array that translates a session to a pad
@ -591,8 +593,12 @@ function _correctMarkersInPad(atext, apool) {
var offset = 0; var offset = 0;
while (iter.hasNext()) { while (iter.hasNext()) {
var op = iter.next(); var op = iter.next();
var listValue = Changeset.opAttributeValue(op, 'list', apool);
if (listValue) { var hasMarker = _.find(AttributeManager.lineAttributes, function(attribute){
return Changeset.opAttributeValue(op, attribute, apool);
}) !== undefined;
if (hasMarker) {
for(var i=0;i<op.chars;i++) { for(var i=0;i<op.chars;i++) {
if (offset > 0 && text.charAt(offset-1) != '\n') { if (offset > 0 && text.charAt(offset-1) != '\n') {
badMarkers.push(offset); badMarkers.push(offset);

View file

@ -4,13 +4,14 @@ var formidable = require('formidable');
var apiHandler = require('../../handler/APIHandler'); var apiHandler = require('../../handler/APIHandler');
//This is for making an api call, collecting all post information and passing it to the apiHandler //This is for making an api call, collecting all post information and passing it to the apiHandler
exports.apiCaller = function(req, res, fields) { var apiCaller = function(req, res, fields) {
res.header("Content-Type", "application/json; charset=utf-8"); res.header("Content-Type", "application/json; charset=utf-8");
apiLogger.info("REQUEST, " + req.params.func + ", " + JSON.stringify(fields)); apiLogger.info("REQUEST, " + req.params.func + ", " + JSON.stringify(fields));
//wrap the send function so we can log the response //wrap the send function so we can log the response
res._send = res.send; //note: res._send seems to be already in use, so better use a "unique" name
res._____send = res.send;
res.send = function (response) { res.send = function (response) {
response = JSON.stringify(response); response = JSON.stringify(response);
apiLogger.info("RESPONSE, " + req.params.func + ", " + response); apiLogger.info("RESPONSE, " + req.params.func + ", " + response);
@ -19,13 +20,14 @@ exports.apiCaller = function(req, res, fields) {
if(req.query.jsonp) if(req.query.jsonp)
response = req.query.jsonp + "(" + response + ")"; response = req.query.jsonp + "(" + response + ")";
res._send(response); res._____send(response);
} }
//call the api handler //call the api handler
apiHandler.handle(req.params.func, fields, req, res); apiHandler.handle(req.params.func, fields, req, res);
} }
exports.apiCaller = apiCaller;
exports.expressCreateServer = function (hook_name, args, cb) { exports.expressCreateServer = function (hook_name, args, cb) {
//This is a api GET call, collect all post informations and pass it to the apiHandler //This is a api GET call, collect all post informations and pass it to the apiHandler
@ -55,4 +57,4 @@ exports.expressCreateServer = function (hook_name, args, cb) {
res.end("OK"); res.end("OK");
}); });
}); });
} }

View file

@ -56,6 +56,7 @@
, "rjquery.js" , "rjquery.js"
, "AttributePool.js" , "AttributePool.js"
, "Changeset.js" , "Changeset.js"
, "ChangesetUtils.js"
, "security.js" , "security.js"
, "skiplist.js" , "skiplist.js"
, "virtual_lines.js" , "virtual_lines.js"
@ -66,6 +67,7 @@
, "changesettracker.js" , "changesettracker.js"
, "linestylefilter.js" , "linestylefilter.js"
, "domline.js" , "domline.js"
, "AttributeManager.js"
, "ace2_inner.js" , "ace2_inner.js"
] ]
} }

View file

@ -42,9 +42,8 @@ a img
border-bottom: 1px solid #ccc; border-bottom: 1px solid #ccc;
overflow: hidden; overflow: hidden;
padding-top: 3px; padding-top: 3px;
position: absolute; width: 100%;
left: 0; white-space: nowrap;
right: 0;
height: 32px; height: 32px;
} }
@ -177,7 +176,6 @@ a#backtoprosite { padding-left: 20px; left: 6px;
background: url(static/img/protop.gif) no-repeat -5px -6px; } background: url(static/img/protop.gif) no-repeat -5px -6px; }
#accountnav { right: 30px; color: #fff; } #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; #specialkeyarea { top: 5px; left: 250px; color: yellow; font-weight: bold;
font-size: 1.5em; position: absolute; } font-size: 1.5em; position: absolute; }
@ -606,8 +604,6 @@ table#otheruserstable { display: none; }
text-align: left; text-align: left;
} }
.nonprouser #sharebox-stripe { display: none; }
.sharebox-url { .sharebox-url {
width: 440px; height: 18px; width: 440px; height: 18px;
text-align: left; 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;} #padcontent {font-size:12px; padding:10px;}
@ -67,8 +70,9 @@
width:122px; width:122px;
} }
.topbarcenter, #docbar {display:none;} .topbarcenter, #docbar {display:none;}
#padmain {top:30px;} #padmain {top:0px !important;}
#editbarright {float:right;} #editbarright {float:right;}
#returnbutton {color:#222; font-size:16px; line-height:29px; margin-top:0; padding-right:6px;} #returnbutton {color:#222; font-size:16px; line-height:29px; margin-top:0; padding-right:6px;}
#importexport .popup {width:185px;} #importexport .popup {width:185px;}
@ -77,6 +81,53 @@
width:185px; 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 */ /* lists */
.list-bullet2, .list-indent2, .list-number2 {margin-left:3em;} .list-bullet2, .list-indent2, .list-number2 {margin-left:3em;}
.list-bullet3, .list-indent3, .list-number3 {margin-left:4.5em;} .list-bullet3, .list-indent3, .list-number3 {margin-left:4.5em;}

View file

@ -0,0 +1,164 @@
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.
A document representation contains
- an array `alines` containing 1 attributes string for each line
- an Attribute pool `apool`
- a SkipList `lines` containing the text lines of the document.
*/
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.lineAttributes = lineAttributes;
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){
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];
if (aline)
{
var opIter = Changeset.opIterator(aline);
if (opIter.hasNext())
{
return Changeset.opAttributeValue(opIter.next(), attributeName, this.rep.apool) || '';
}
}
return '';
},
/*
Sets 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 set, e.g. list
@param attributeValue: an optional parameter to pass to the attribute (e.g. indention level)
*/
setAttributeOnLine: function(lineNum, attributeName, attributeValue){
var loc = [0,0];
var builder = Changeset.builder(this.rep.lines.totalWidth());
var hasMarker = this.lineHasMarker(lineNum);
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
if(hasMarker){
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 1]), [
[attributeName, attributeValue]
], this.rep.apool);
}else{
// add a line marker
builder.insert('*', [
['author', this.author],
['insertorder', 'first'],
[lineMarkerAttribute, '1'],
[attributeName, attributeValue]
], this.rep.apool);
}
return this.applyChangeset(builder);
},
/*
Removes a specified attribute on a line
@param lineNum: the number of the affected line
@param attributeKey: the name of the attribute to remove, e.g. list
*/
removeAttributeOnLine: function(lineNum, attributeName, attributeValue){
var loc = [0,0];
var builder = Changeset.builder(this.rep.lines.totalWidth());
var hasMarker = this.lineHasMarker(lineNum);
if(hasMarker){
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
ChangesetUtils.buildRemoveRange(this.rep, builder, loc, (loc = [lineNum, 1]));
}
return this.applyChangeset(builder);
},
/*
Sets 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 set, e.g. list
@param attributeValue: an optional parameter to pass to the attribute (e.g. indention level)
*/
toggleAttributeOnLine: function(lineNum, attributeName, attributeValue) {
return this.getAttributeOnLine(attributeName) ?
this.removeAttributeOnLine(lineNum, attributeName) :
this.setAttributeOnLine(lineNum, attributeName, attributeValue);
}
});
module.exports = AttributeManager;

View file

@ -22,6 +22,12 @@
* limitations under the License. * 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 () { var AttributePool = function () {
this.numToAttrib = {}; // e.g. {0: ['foo','bar']} this.numToAttrib = {}; // e.g. {0: ['foo','bar']}
this.attribToNum = {}; // e.g. {'foo,bar': 0} this.attribToNum = {}; // e.g. {'foo,bar': 0}

View file

@ -0,0 +1,60 @@
/**
* This module contains several helper Functions to build Changesets
* based on a SkipList
*/
/**
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
exports.buildRemoveRange = function(rep, builder, start, end)
{
var startLineOffset = rep.lines.offsetOfIndex(start[0]);
var endLineOffset = rep.lines.offsetOfIndex(end[0]);
if (end[0] > start[0])
{
builder.remove(endLineOffset - startLineOffset - start[1], end[0] - start[0]);
builder.remove(end[1]);
}
else
{
builder.remove(end[1] - start[1]);
}
}
exports.buildKeepRange = function(rep, builder, start, end, attribs, pool)
{
var startLineOffset = rep.lines.offsetOfIndex(start[0]);
var endLineOffset = rep.lines.offsetOfIndex(end[0]);
if (end[0] > start[0])
{
builder.keep(endLineOffset - startLineOffset - start[1], end[0] - start[0], attribs, pool);
builder.keep(end[1], 0, attribs, pool);
}
else
{
builder.keep(end[1] - start[1], 0, attribs, pool);
}
}
exports.buildKeepToStartOfRange = function(rep, builder, start)
{
var startLineOffset = rep.lines.offsetOfIndex(start[0]);
builder.keep(startLineOffset, start[0]);
builder.keep(start[1]);
}

View file

@ -256,6 +256,10 @@ require.setGlobalKeyPath("require");\n\
$$INCLUDE_CSS("../static/css/iframe_editor.css"); $$INCLUDE_CSS("../static/css/iframe_editor.css");
$$INCLUDE_CSS("../static/css/pad.css"); $$INCLUDE_CSS("../static/css/pad.css");
$$INCLUDE_CSS("../static/custom/pad.css"); $$INCLUDE_CSS("../static/custom/pad.css");
var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path });
includedCSS = includedCSS.concat(additionalCSS);
pushStyleTagsFor(iframeHTML, includedCSS); pushStyleTagsFor(iframeHTML, includedCSS);
var includedJS = []; var includedJS = [];
@ -294,6 +298,11 @@ require.setGlobalKeyPath("require");\n\
$$INCLUDE_CSS("../static/css/iframe_editor.css"); $$INCLUDE_CSS("../static/css/iframe_editor.css");
$$INCLUDE_CSS("../static/css/pad.css"); $$INCLUDE_CSS("../static/css/pad.css");
$$INCLUDE_CSS("../static/custom/pad.css"); $$INCLUDE_CSS("../static/custom/pad.css");
var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path });
includedCSS = includedCSS.concat(additionalCSS);
pushStyleTagsFor(outerHTML, includedCSS); pushStyleTagsFor(outerHTML, includedCSS);
// bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly // bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly

View file

@ -35,6 +35,8 @@ var isNodeText = Ace2Common.isNodeText,
binarySearchInfinite = Ace2Common.binarySearchInfinite, binarySearchInfinite = Ace2Common.binarySearchInfinite,
htmlPrettyEscape = Ace2Common.htmlPrettyEscape, htmlPrettyEscape = Ace2Common.htmlPrettyEscape,
noop = Ace2Common.noop; noop = Ace2Common.noop;
var hooks = require('./pluginfw/hooks');
function Ace2Inner(){ function Ace2Inner(){
@ -45,10 +47,12 @@ function Ace2Inner(){
var domline = require('./domline').domline; var domline = require('./domline').domline;
var AttribPool = require('./AttributePool'); var AttribPool = require('./AttributePool');
var Changeset = require('./Changeset'); var Changeset = require('./Changeset');
var ChangesetUtils = require('./ChangesetUtils');
var linestylefilter = require('./linestylefilter').linestylefilter; var linestylefilter = require('./linestylefilter').linestylefilter;
var SkipList = require('./skiplist'); var SkipList = require('./skiplist');
var undoModule = require('./undomodule').undoModule; var undoModule = require('./undomodule').undoModule;
var makeVirtualLineView = require('./virtual_lines').makeVirtualLineView; var makeVirtualLineView = require('./virtual_lines').makeVirtualLineView;
var AttributeManager = require('./AttributeManager');
var DEBUG = false; //$$ build script replaces the string "var DEBUG=true;//$$" with "var DEBUG=false;" var DEBUG = false; //$$ build script replaces the string "var DEBUG=true;//$$" with "var DEBUG=false;"
// changed to false // changed to false
@ -78,14 +82,11 @@ function Ace2Inner(){
var overlaysdiv = lineMetricsDiv.nextSibling; var overlaysdiv = lineMetricsDiv.nextSibling;
initLineNumbers(); initLineNumbers();
var outsideKeyDown = function(evt) var outsideKeyDown = noop;
{};
var outsideKeyPress = function(evt) var outsideKeyPress = function(){return true;};
{
return true; var outsideNotifyDirty = noop;
};
var outsideNotifyDirty = function()
{};
// selFocusAtStart -- determines whether the selection extends "backwards", so that the focus // selFocusAtStart -- determines whether the selection extends "backwards", so that the focus
// point (controlled with the arrow keys) is at the beginning; not supported in IE, though // point (controlled with the arrow keys) is at the beginning; not supported in IE, though
@ -100,6 +101,7 @@ function Ace2Inner(){
alines: [], alines: [],
apool: new AttribPool() apool: new AttribPool()
}; };
// lines, alltext, alines, and DOM are set up in setup() // lines, alltext, alines, and DOM are set up in setup()
if (undoModule.enabled) if (undoModule.enabled)
{ {
@ -119,6 +121,7 @@ function Ace2Inner(){
iframePadRight = 0; iframePadRight = 0;
var console = (DEBUG && window.console); var console = (DEBUG && window.console);
var documentAttributeManager;
if (!window.console) if (!window.console)
{ {
@ -155,6 +158,7 @@ function Ace2Inner(){
var textFace = 'monospace'; var textFace = 'monospace';
var textSize = 12; var textSize = 12;
function textLineHeight() function textLineHeight()
{ {
@ -929,7 +933,10 @@ function Ace2Inner(){
}, },
grayedout: setClassPresenceNamed(outerWin.document.body, "grayedout"), grayedout: setClassPresenceNamed(outerWin.document.body, "grayedout"),
dmesg: function(){ dmesg = window.dmesg = value; }, dmesg: function(){ dmesg = window.dmesg = value; },
userauthor: function(value){ thisAuthor = String(value); }, userauthor: function(value){
thisAuthor = String(value);
documentAttributeManager.author = thisAuthor;
},
styled: setStyled, styled: setStyled,
textface: setTextFace, textface: setTextFace,
textsize: setTextSize, textsize: setTextSize,
@ -1864,55 +1871,6 @@ function Ace2Inner(){
} }
} }
function setupMozillaCaretHack(lineNum)
{
// This is really ugly, but by god, it works!
// Fixes annoying Firefox caret artifact (observed in 2.0.0.12
// and unfixed in Firefox 2 as of now) where mutating the DOM
// and then moving the caret to the beginning of a line causes
// an image of the caret to be XORed at the top of the iframe.
// The previous solution involved remembering to set the selection
// later, in response to the next event in the queue, which was hugely
// annoying.
// This solution: add a space character (0x20) to the beginning of the line.
// After setting the selection, remove the space.
var lineNode = rep.lines.atIndex(lineNum).lineNode;
var fc = lineNode.firstChild;
while (isBlockElement(fc) && fc.firstChild)
{
fc = fc.firstChild;
}
var textNode;
if (isNodeText(fc))
{
fc.nodeValue = " " + fc.nodeValue;
textNode = fc;
}
else
{
textNode = doc.createTextNode(" ");
fc.parentNode.insertBefore(textNode, fc);
}
markNodeClean(lineNode);
return {
unhack: function()
{
if (textNode.nodeValue == " ")
{
textNode.parentNode.removeChild(textNode);
}
else
{
textNode.nodeValue = textNode.nodeValue.substring(1);
}
markNodeClean(lineNode);
}
};
}
function getPointForLineAndChar(lineAndChar) function getPointForLineAndChar(lineAndChar)
{ {
var line = lineAndChar[0]; var line = lineAndChar[0];
@ -2247,6 +2205,9 @@ function Ace2Inner(){
} }
/*
Converts the position of a char (index in String) into a [row, col] tuple
*/
function lineAndColumnFromChar(x) function lineAndColumnFromChar(x)
{ {
var lineEntry = rep.lines.atOffset(x); var lineEntry = rep.lines.atOffset(x);
@ -2301,8 +2262,8 @@ function Ace2Inner(){
// CCCC\n // CCCC\n
// end[0]: <CCC end[1] CCC>-------\n // end[0]: <CCC end[1] CCC>-------\n
var builder = Changeset.builder(rep.lines.totalWidth()); var builder = Changeset.builder(rep.lines.totalWidth());
buildKeepToStartOfRange(builder, start); ChangesetUtils.buildKeepToStartOfRange(rep, builder, start);
buildRemoveRange(builder, start, end); ChangesetUtils.buildRemoveRange(rep, builder, start, end);
builder.insert(newText, [ builder.insert(newText, [
['author', thisAuthor] ['author', thisAuthor]
], rep.apool); ], rep.apool);
@ -2313,69 +2274,17 @@ function Ace2Inner(){
function performDocumentApplyAttributesToCharRange(start, end, attribs) function performDocumentApplyAttributesToCharRange(start, end, attribs)
{ {
if (end >= rep.alltext.length) end = Math.min(end, rep.alltext.length - 1);
{ documentAttributeManager.setAttributesOnRange(lineAndColumnFromChar(start), lineAndColumnFromChar(end), attribs);
end = rep.alltext.length - 1;
}
performDocumentApplyAttributesToRange(lineAndColumnFromChar(start), lineAndColumnFromChar(end), attribs);
} }
editorInfo.ace_performDocumentApplyAttributesToCharRange = performDocumentApplyAttributesToCharRange; editorInfo.ace_performDocumentApplyAttributesToCharRange = performDocumentApplyAttributesToCharRange;
function performDocumentApplyAttributesToRange(start, end, attribs)
{
var builder = Changeset.builder(rep.lines.totalWidth());
buildKeepToStartOfRange(builder, start);
buildKeepRange(builder, start, end, attribs, rep.apool);
var cs = builder.toString();
performDocumentApplyChangeset(cs);
}
editorInfo.ace_performDocumentApplyAttributesToRange = performDocumentApplyAttributesToRange;
function buildKeepToStartOfRange(builder, start)
{
var startLineOffset = rep.lines.offsetOfIndex(start[0]);
builder.keep(startLineOffset, start[0]);
builder.keep(start[1]);
}
function buildRemoveRange(builder, start, end)
{
var startLineOffset = rep.lines.offsetOfIndex(start[0]);
var endLineOffset = rep.lines.offsetOfIndex(end[0]);
if (end[0] > start[0])
{
builder.remove(endLineOffset - startLineOffset - start[1], end[0] - start[0]);
builder.remove(end[1]);
}
else
{
builder.remove(end[1] - start[1]);
}
}
function buildKeepRange(builder, start, end, attribs, pool)
{
var startLineOffset = rep.lines.offsetOfIndex(start[0]);
var endLineOffset = rep.lines.offsetOfIndex(end[0]);
if (end[0] > start[0])
{
builder.keep(endLineOffset - startLineOffset - start[1], end[0] - start[0], attribs, pool);
builder.keep(end[1], 0, attribs, pool);
}
else
{
builder.keep(end[1] - start[1], 0, attribs, pool);
}
}
function setAttributeOnSelection(attributeName, attributeValue) function setAttributeOnSelection(attributeName, attributeValue)
{ {
if (!(rep.selStart && rep.selEnd)) return; if (!(rep.selStart && rep.selEnd)) return;
performDocumentApplyAttributesToRange(rep.selStart, rep.selEnd, [ documentAttributeManager.setAttributesOnRange(rep.selStart, rep.selEnd, [
[attributeName, attributeValue] [attributeName, attributeValue]
]); ]);
} }
@ -2436,13 +2345,13 @@ function Ace2Inner(){
if (selectionAllHasIt) if (selectionAllHasIt)
{ {
performDocumentApplyAttributesToRange(rep.selStart, rep.selEnd, [ documentAttributeManager.setAttributesOnRange(rep.selStart, rep.selEnd, [
[attributeName, ''] [attributeName, '']
]); ]);
} }
else else
{ {
performDocumentApplyAttributesToRange(rep.selStart, rep.selEnd, [ documentAttributeManager.setAttributesOnRange(rep.selStart, rep.selEnd, [
[attributeName, 'true'] [attributeName, 'true']
]); ]);
} }
@ -2964,6 +2873,10 @@ function Ace2Inner(){
"ul": 1 "ul": 1
}; };
_.each(hooks.callAll('aceRegisterBlockElements'), function(element){
_blockElems[element] = 1;
});
function isBlockElement(n) function isBlockElement(n)
{ {
return !!_blockElems[(n.tagName || "").toLowerCase()]; return !!_blockElems[(n.tagName || "").toLowerCase()];
@ -3328,6 +3241,7 @@ function Ace2Inner(){
{ {
return; return;
} }
var lineNum = rep.selStart[0]; var lineNum = rep.selStart[0];
var listType = getLineListType(lineNum); var listType = getLineListType(lineNum);
@ -3399,11 +3313,9 @@ function Ace2Inner(){
} }
} }
if (mods.length > 0) _.each(mods, function(mod){
{ setLineListType(mod[0], mod[1]);
setLineListTypes(mods); });
}
return true; return true;
} }
editorInfo.ace_doIndentOutdent = doIndentOutdent; editorInfo.ace_doIndentOutdent = doIndentOutdent;
@ -3453,6 +3365,9 @@ function Ace2Inner(){
var thisLineListType = getLineListType(theLine); var thisLineListType = getLineListType(theLine);
var prevLineEntry = (theLine > 0 && rep.lines.atIndex(theLine - 1)); var prevLineEntry = (theLine > 0 && rep.lines.atIndex(theLine - 1));
var prevLineBlank = (prevLineEntry && prevLineEntry.text.length == prevLineEntry.lineMarker); var prevLineBlank = (prevLineEntry && prevLineEntry.text.length == prevLineEntry.lineMarker);
var thisLineHasMarker = documentAttributeManager.lineHasMarker(theLine);
if (thisLineListType) if (thisLineListType)
{ {
// this line is a list // this line is a list
@ -3466,6 +3381,9 @@ function Ace2Inner(){
// delistify // delistify
performDocumentReplaceRange([theLine, 0], [theLine, lineEntry.lineMarker], ''); performDocumentReplaceRange([theLine, 0], [theLine, lineEntry.lineMarker], '');
} }
}else if (thisLineHasMarker && prevLineEntry){
// If the line has any attributes assigned, remove them by removing the marker '*'
performDocumentReplaceRange([theLine -1 , prevLineEntry.text.length], [theLine, lineEntry.lineMarker], '');
} }
else if (theLine > 0) else if (theLine > 0)
{ {
@ -3818,26 +3736,17 @@ function Ace2Inner(){
return; return;
} }
var mozillaCaretHack = (false && browser.mozilla && selStart && selEnd && selStart[0] == selEnd[0] && selStart[1] == rep.lines.atIndex(selStart[0]).lineMarker && selEnd[1] == rep.lines.atIndex(selEnd[0]).lineMarker && setupMozillaCaretHack(selStart[0]));
var selection = {}; var selection = {};
var ss = [selStart[0], selStart[1]]; var ss = [selStart[0], selStart[1]];
if (mozillaCaretHack) ss[1] += 1;
selection.startPoint = getPointForLineAndChar(ss); selection.startPoint = getPointForLineAndChar(ss);
var se = [selEnd[0], selEnd[1]]; var se = [selEnd[0], selEnd[1]];
if (mozillaCaretHack) se[1] += 1;
selection.endPoint = getPointForLineAndChar(se); selection.endPoint = getPointForLineAndChar(se);
selection.focusAtStart = !! rep.selFocusAtStart; selection.focusAtStart = !! rep.selFocusAtStart;
setSelection(selection); setSelection(selection);
if (mozillaCaretHack)
{
mozillaCaretHack.unhack();
}
} }
function getRepHTML() function getRepHTML()
@ -4926,27 +4835,30 @@ function Ace2Inner(){
} }
} }
} }
var listAttributeName = 'list';
function getLineListType(lineNum) function getLineListType(lineNum)
{ {
// get "list" attribute of first char of line return documentAttributeManager.getAttributeOnLine(lineNum, listAttributeName)
var aline = rep.alines[lineNum];
if (aline)
{
var opIter = Changeset.opIterator(aline);
if (opIter.hasNext())
{
return Changeset.opAttributeValue(opIter.next(), 'list', rep.apool) || '';
}
}
return '';
} }
function setLineListType(lineNum, listType) function setLineListType(lineNum, listType)
{ {
setLineListTypes([ if(listType == ''){
[lineNum, listType] documentAttributeManager.removeAttributeOnLine(lineNum, listAttributeName);
]); }else{
documentAttributeManager.setAttributeOnLine(lineNum, listAttributeName, listType);
}
//if the list has been removed, it is necessary to renumber
//starting from the *next* line because the list may have been
//separated. If it returns null, it means that the list was not cut, try
//from the current one.
if(renumberList(lineNum+1)==null)
{
renumberList(lineNum);
}
} }
function renumberList(lineNum){ function renumberList(lineNum){
@ -4993,8 +4905,8 @@ function Ace2Inner(){
} }
else if(curLevel == level) else if(curLevel == level)
{ {
buildKeepRange(builder, loc, (loc = [line, 0])); ChangesetUtils.buildKeepRange(rep, builder, loc, (loc = [line, 0]));
buildKeepRange(builder, loc, (loc = [line, 1]), [ ChangesetUtils.buildKeepRange(rep, builder, loc, (loc = [line, 1]), [
['start', position] ['start', position]
], rep.apool); ], rep.apool);
@ -5025,62 +4937,6 @@ function Ace2Inner(){
} }
function setLineListTypes(lineNumTypePairsInOrder)
{
var loc = [0, 0];
var builder = Changeset.builder(rep.lines.totalWidth());
for (var i = 0; i < lineNumTypePairsInOrder.length; i++)
{
var pair = lineNumTypePairsInOrder[i];
var lineNum = pair[0];
var listType = pair[1];
buildKeepRange(builder, loc, (loc = [lineNum, 0]));
if (getLineListType(lineNum))
{
// already a line marker
if (listType)
{
// make different list type
buildKeepRange(builder, loc, (loc = [lineNum, 1]), [
['list', listType]
], rep.apool);
}
else
{
// remove list marker
buildRemoveRange(builder, loc, (loc = [lineNum, 1]));
}
}
else
{
// currently no line marker
if (listType)
{
// add a line marker
builder.insert('*', [
['author', thisAuthor],
['insertorder', 'first'],
['list', listType]
], rep.apool);
}
}
}
var cs = builder.toString();
if (!Changeset.isIdentity(cs))
{
performDocumentApplyChangeset(cs);
}
//if the list has been removed, it is necessary to renumber
//starting from the *next* line because the list may have been
//separated. If it returns null, it means that the list was not cut, try
//from the current one.
if(renumberList(lineNum+1)==null)
{
renumberList(lineNum);
}
}
function doInsertList(type) function doInsertList(type)
{ {
@ -5118,7 +4974,10 @@ function Ace2Inner(){
var t = getLineListType(n); var t = getLineListType(n);
mods.push([n, allLinesAreList ? 'indent' + level : (t ? type + level : type + '1')]); mods.push([n, allLinesAreList ? 'indent' + level : (t ? type + level : type + '1')]);
} }
setLineListTypes(mods);
_.each(mods, function(mod){
setLineListType(mod[0], mod[1]);
});
} }
function doInsertUnorderedList(){ function doInsertUnorderedList(){
@ -5538,6 +5397,11 @@ function Ace2Inner(){
} }
} }
} }
// Init documentAttributeManager
documentAttributeManager = new AttributeManager(rep, performDocumentApplyChangeset);
editorInfo.ace_performDocumentApplyAttributesToRange = documentAttributeManager.setAttributesOnRange;
$(document).ready(function(){ $(document).ready(function(){
doc = document; // defined as a var in scope outside doc = document; // defined as a var in scope outside
@ -5577,7 +5441,13 @@ function Ace2Inner(){
bindTheEventHandlers(); bindTheEventHandlers();
}); });
hooks.callAll('aceInitialized', {
editorInfo: editorInfo,
rep: rep,
documentAttributeManager: documentAttributeManager
});
scheduler.setTimeout(function() scheduler.setTimeout(function()
{ {
parent.readyFunc(); // defined in code that sets up the inner iframe parent.readyFunc(); // defined in code that sets up the inner iframe

View file

@ -170,41 +170,67 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
$('#error').show(); $('#error').show();
} }
var fixPadHeight = _.throttle(function(){
var height = $('#timeslider-top').height();
$('#editorcontainerbox').css({marginTop: height});
}, 600);
function setAuthors(authors) function setAuthors(authors)
{ {
$("#authorstable").empty(); var authorsList = $("#authorsList");
authorsList.empty();
var numAnonymous = 0; var numAnonymous = 0;
var numNamed = 0; var numNamed = 0;
var colorsAnonymous = [];
_.each(authors, function(author) _.each(authors, function(author)
{ {
var authorColor = clientVars.colorPalette[author.colorId] || author.colorId;
if (author.name) if (author.name)
{ {
if (numNamed !== 0) authorsList.append(', ');
$('<span />')
.text(author.name || "unnamed")
.css('background-color', authorColor)
.addClass('author')
.appendTo(authorsList);
numNamed++; 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 else
{ {
numAnonymous++; numAnonymous++;
if(authorColor) colorsAnonymous.push(authorColor);
} }
}); });
if (numAnonymous > 0) 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>"; var anonymousAuthorString = numAnonymous + " unnamed author" + (numAnonymous > 1 ? "s" : "")
$("#authorstable").append($(html)); 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) 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 = { BroadcastSlider = {
@ -465,7 +491,6 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
{ {
if (clientVars.supportsSlider) if (clientVars.supportsSlider)
{ {
$("#padmain, #rightbars").css('top', "130px");
$("#timeslider").show(); $("#timeslider").show();
setSliderLength(clientVars.totalRevs); setSliderLength(clientVars.totalRevs);
setSliderPosition(clientVars.revNum); setSliderPosition(clientVars.revNum);

View file

@ -27,6 +27,7 @@ var _MAX_LIST_LEVEL = 8;
var Changeset = require('./Changeset'); var Changeset = require('./Changeset');
var hooks = require('./pluginfw/hooks'); var hooks = require('./pluginfw/hooks');
var _ = require('./underscore');
function sanitizeUnicode(s) function sanitizeUnicode(s)
{ {
@ -161,12 +162,6 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
var selection, startPoint, endPoint; var selection, startPoint, endPoint;
var selStart = [-1, -1], var selStart = [-1, -1],
selEnd = [-1, -1]; selEnd = [-1, -1];
var blockElems = {
"div": 1,
"p": 1,
"pre": 1
};
function _isEmpty(node, state) function _isEmpty(node, state)
{ {
// consider clean blank lines pasted in IE to be empty // consider clean blank lines pasted in IE to be empty
@ -188,7 +183,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
{ {
var ln = lines.length() - 1; var ln = lines.length() - 1;
var chr = lines.textOfLine(ln).length; var chr = lines.textOfLine(ln).length;
if (chr == 0 && state.listType && state.listType != 'none') if (chr == 0 && !_.isEmpty(state.lineAttributes))
{ {
chr += 1; // listMarker chr += 1; // listMarker
} }
@ -240,25 +235,30 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
function _enterList(state, listType) function _enterList(state, listType)
{ {
var oldListType = state.listType; var oldListType = state.lineAttributes['list'];
state.listLevel = (state.listLevel || 0) + 1;
if (listType != 'none') if (listType != 'none')
{ {
state.listNesting = (state.listNesting || 0) + 1; state.listNesting = (state.listNesting || 0) + 1;
} }
state.listType = listType;
if(listType === 'none' || !listType ){
delete state.lineAttributes['list'];
}
else{
state.lineAttributes['list'] = listType;
}
_recalcAttribString(state); _recalcAttribString(state);
return oldListType; return oldListType;
} }
function _exitList(state, oldListType) function _exitList(state, oldListType)
{ {
state.listLevel--; if (state.lineAttributes['list'])
if (state.listType != 'none')
{ {
state.listNesting--; state.listNesting--;
} }
state.listType = oldListType; if(oldListType) state.lineAttributes['list'] = oldListType;
_recalcAttribString(state); _recalcAttribString(state);
} }
@ -301,21 +301,29 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
state.attribString = Changeset.makeAttribsString('+', lst, apool); state.attribString = Changeset.makeAttribsString('+', lst, apool);
} }
function _produceListMarker(state) function _produceLineAttributesMarker(state)
{ {
lines.appendText('*', Changeset.makeAttribsString('+', [ // TODO: This has to go to AttributeManager.
['list', state.listType], var attributes = [
['lmkr', '1'],
['insertorder', 'first'] ['insertorder', 'first']
], apool)); ].concat(
_.map(state.lineAttributes,function(value,key){
console.log([key, value])
return [key, value];
})
);
lines.appendText('*', Changeset.makeAttribsString('+', attributes , apool));
} }
cc.startNewLine = function(state) cc.startNewLine = function(state)
{ {
if (state) if (state)
{ {
var atBeginningOfLine = lines.textOfLine(lines.length() - 1).length == 0; var atBeginningOfLine = lines.textOfLine(lines.length() - 1).length == 0;
if (atBeginningOfLine && state.listType && state.listType != 'none') if (atBeginningOfLine && !_.isEmpty(state.lineAttributes))
{ {
_produceListMarker(state); _produceLineAttributesMarker(state);
} }
} }
lines.startNew(); lines.startNew();
@ -345,7 +353,14 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
localAttribs: null, localAttribs: null,
attribs: { /*name -> nesting counter*/ attribs: { /*name -> nesting counter*/
}, },
attribString: '' attribString: '',
// lineAttributes maintain a map from attributes to attribute values set on a line
lineAttributes: {
/*
example:
'list': 'bullet1',
*/
}
}; };
} }
var localAttribs = state.localAttribs; var localAttribs = state.localAttribs;
@ -407,9 +422,9 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
// newlines in the source mustn't become spaces at beginning of line box // newlines in the source mustn't become spaces at beginning of line box
txt2 = txt2.replace(/^\n*/, ''); txt2 = txt2.replace(/^\n*/, '');
} }
if (atBeginningOfLine && state.listType && state.listType != 'none') if (atBeginningOfLine && !_.isEmpty(state.lineAttributes))
{ {
_produceListMarker(state); _produceLineAttributesMarker(state);
} }
lines.appendText(textify(txt2), state.attribString); lines.appendText(textify(txt2), state.attribString);
x += consumed; x += consumed;

View file

@ -29,7 +29,7 @@
var Security = require('./security'); var Security = require('./security');
var hooks = require('./pluginfw/hooks'); var hooks = require('./pluginfw/hooks');
var _ = require('./underscore'); var _ = require('./underscore');
var lineAttributeMarker = require('./linestylefilter').lineAttributeMarker;
var Ace2Common = require('./ace2_common'); var Ace2Common = require('./ace2_common');
var noop = Ace2Common.noop; var noop = Ace2Common.noop;
@ -82,7 +82,8 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
} }
var html = []; var html = [];
var preHtml, postHtml; var preHtml = '',
postHtml = '';
var curHTML = null; var curHTML = null;
function processSpaces(s) function processSpaces(s)
@ -95,7 +96,9 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
var lineClass = 'ace-line'; var lineClass = 'ace-line';
result.appendSpan = function(txt, cls) result.appendSpan = function(txt, cls)
{ {
if (cls.indexOf('list') >= 0) var processedMarker = false;
// Handle lineAttributeMarker, if present
if (cls.indexOf(lineAttributeMarker) >= 0)
{ {
var listType = /(?:^| )list:(\S+)/.exec(cls); var listType = /(?:^| )list:(\S+)/.exec(cls);
var start = /(?:^| )start:(\S+)/.exec(cls); var start = /(?:^| )start:(\S+)/.exec(cls);
@ -115,10 +118,26 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
preHtml = '<ol '+start+' class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>'; preHtml = '<ol '+start+' class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>';
postHtml = '</li></ol>'; postHtml = '</li></ol>';
} }
} }
processedMarker = true;
}
_.map(hooks.callAll("aceDomLineProcessLineAttributes", {
domline: domline,
cls: cls
}), function(modifier)
{
preHtml += modifier.preHtml;
postHtml += modifier.postHtml;
processedMarker |= modifier.processedMarker;
});
if( processedMarker ){
result.lineMarker += txt.length; result.lineMarker += txt.length;
return; // don't append any text return; // don't append any text
} }
} }
var href = null; var href = null;
var simpleTags = null; var simpleTags = null;
@ -203,7 +222,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
{ {
newHTML = (preHtml || '') + newHTML + (postHtml || ''); newHTML = (preHtml || '') + newHTML + (postHtml || '');
} }
html = preHtml = postHtml = null; // free memory html = preHtml = postHtml = ''; // free memory
if (newHTML !== curHTML) if (newHTML !== curHTML)
{ {
curHTML = newHTML; curHTML = newHTML;

View file

@ -32,6 +32,8 @@ var Changeset = require('./Changeset');
var hooks = require('./pluginfw/hooks'); var hooks = require('./pluginfw/hooks');
var linestylefilter = {}; var linestylefilter = {};
var _ = require('./underscore'); var _ = require('./underscore');
var AttributeManager = require('./AttributeManager');
linestylefilter.ATTRIB_CLASSES = { linestylefilter.ATTRIB_CLASSES = {
'bold': 'tag:b', 'bold': 'tag:b',
@ -40,6 +42,9 @@ linestylefilter.ATTRIB_CLASSES = {
'strikethrough': 'tag:s' 'strikethrough': 'tag:s'
}; };
var lineAttributeMarker = 'lineAttribMarker';
exports.lineAttributeMarker = lineAttributeMarker;
linestylefilter.getAuthorClassName = function(author) linestylefilter.getAuthorClassName = function(author)
{ {
return "author-" + author.replace(/[^a-y0-9]/g, function(c) return "author-" + author.replace(/[^a-y0-9]/g, function(c)
@ -68,14 +73,19 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
function attribsToClasses(attribs) function attribsToClasses(attribs)
{ {
var classes = ''; var classes = '';
var isLineAttribMarker = false;
Changeset.eachAttribNumber(attribs, function(n) Changeset.eachAttribNumber(attribs, function(n)
{ {
var key = apool.getAttribKey(n); var key = apool.getAttribKey(n);
if (key) if (key)
{ {
var value = apool.getAttribValue(n); var value = apool.getAttribValue(n);
if (value) if (value)
{ {
if (!isLineAttribMarker && _.indexOf(AttributeManager.lineAttributes, key) >= 0){
isLineAttribMarker = true;
}
if (key == 'author') if (key == 'author')
{ {
classes += ' ' + linestylefilter.getAuthorClassName(value); classes += ' ' + linestylefilter.getAuthorClassName(value);
@ -99,10 +109,12 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
key: key, key: key,
value: value value: value
}, " ", " ", ""); }, " ", " ", "");
} }
} }
} }
}); });
if(isLineAttribMarker) classes += ' ' + lineAttributeMarker;
return classes.substring(1); return classes.substring(1);
} }

View file

@ -534,7 +534,7 @@ var pad = {
if(padcookie.getPref("showAuthorshipColors") == false){ if(padcookie.getPref("showAuthorshipColors") == false){
pad.changeViewOption('showAuthorColors', false); pad.changeViewOption('showAuthorColors', false);
} }
hooks.aCallAll("postAceInit"); hooks.aCallAll("postAceInit", {ace: padeditor.ace});
} }
}, },
dispose: function() dispose: function()

View file

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

View file

@ -98,6 +98,28 @@ if (exports.isClient) {
}; };
} else { } 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.update = function (cb) {
exports.getPackages(function (er, packages) { exports.getPackages(function (er, packages) {
var parts = []; var parts = [];
@ -109,11 +131,12 @@ exports.update = function (cb) {
exports.loadPlugin(packages, plugin_name, plugins, parts, cb); exports.loadPlugin(packages, plugin_name, plugins, parts, cb);
}, },
function (err) { function (err) {
exports.plugins = plugins; if (err) cb(err);
exports.plugins = plugins;
exports.parts = exports.sortParts(parts); exports.parts = exports.sortParts(parts);
exports.hooks = exports.extractHooks(exports.parts, "hooks"); exports.hooks = exports.extractHooks(exports.parts, "hooks");
exports.loaded = true; exports.loaded = true;
cb(err); exports.callInit(cb);
} }
); );
}); });

View file

@ -155,6 +155,9 @@ function SkipList()
var widthLoc = point.widthSkips[0] + point.nodes[0].downSkipWidths[0]; var widthLoc = point.widthSkips[0] + point.nodes[0].downSkipWidths[0];
var newWidth = _entryWidth(entry); var newWidth = _entryWidth(entry);
p.mark("loop1"); p.mark("loop1");
// The new node will have at least level 1
// With a proability of 0.01^(n-1) the nodes level will be >= n
while (newNode.levels == 0 || Math.random() < 0.01) while (newNode.levels == 0 || Math.random() < 0.01)
{ {
var lvl = newNode.levels; var lvl = newNode.levels;

View file

@ -130,6 +130,7 @@
<script src="static/custom/index.js"></script> <script src="static/custom/index.js"></script>
<script> <script>
document.domain = document.domain;
function go2Name() function go2Name()
{ {
var padname = document.getElementById("padname").value; 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" src="../javascripts/lib/ep_etherpad-lite/static/js/pad.js?callback=require.define"></script>
<% } %> <% } %>
<script type="text/javascript"> <script type="text/javascript">
document.domain = document.domain;
var clientVars = {}; var clientVars = {};
(function () { (function () {
<% if (settings.minify) { %> <% if (settings.minify) { %>

View file

@ -11,40 +11,14 @@
<style type="text/css" title="dynamicsyntax"></style> <style type="text/css" title="dynamicsyntax"></style>
</head> </head>
<body id="padbody" class="timeslider limwidth nonpropad nonprouser"> <body id="padbody" class="timeslider limwidth">
<div id="padpage"> <div id="padpage">
<div id="padtop"> <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="alertbar">
<div id="servermsg"> <div id="servermsg">
<h3>Server Notice<span id="servermsgdate"><!-- --></span>:</h3><a id= <h3>Server Notice<span id="servermsgdate"><!-- --></span>:</h3><a id=
"hidetopmsg" href="javascript:%20void%20pad.hideServerMessage()" name= "hidetopmsg" href="javascript:%20void%20pad.hideServerMessage()" name=
"hidetopmsg">hide</a> "hidetopmsg">hide</a>
<p id="servermsgtext"><!-- --></p> <p id="servermsgtext"><!-- --></p>
</div> </div>
</div> </div>
@ -67,104 +41,56 @@
</table> </table>
</div><!-- /docbar --> </div><!-- /docbar -->
</div> </div>
<div id="timeslider-wrapper"> <div id="timeslider-top">
<div id="error" style="display: none"> <div id="timeslider-wrapper">
It looks like you're having connection troubles. <a href= <div id="timeslider" unselectable="on" style="display: none">
"/ep/pad/view/test/latest">Reconnect now</a>. <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>
<div id="timeslider" unselectable="on" style="display: none"> <div class="timeslider-bar">
<div id="timeslider-left"></div> <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>
<h1>
<div id="timer"></div> <span id="revision_label"></span>
<span id="revision_date"></span>
<div id="timeslider-slider"> </h1>
<div id="ui-slider-handle"></div> <p>Authors:
<span id="authorsList">
<div id="ui-slider-bar"></div> <span>No Authors</span>
</div> </span> </p>
</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> </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="padmain">
<div id="padeditor"> <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="editorcontainerbox">
<div id="padcontent"> <div id="padcontent">
</div> </div>
</div> </div>
</div><!-- /padeditor --> </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="../../../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" src="../../../static/custom/timeslider.js"></script>
<script type="text/javascript" > <script type="text/javascript" >
document.domain = document.domain;
var clientVars = {}; var clientVars = {};
(function () { (function () {
require.setRootURI("../../../javascripts/src"); require.setRootURI("../../../javascripts/src");