mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-21 16:06:16 -04:00
Merge branch 'develop' of https://github.com/Pita/etherpad-lite into develop
This commit is contained in:
commit
baf215fae6
22 changed files with 581 additions and 387 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -11,3 +11,4 @@ bin/convertSettings.json
|
|||
src/static/js/jquery.js
|
||||
npm-debug.log
|
||||
*.DS_Store
|
||||
.ep_initialized
|
||||
|
|
|
@ -24,6 +24,7 @@ var async = require("async");
|
|||
var padManager = require("../db/PadManager");
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var AttributePool = require("ep_etherpad-lite/static/js/AttributePool");
|
||||
var AttributeManager = require("ep_etherpad-lite/static/js/AttributeManager");
|
||||
var authorManager = require("../db/AuthorManager");
|
||||
var readOnlyManager = require("../db/ReadOnlyManager");
|
||||
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 log4js = require('log4js');
|
||||
var messageLogger = log4js.getLogger("message");
|
||||
var _ = require('underscore');
|
||||
|
||||
/**
|
||||
* A associative array that translates a session to a pad
|
||||
|
@ -591,8 +593,12 @@ function _correctMarkersInPad(atext, apool) {
|
|||
var offset = 0;
|
||||
while (iter.hasNext()) {
|
||||
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++) {
|
||||
if (offset > 0 && text.charAt(offset-1) != '\n') {
|
||||
badMarkers.push(offset);
|
||||
|
|
|
@ -4,13 +4,14 @@ var formidable = require('formidable');
|
|||
var apiHandler = require('../../handler/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");
|
||||
|
||||
apiLogger.info("REQUEST, " + req.params.func + ", " + JSON.stringify(fields));
|
||||
|
||||
//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) {
|
||||
response = JSON.stringify(response);
|
||||
apiLogger.info("RESPONSE, " + req.params.func + ", " + response);
|
||||
|
@ -19,13 +20,14 @@ exports.apiCaller = function(req, res, fields) {
|
|||
if(req.query.jsonp)
|
||||
response = req.query.jsonp + "(" + response + ")";
|
||||
|
||||
res._send(response);
|
||||
res._____send(response);
|
||||
}
|
||||
|
||||
//call the api handler
|
||||
apiHandler.handle(req.params.func, fields, req, res);
|
||||
}
|
||||
|
||||
exports.apiCaller = apiCaller;
|
||||
|
||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
//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");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
, "rjquery.js"
|
||||
, "AttributePool.js"
|
||||
, "Changeset.js"
|
||||
, "ChangesetUtils.js"
|
||||
, "security.js"
|
||||
, "skiplist.js"
|
||||
, "virtual_lines.js"
|
||||
|
@ -66,6 +67,7 @@
|
|||
, "changesettracker.js"
|
||||
, "linestylefilter.js"
|
||||
, "domline.js"
|
||||
, "AttributeManager.js"
|
||||
, "ace2_inner.js"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -42,9 +42,8 @@ a img
|
|||
border-bottom: 1px solid #ccc;
|
||||
overflow: hidden;
|
||||
padding-top: 3px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
|
@ -177,7 +176,6 @@ a#backtoprosite { padding-left: 20px; left: 6px;
|
|||
background: url(static/img/protop.gif) no-repeat -5px -6px; }
|
||||
#accountnav { right: 30px; color: #fff; }
|
||||
|
||||
.propad a#topbaretherpad { background: url(static/img/protop.gif) no-repeat -397px -3px; }
|
||||
|
||||
#specialkeyarea { top: 5px; left: 250px; color: yellow; font-weight: bold;
|
||||
font-size: 1.5em; position: absolute; }
|
||||
|
@ -606,8 +604,6 @@ table#otheruserstable { display: none; }
|
|||
text-align: left;
|
||||
}
|
||||
|
||||
.nonprouser #sharebox-stripe { display: none; }
|
||||
|
||||
.sharebox-url {
|
||||
width: 440px; height: 18px;
|
||||
text-align: left;
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#editorcontainerbox {overflow:auto; top:40px;}
|
||||
#editorcontainerbox {
|
||||
overflow:auto; top:40px;
|
||||
position: static;
|
||||
}
|
||||
|
||||
#padcontent {font-size:12px; padding:10px;}
|
||||
|
||||
|
@ -67,8 +70,9 @@
|
|||
width:122px;
|
||||
}
|
||||
|
||||
|
||||
.topbarcenter, #docbar {display:none;}
|
||||
#padmain {top:30px;}
|
||||
#padmain {top:0px !important;}
|
||||
#editbarright {float:right;}
|
||||
#returnbutton {color:#222; font-size:16px; line-height:29px; margin-top:0; padding-right:6px;}
|
||||
#importexport .popup {width:185px;}
|
||||
|
@ -77,6 +81,53 @@
|
|||
width:185px;
|
||||
}
|
||||
|
||||
|
||||
.timeslider-bar
|
||||
{
|
||||
background: #f7f7f7;
|
||||
background: linear-gradient(#f7f7f7, #f1f1f1 80%);
|
||||
border-bottom: 1px solid #ccc;
|
||||
overflow: hidden;
|
||||
padding-top: 3px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.timeslider-bar #editbar
|
||||
{
|
||||
border-bottom: none;
|
||||
float: right;
|
||||
width: 170px;
|
||||
width: initial;
|
||||
}
|
||||
|
||||
.timeslider-bar h1
|
||||
{
|
||||
margin: 5px;
|
||||
}
|
||||
.timeslider-bar p
|
||||
{
|
||||
margin: 5px;
|
||||
}
|
||||
#timeslider-top {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#authorsList .author {
|
||||
padding-left: 0.4em;
|
||||
padding-right: 0.4em;
|
||||
}
|
||||
|
||||
#authorsList .author-anonymous {
|
||||
padding-left: 0.6em;
|
||||
padding-right: 0.6em;
|
||||
}
|
||||
|
||||
#padeditor {
|
||||
position: static;
|
||||
}
|
||||
|
||||
/* lists */
|
||||
.list-bullet2, .list-indent2, .list-number2 {margin-left:3em;}
|
||||
.list-bullet3, .list-indent3, .list-number3 {margin-left:4.5em;}
|
||||
|
|
164
src/static/js/AttributeManager.js
Normal file
164
src/static/js/AttributeManager.js
Normal 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;
|
|
@ -22,6 +22,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
An AttributePool maintains a mapping from [key,value] Pairs called
|
||||
Attributes to Numbers (unsigened integers) and vice versa. These numbers are
|
||||
used to reference Attributes in Changesets.
|
||||
*/
|
||||
|
||||
var AttributePool = function () {
|
||||
this.numToAttrib = {}; // e.g. {0: ['foo','bar']}
|
||||
this.attribToNum = {}; // e.g. {'foo,bar': 0}
|
||||
|
|
60
src/static/js/ChangesetUtils.js
Normal file
60
src/static/js/ChangesetUtils.js
Normal 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]);
|
||||
}
|
||||
|
|
@ -256,6 +256,10 @@ require.setGlobalKeyPath("require");\n\
|
|||
$$INCLUDE_CSS("../static/css/iframe_editor.css");
|
||||
$$INCLUDE_CSS("../static/css/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);
|
||||
|
||||
var includedJS = [];
|
||||
|
@ -294,6 +298,11 @@ require.setGlobalKeyPath("require");\n\
|
|||
$$INCLUDE_CSS("../static/css/iframe_editor.css");
|
||||
$$INCLUDE_CSS("../static/css/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);
|
||||
|
||||
// bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly
|
||||
|
|
|
@ -35,6 +35,8 @@ var isNodeText = Ace2Common.isNodeText,
|
|||
binarySearchInfinite = Ace2Common.binarySearchInfinite,
|
||||
htmlPrettyEscape = Ace2Common.htmlPrettyEscape,
|
||||
noop = Ace2Common.noop;
|
||||
var hooks = require('./pluginfw/hooks');
|
||||
|
||||
|
||||
function Ace2Inner(){
|
||||
|
||||
|
@ -45,10 +47,12 @@ function Ace2Inner(){
|
|||
var domline = require('./domline').domline;
|
||||
var AttribPool = require('./AttributePool');
|
||||
var Changeset = require('./Changeset');
|
||||
var ChangesetUtils = require('./ChangesetUtils');
|
||||
var linestylefilter = require('./linestylefilter').linestylefilter;
|
||||
var SkipList = require('./skiplist');
|
||||
var undoModule = require('./undomodule').undoModule;
|
||||
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;"
|
||||
// changed to false
|
||||
|
@ -78,14 +82,11 @@ function Ace2Inner(){
|
|||
var overlaysdiv = lineMetricsDiv.nextSibling;
|
||||
initLineNumbers();
|
||||
|
||||
var outsideKeyDown = function(evt)
|
||||
{};
|
||||
var outsideKeyPress = function(evt)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
var outsideNotifyDirty = function()
|
||||
{};
|
||||
var outsideKeyDown = noop;
|
||||
|
||||
var outsideKeyPress = function(){return true;};
|
||||
|
||||
var outsideNotifyDirty = noop;
|
||||
|
||||
// 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
|
||||
|
@ -100,6 +101,7 @@ function Ace2Inner(){
|
|||
alines: [],
|
||||
apool: new AttribPool()
|
||||
};
|
||||
|
||||
// lines, alltext, alines, and DOM are set up in setup()
|
||||
if (undoModule.enabled)
|
||||
{
|
||||
|
@ -119,6 +121,7 @@ function Ace2Inner(){
|
|||
iframePadRight = 0;
|
||||
|
||||
var console = (DEBUG && window.console);
|
||||
var documentAttributeManager;
|
||||
|
||||
if (!window.console)
|
||||
{
|
||||
|
@ -155,6 +158,7 @@ function Ace2Inner(){
|
|||
|
||||
var textFace = 'monospace';
|
||||
var textSize = 12;
|
||||
|
||||
|
||||
function textLineHeight()
|
||||
{
|
||||
|
@ -929,7 +933,10 @@ function Ace2Inner(){
|
|||
},
|
||||
grayedout: setClassPresenceNamed(outerWin.document.body, "grayedout"),
|
||||
dmesg: function(){ dmesg = window.dmesg = value; },
|
||||
userauthor: function(value){ thisAuthor = String(value); },
|
||||
userauthor: function(value){
|
||||
thisAuthor = String(value);
|
||||
documentAttributeManager.author = thisAuthor;
|
||||
},
|
||||
styled: setStyled,
|
||||
textface: setTextFace,
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
var lineEntry = rep.lines.atOffset(x);
|
||||
|
@ -2301,8 +2262,8 @@ function Ace2Inner(){
|
|||
// CCCC\n
|
||||
// end[0]: <CCC end[1] CCC>-------\n
|
||||
var builder = Changeset.builder(rep.lines.totalWidth());
|
||||
buildKeepToStartOfRange(builder, start);
|
||||
buildRemoveRange(builder, start, end);
|
||||
ChangesetUtils.buildKeepToStartOfRange(rep, builder, start);
|
||||
ChangesetUtils.buildRemoveRange(rep, builder, start, end);
|
||||
builder.insert(newText, [
|
||||
['author', thisAuthor]
|
||||
], rep.apool);
|
||||
|
@ -2313,69 +2274,17 @@ function Ace2Inner(){
|
|||
|
||||
function performDocumentApplyAttributesToCharRange(start, end, attribs)
|
||||
{
|
||||
if (end >= rep.alltext.length)
|
||||
{
|
||||
end = rep.alltext.length - 1;
|
||||
}
|
||||
performDocumentApplyAttributesToRange(lineAndColumnFromChar(start), lineAndColumnFromChar(end), attribs);
|
||||
end = Math.min(end, rep.alltext.length - 1);
|
||||
documentAttributeManager.setAttributesOnRange(lineAndColumnFromChar(start), lineAndColumnFromChar(end), attribs);
|
||||
}
|
||||
editorInfo.ace_performDocumentApplyAttributesToCharRange = performDocumentApplyAttributesToCharRange;
|
||||
|
||||
function performDocumentApplyAttributesToRange(start, end, attribs)
|
||||
{
|
||||
var builder = Changeset.builder(rep.lines.totalWidth());
|
||||
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)
|
||||
{
|
||||
if (!(rep.selStart && rep.selEnd)) return;
|
||||
|
||||
performDocumentApplyAttributesToRange(rep.selStart, rep.selEnd, [
|
||||
documentAttributeManager.setAttributesOnRange(rep.selStart, rep.selEnd, [
|
||||
[attributeName, attributeValue]
|
||||
]);
|
||||
}
|
||||
|
@ -2436,13 +2345,13 @@ function Ace2Inner(){
|
|||
|
||||
if (selectionAllHasIt)
|
||||
{
|
||||
performDocumentApplyAttributesToRange(rep.selStart, rep.selEnd, [
|
||||
documentAttributeManager.setAttributesOnRange(rep.selStart, rep.selEnd, [
|
||||
[attributeName, '']
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
performDocumentApplyAttributesToRange(rep.selStart, rep.selEnd, [
|
||||
documentAttributeManager.setAttributesOnRange(rep.selStart, rep.selEnd, [
|
||||
[attributeName, 'true']
|
||||
]);
|
||||
}
|
||||
|
@ -2964,6 +2873,10 @@ function Ace2Inner(){
|
|||
"ul": 1
|
||||
};
|
||||
|
||||
_.each(hooks.callAll('aceRegisterBlockElements'), function(element){
|
||||
_blockElems[element] = 1;
|
||||
});
|
||||
|
||||
function isBlockElement(n)
|
||||
{
|
||||
return !!_blockElems[(n.tagName || "").toLowerCase()];
|
||||
|
@ -3328,6 +3241,7 @@ function Ace2Inner(){
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var lineNum = rep.selStart[0];
|
||||
var listType = getLineListType(lineNum);
|
||||
|
||||
|
@ -3399,11 +3313,9 @@ function Ace2Inner(){
|
|||
}
|
||||
}
|
||||
|
||||
if (mods.length > 0)
|
||||
{
|
||||
setLineListTypes(mods);
|
||||
}
|
||||
|
||||
_.each(mods, function(mod){
|
||||
setLineListType(mod[0], mod[1]);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
editorInfo.ace_doIndentOutdent = doIndentOutdent;
|
||||
|
@ -3453,6 +3365,9 @@ function Ace2Inner(){
|
|||
var thisLineListType = getLineListType(theLine);
|
||||
var prevLineEntry = (theLine > 0 && rep.lines.atIndex(theLine - 1));
|
||||
var prevLineBlank = (prevLineEntry && prevLineEntry.text.length == prevLineEntry.lineMarker);
|
||||
|
||||
var thisLineHasMarker = documentAttributeManager.lineHasMarker(theLine);
|
||||
|
||||
if (thisLineListType)
|
||||
{
|
||||
// this line is a list
|
||||
|
@ -3466,6 +3381,9 @@ function Ace2Inner(){
|
|||
// delistify
|
||||
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)
|
||||
{
|
||||
|
@ -3818,26 +3736,17 @@ function Ace2Inner(){
|
|||
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 ss = [selStart[0], selStart[1]];
|
||||
if (mozillaCaretHack) ss[1] += 1;
|
||||
selection.startPoint = getPointForLineAndChar(ss);
|
||||
|
||||
var se = [selEnd[0], selEnd[1]];
|
||||
if (mozillaCaretHack) se[1] += 1;
|
||||
selection.endPoint = getPointForLineAndChar(se);
|
||||
|
||||
selection.focusAtStart = !! rep.selFocusAtStart;
|
||||
|
||||
setSelection(selection);
|
||||
|
||||
if (mozillaCaretHack)
|
||||
{
|
||||
mozillaCaretHack.unhack();
|
||||
}
|
||||
}
|
||||
|
||||
function getRepHTML()
|
||||
|
@ -4926,27 +4835,30 @@ function Ace2Inner(){
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var listAttributeName = 'list';
|
||||
|
||||
function getLineListType(lineNum)
|
||||
{
|
||||
// get "list" attribute of first char of line
|
||||
var aline = rep.alines[lineNum];
|
||||
if (aline)
|
||||
{
|
||||
var opIter = Changeset.opIterator(aline);
|
||||
if (opIter.hasNext())
|
||||
{
|
||||
return Changeset.opAttributeValue(opIter.next(), 'list', rep.apool) || '';
|
||||
}
|
||||
}
|
||||
return '';
|
||||
return documentAttributeManager.getAttributeOnLine(lineNum, listAttributeName)
|
||||
}
|
||||
|
||||
function setLineListType(lineNum, listType)
|
||||
{
|
||||
setLineListTypes([
|
||||
[lineNum, listType]
|
||||
]);
|
||||
if(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){
|
||||
|
@ -4993,8 +4905,8 @@ function Ace2Inner(){
|
|||
}
|
||||
else if(curLevel == level)
|
||||
{
|
||||
buildKeepRange(builder, loc, (loc = [line, 0]));
|
||||
buildKeepRange(builder, loc, (loc = [line, 1]), [
|
||||
ChangesetUtils.buildKeepRange(rep, builder, loc, (loc = [line, 0]));
|
||||
ChangesetUtils.buildKeepRange(rep, builder, loc, (loc = [line, 1]), [
|
||||
['start', position]
|
||||
], 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)
|
||||
{
|
||||
|
@ -5118,7 +4974,10 @@ function Ace2Inner(){
|
|||
var t = getLineListType(n);
|
||||
mods.push([n, allLinesAreList ? 'indent' + level : (t ? type + level : type + '1')]);
|
||||
}
|
||||
setLineListTypes(mods);
|
||||
|
||||
_.each(mods, function(mod){
|
||||
setLineListType(mod[0], mod[1]);
|
||||
});
|
||||
}
|
||||
|
||||
function doInsertUnorderedList(){
|
||||
|
@ -5538,6 +5397,11 @@ function Ace2Inner(){
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Init documentAttributeManager
|
||||
documentAttributeManager = new AttributeManager(rep, performDocumentApplyChangeset);
|
||||
editorInfo.ace_performDocumentApplyAttributesToRange = documentAttributeManager.setAttributesOnRange;
|
||||
|
||||
$(document).ready(function(){
|
||||
doc = document; // defined as a var in scope outside
|
||||
|
@ -5577,7 +5441,13 @@ function Ace2Inner(){
|
|||
bindTheEventHandlers();
|
||||
|
||||
});
|
||||
|
||||
|
||||
hooks.callAll('aceInitialized', {
|
||||
editorInfo: editorInfo,
|
||||
rep: rep,
|
||||
documentAttributeManager: documentAttributeManager
|
||||
});
|
||||
|
||||
scheduler.setTimeout(function()
|
||||
{
|
||||
parent.readyFunc(); // defined in code that sets up the inner iframe
|
||||
|
|
|
@ -170,41 +170,67 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
$('#error').show();
|
||||
}
|
||||
|
||||
var fixPadHeight = _.throttle(function(){
|
||||
var height = $('#timeslider-top').height();
|
||||
$('#editorcontainerbox').css({marginTop: height});
|
||||
}, 600);
|
||||
|
||||
function setAuthors(authors)
|
||||
{
|
||||
$("#authorstable").empty();
|
||||
var authorsList = $("#authorsList");
|
||||
authorsList.empty();
|
||||
var numAnonymous = 0;
|
||||
var numNamed = 0;
|
||||
var colorsAnonymous = [];
|
||||
_.each(authors, function(author)
|
||||
{
|
||||
var authorColor = clientVars.colorPalette[author.colorId] || author.colorId;
|
||||
if (author.name)
|
||||
{
|
||||
if (numNamed !== 0) authorsList.append(', ');
|
||||
|
||||
$('<span />')
|
||||
.text(author.name || "unnamed")
|
||||
.css('background-color', authorColor)
|
||||
.addClass('author')
|
||||
.appendTo(authorsList);
|
||||
|
||||
numNamed++;
|
||||
var tr = $('<tr></tr>');
|
||||
var swatchtd = $('<td></td>');
|
||||
var swatch = $('<div class="swatch"></div>');
|
||||
swatch.css('background-color', clientVars.colorPalette[author.colorId]);
|
||||
swatchtd.append(swatch);
|
||||
tr.append(swatchtd);
|
||||
var nametd = $('<td></td>');
|
||||
nametd.text(author.name || "unnamed");
|
||||
tr.append(nametd);
|
||||
$("#authorstable").append(tr);
|
||||
}
|
||||
else
|
||||
{
|
||||
numAnonymous++;
|
||||
if(authorColor) colorsAnonymous.push(authorColor);
|
||||
}
|
||||
});
|
||||
if (numAnonymous > 0)
|
||||
{
|
||||
var html = "<tr><td colspan=\"2\" style=\"color:#999; padding-left: 10px\">" + (numNamed > 0 ? "...and " : "") + numAnonymous + " unnamed author" + (numAnonymous > 1 ? "s" : "") + "</td></tr>";
|
||||
$("#authorstable").append($(html));
|
||||
var anonymousAuthorString = numAnonymous + " unnamed author" + (numAnonymous > 1 ? "s" : "")
|
||||
if (numNamed !== 0){
|
||||
authorsList.append(' + ' + anonymousAuthorString);
|
||||
} else {
|
||||
authorsList.append(anonymousAuthorString);
|
||||
}
|
||||
|
||||
if(colorsAnonymous.length > 0){
|
||||
authorsList.append(' (');
|
||||
_.each(colorsAnonymous, function(color, i){
|
||||
if( i > 0 ) authorsList.append(' ');
|
||||
$('<span /> ')
|
||||
.css('background-color', color)
|
||||
.addClass('author author-anonymous')
|
||||
.appendTo(authorsList);
|
||||
});
|
||||
authorsList.append(')');
|
||||
}
|
||||
|
||||
}
|
||||
if (authors.length == 0)
|
||||
{
|
||||
$("#authorstable").append($("<tr><td colspan=\"2\" style=\"color:#999; padding-left: 10px\">No Authors</td></tr>"))
|
||||
authorsList.append("No Authors");
|
||||
}
|
||||
|
||||
fixPadHeight();
|
||||
}
|
||||
|
||||
BroadcastSlider = {
|
||||
|
@ -465,7 +491,6 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
{
|
||||
if (clientVars.supportsSlider)
|
||||
{
|
||||
$("#padmain, #rightbars").css('top', "130px");
|
||||
$("#timeslider").show();
|
||||
setSliderLength(clientVars.totalRevs);
|
||||
setSliderPosition(clientVars.revNum);
|
||||
|
|
|
@ -27,6 +27,7 @@ var _MAX_LIST_LEVEL = 8;
|
|||
|
||||
var Changeset = require('./Changeset');
|
||||
var hooks = require('./pluginfw/hooks');
|
||||
var _ = require('./underscore');
|
||||
|
||||
function sanitizeUnicode(s)
|
||||
{
|
||||
|
@ -161,12 +162,6 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
|||
var selection, startPoint, endPoint;
|
||||
var selStart = [-1, -1],
|
||||
selEnd = [-1, -1];
|
||||
var blockElems = {
|
||||
"div": 1,
|
||||
"p": 1,
|
||||
"pre": 1
|
||||
};
|
||||
|
||||
function _isEmpty(node, state)
|
||||
{
|
||||
// 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 chr = lines.textOfLine(ln).length;
|
||||
if (chr == 0 && state.listType && state.listType != 'none')
|
||||
if (chr == 0 && !_.isEmpty(state.lineAttributes))
|
||||
{
|
||||
chr += 1; // listMarker
|
||||
}
|
||||
|
@ -240,25 +235,30 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
|||
|
||||
function _enterList(state, listType)
|
||||
{
|
||||
var oldListType = state.listType;
|
||||
state.listLevel = (state.listLevel || 0) + 1;
|
||||
var oldListType = state.lineAttributes['list'];
|
||||
if (listType != 'none')
|
||||
{
|
||||
state.listNesting = (state.listNesting || 0) + 1;
|
||||
}
|
||||
state.listType = listType;
|
||||
|
||||
if(listType === 'none' || !listType ){
|
||||
delete state.lineAttributes['list'];
|
||||
}
|
||||
else{
|
||||
state.lineAttributes['list'] = listType;
|
||||
}
|
||||
|
||||
_recalcAttribString(state);
|
||||
return oldListType;
|
||||
}
|
||||
|
||||
function _exitList(state, oldListType)
|
||||
{
|
||||
state.listLevel--;
|
||||
if (state.listType != 'none')
|
||||
if (state.lineAttributes['list'])
|
||||
{
|
||||
state.listNesting--;
|
||||
}
|
||||
state.listType = oldListType;
|
||||
if(oldListType) state.lineAttributes['list'] = oldListType;
|
||||
_recalcAttribString(state);
|
||||
}
|
||||
|
||||
|
@ -301,21 +301,29 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
|||
state.attribString = Changeset.makeAttribsString('+', lst, apool);
|
||||
}
|
||||
|
||||
function _produceListMarker(state)
|
||||
function _produceLineAttributesMarker(state)
|
||||
{
|
||||
lines.appendText('*', Changeset.makeAttribsString('+', [
|
||||
['list', state.listType],
|
||||
// TODO: This has to go to AttributeManager.
|
||||
var attributes = [
|
||||
['lmkr', '1'],
|
||||
['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)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
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();
|
||||
|
@ -345,7 +353,14 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
|||
localAttribs: null,
|
||||
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;
|
||||
|
@ -407,9 +422,9 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
|||
// newlines in the source mustn't become spaces at beginning of line box
|
||||
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);
|
||||
x += consumed;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
var Security = require('./security');
|
||||
var hooks = require('./pluginfw/hooks');
|
||||
var _ = require('./underscore');
|
||||
|
||||
var lineAttributeMarker = require('./linestylefilter').lineAttributeMarker;
|
||||
var Ace2Common = require('./ace2_common');
|
||||
var noop = Ace2Common.noop;
|
||||
|
||||
|
@ -82,7 +82,8 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
}
|
||||
|
||||
var html = [];
|
||||
var preHtml, postHtml;
|
||||
var preHtml = '',
|
||||
postHtml = '';
|
||||
var curHTML = null;
|
||||
|
||||
function processSpaces(s)
|
||||
|
@ -95,7 +96,9 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
var lineClass = 'ace-line';
|
||||
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 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>';
|
||||
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;
|
||||
return; // don't append any text
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
var href = null;
|
||||
var simpleTags = null;
|
||||
|
@ -203,7 +222,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
{
|
||||
newHTML = (preHtml || '') + newHTML + (postHtml || '');
|
||||
}
|
||||
html = preHtml = postHtml = null; // free memory
|
||||
html = preHtml = postHtml = ''; // free memory
|
||||
if (newHTML !== curHTML)
|
||||
{
|
||||
curHTML = newHTML;
|
||||
|
|
|
@ -32,6 +32,8 @@ var Changeset = require('./Changeset');
|
|||
var hooks = require('./pluginfw/hooks');
|
||||
var linestylefilter = {};
|
||||
var _ = require('./underscore');
|
||||
var AttributeManager = require('./AttributeManager');
|
||||
|
||||
|
||||
linestylefilter.ATTRIB_CLASSES = {
|
||||
'bold': 'tag:b',
|
||||
|
@ -40,6 +42,9 @@ linestylefilter.ATTRIB_CLASSES = {
|
|||
'strikethrough': 'tag:s'
|
||||
};
|
||||
|
||||
var lineAttributeMarker = 'lineAttribMarker';
|
||||
exports.lineAttributeMarker = lineAttributeMarker;
|
||||
|
||||
linestylefilter.getAuthorClassName = function(author)
|
||||
{
|
||||
return "author-" + author.replace(/[^a-y0-9]/g, function(c)
|
||||
|
@ -68,14 +73,19 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
|||
function attribsToClasses(attribs)
|
||||
{
|
||||
var classes = '';
|
||||
var isLineAttribMarker = false;
|
||||
|
||||
Changeset.eachAttribNumber(attribs, function(n)
|
||||
{
|
||||
var key = apool.getAttribKey(n);
|
||||
var key = apool.getAttribKey(n);
|
||||
if (key)
|
||||
{
|
||||
var value = apool.getAttribValue(n);
|
||||
if (value)
|
||||
{
|
||||
if (!isLineAttribMarker && _.indexOf(AttributeManager.lineAttributes, key) >= 0){
|
||||
isLineAttribMarker = true;
|
||||
}
|
||||
if (key == 'author')
|
||||
{
|
||||
classes += ' ' + linestylefilter.getAuthorClassName(value);
|
||||
|
@ -99,10 +109,12 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
|||
key: key,
|
||||
value: value
|
||||
}, " ", " ", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(isLineAttribMarker) classes += ' ' + lineAttributeMarker;
|
||||
return classes.substring(1);
|
||||
}
|
||||
|
||||
|
|
|
@ -534,7 +534,7 @@ var pad = {
|
|||
if(padcookie.getPref("showAuthorshipColors") == false){
|
||||
pad.changeViewOption('showAuthorColors', false);
|
||||
}
|
||||
hooks.aCallAll("postAceInit");
|
||||
hooks.aCallAll("postAceInit", {ace: padeditor.ace});
|
||||
}
|
||||
},
|
||||
dispose: function()
|
||||
|
|
|
@ -200,10 +200,11 @@ var padeditbar = (function()
|
|||
else
|
||||
{
|
||||
var nth_child = indexOf(modules, moduleName) + 1;
|
||||
if (nth_child > 0 && nth_child <= 3) {
|
||||
if (nth_child > 0 && nth_child <= (modules.length-1)) {
|
||||
$("#editbar ul#menu_right li:not(:nth-child(" + nth_child + "))").removeClass("selected");
|
||||
$("#editbar ul#menu_right li:nth-child(" + nth_child + ")").toggleClass("selected");
|
||||
}
|
||||
if(modules[modules.length-1] === moduleName) $("#editbar ul#menu_right li").removeClass("selected");
|
||||
//hide all modules that are not selected and show the selected one
|
||||
for(var i=0;i<modules.length;i++)
|
||||
{
|
||||
|
|
|
@ -98,6 +98,28 @@ if (exports.isClient) {
|
|||
};
|
||||
} else {
|
||||
|
||||
exports.callInit = function (cb) {
|
||||
var hooks = require("./hooks");
|
||||
async.map(
|
||||
Object.keys(exports.plugins),
|
||||
function (plugin_name, cb) {
|
||||
var plugin = exports.plugins[plugin_name];
|
||||
fs.stat(path.normalize(path.join(plugin.package.path, ".ep_initialized")), function (err, stats) {
|
||||
if (err) {
|
||||
async.waterfall([
|
||||
function (cb) { fs.writeFile(path.normalize(path.join(plugin.package.path, ".ep_initialized")), 'done', cb); },
|
||||
function (cb) { hooks.aCallAll("init_" + plugin_name, {}, cb); },
|
||||
cb,
|
||||
]);
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
},
|
||||
function () { cb(); }
|
||||
);
|
||||
}
|
||||
|
||||
exports.update = function (cb) {
|
||||
exports.getPackages(function (er, packages) {
|
||||
var parts = [];
|
||||
|
@ -109,11 +131,12 @@ exports.update = function (cb) {
|
|||
exports.loadPlugin(packages, plugin_name, plugins, parts, cb);
|
||||
},
|
||||
function (err) {
|
||||
exports.plugins = plugins;
|
||||
if (err) cb(err);
|
||||
exports.plugins = plugins;
|
||||
exports.parts = exports.sortParts(parts);
|
||||
exports.hooks = exports.extractHooks(exports.parts, "hooks");
|
||||
exports.loaded = true;
|
||||
cb(err);
|
||||
exports.loaded = true;
|
||||
exports.callInit(cb);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -155,6 +155,9 @@ function SkipList()
|
|||
var widthLoc = point.widthSkips[0] + point.nodes[0].downSkipWidths[0];
|
||||
var newWidth = _entryWidth(entry);
|
||||
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)
|
||||
{
|
||||
var lvl = newNode.levels;
|
||||
|
|
|
@ -130,6 +130,7 @@
|
|||
|
||||
<script src="static/custom/index.js"></script>
|
||||
<script>
|
||||
document.domain = document.domain;
|
||||
function go2Name()
|
||||
{
|
||||
var padname = document.getElementById("padname").value;
|
||||
|
|
|
@ -280,6 +280,7 @@
|
|||
<script type="text/javascript" src="../javascripts/lib/ep_etherpad-lite/static/js/pad.js?callback=require.define"></script>
|
||||
<% } %>
|
||||
<script type="text/javascript">
|
||||
document.domain = document.domain;
|
||||
var clientVars = {};
|
||||
(function () {
|
||||
<% if (settings.minify) { %>
|
||||
|
|
|
@ -11,40 +11,14 @@
|
|||
<style type="text/css" title="dynamicsyntax"></style>
|
||||
</head>
|
||||
|
||||
<body id="padbody" class="timeslider limwidth nonpropad nonprouser">
|
||||
<body id="padbody" class="timeslider limwidth">
|
||||
<div id="padpage">
|
||||
<div id="padtop">
|
||||
<div class="topbar">
|
||||
<div class="topbarleft">
|
||||
<!-- -->
|
||||
</div>
|
||||
|
||||
<div class="topbarright">
|
||||
<!-- -->
|
||||
</div>
|
||||
|
||||
<div class="topbarcenter">
|
||||
<a href="/" class="topbarBrand">Etherpad v1.1</a> <a href="http://etherpad.org"
|
||||
class="EtherpadLink">Etherpad is</a> <a href="../../static/LICENSE" class=
|
||||
"Licensing">free software</a>
|
||||
|
||||
<div class="fullscreen" onclick="$('body').toggleClass('maximized');">
|
||||
Full screen
|
||||
</div><a href="javascript:void(0);" onclick=
|
||||
"$('body').toggleClass('maximized');" class="topbarmaximize" title=
|
||||
"Toggle maximization"></a>
|
||||
</div>
|
||||
|
||||
<div class="specialkeyarea">
|
||||
<!-- -->
|
||||
</div>
|
||||
</div>
|
||||
<div id="alertbar">
|
||||
<div id="servermsg">
|
||||
<h3>Server Notice<span id="servermsgdate"><!-- --></span>:</h3><a id=
|
||||
"hidetopmsg" href="javascript:%20void%20pad.hideServerMessage()" name=
|
||||
"hidetopmsg">hide</a>
|
||||
|
||||
<p id="servermsgtext"><!-- --></p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -67,104 +41,56 @@
|
|||
</table>
|
||||
</div><!-- /docbar -->
|
||||
</div>
|
||||
|
||||
<div id="timeslider-wrapper">
|
||||
<div id="error" style="display: none">
|
||||
It looks like you're having connection troubles. <a href=
|
||||
"/ep/pad/view/test/latest">Reconnect now</a>.
|
||||
|
||||
<div id="timeslider-top">
|
||||
<div id="timeslider-wrapper">
|
||||
<div id="timeslider" unselectable="on" style="display: none">
|
||||
<div id="timeslider-left"></div>
|
||||
<div id="timeslider-right"></div>
|
||||
<div id="timer"></div>
|
||||
<div id="timeslider-slider">
|
||||
<div id="ui-slider-handle"></div>
|
||||
<div id="ui-slider-bar"></div>
|
||||
</div>
|
||||
<div id="playpause_button">
|
||||
<div id="playpause_button_icon" class=""></div>
|
||||
</div>
|
||||
<div id="steppers">
|
||||
<div class="stepper" id="leftstep"></div>
|
||||
<div class="stepper" id="rightstep"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="timeslider" unselectable="on" style="display: none">
|
||||
<div id="timeslider-left"></div>
|
||||
<div class="timeslider-bar">
|
||||
<div class="editbarright toolbar" id="editbar">
|
||||
<ul>
|
||||
<li onClick="window.padeditbar.toolbarClick('import_export');return false;">
|
||||
<a id="exportlink" title="Export to different document formats">
|
||||
<div class="buttonicon buttonicon-import_export"></div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a id="returnbutton">Return to pad</a>
|
||||
</div>
|
||||
|
||||
<div id="timeslider-right"></div>
|
||||
|
||||
<div id="timer"></div>
|
||||
|
||||
<div id="timeslider-slider">
|
||||
<div id="ui-slider-handle"></div>
|
||||
|
||||
<div id="ui-slider-bar"></div>
|
||||
</div>
|
||||
|
||||
<div id="playpause_button">
|
||||
<div id="playpause_button_icon" class=""></div>
|
||||
</div>
|
||||
|
||||
<div id="steppers">
|
||||
<div class="stepper" id="leftstep"></div>
|
||||
|
||||
<div class="stepper" id="rightstep"></div>
|
||||
</div>
|
||||
<div>
|
||||
<h1>
|
||||
<span id="revision_label"></span>
|
||||
<span id="revision_date"></span>
|
||||
</h1>
|
||||
<p>Authors:
|
||||
<span id="authorsList">
|
||||
<span>No Authors</span>
|
||||
</span> </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--<div id="rightbars" style="top: 95px;">
|
||||
<div id="rightbar"><a href="/ep/pad/view/c6fg9GM51V/latest" id="viewlatest">Viewing latest content</a><br>
|
||||
<a thref="/ep/pad/view/c6fg9GM51V/rev.%revision%" href="/ep/pad/view/c6fg9GM51V/rev.0" class="tlink">Link to this version</a>
|
||||
<br><a thref="/ep/pad/view/ro.fw470Orpi4T/rev.%revision%" href="/ep/pad/view/ro.fw470Orpi4T/rev.0" class="tlink">Link to read-only page</a><br><a href="/c6fg9GM51V">Edit this pad</a>
|
||||
<h2>Download as</h2>
|
||||
<img src="../../static/img/may09/html.gif"><a thref="/ep/pad/export/c6fg9GM51V/rev.%revision%?format=html" href="/ep/pad/export/c6fg9GM51V/rev.0?format=html" class="tlink">HTML</a><br>
|
||||
<img src="../../static/img/may09/txt.gif"><a thref="/ep/pad/export/c6fg9GM51V/rev.%revision%?format=txt" href="/ep/pad/export/c6fg9GM51V/rev.0?format=txt" class="tlink">Plain text</a><br>
|
||||
<img src="../../static/img/may09/doc.gif"><a thref="/ep/pad/export/c6fg9GM51V/rev.%revision%?format=doc" href="/ep/pad/export/c6fg9GM51V/rev.0?format=doc" class="tlink">Microsoft Word</a><br>
|
||||
<img src="../../static/img/may09/pdf.gif"><a thref="/ep/pad/export/c6fg9GM51V/rev.%revision%?format=pdf" href="/ep/pad/export/c6fg9GM51V/rev.0?format=pdf" class="tlink">PDF</a>
|
||||
|
||||
|
||||
</div>
|
||||
<div id="legend">
|
||||
<h2>Authors</h2>
|
||||
<table cellspacing="0" cellpadding="0" border="0" id="authorstable"><tbody><tr><td style="color:#999; padding-left: 10px" colspan="2">No Authors</td></tr></tbody></table>
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
<div id="padmain">
|
||||
<div id="padeditor">
|
||||
<div id="editbar" class="toolbar disabledtoolbar">
|
||||
<div id="editbarinner" class="toolbarinner">
|
||||
<div id="editbarleft" class="editbarleft">
|
||||
<!-- -->
|
||||
</div>
|
||||
|
||||
<div id="editbarright" class="editbarright">
|
||||
<!-- termporary place holder-->
|
||||
<ul>
|
||||
<li onClick="window.padeditbar.toolbarClick('import_export');return false;">
|
||||
<a id="exportlink" title="Export to different document formats">
|
||||
<div class="buttonicon buttonicon-import_export"></div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a id = "returnbutton">Return to pad</a>
|
||||
</div>
|
||||
|
||||
<div id="editbarinner" class="editbarinner">
|
||||
<table cellpadding="0" cellspacing="0" border="0" id="editbartable" class=
|
||||
"editbartable">
|
||||
<tr>
|
||||
<td>
|
||||
<h1>
|
||||
<span id="revision_label"></span>
|
||||
<span id="revision_date"></span>
|
||||
</h1>
|
||||
</td>
|
||||
|
||||
<td width="100%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table cellpadding="0" cellspacing="0" border="0" id="editbarsavetable"
|
||||
class="editbarsavetable">
|
||||
<tr>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="editorcontainerbox">
|
||||
<div id="padcontent">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /padeditor -->
|
||||
|
@ -203,6 +129,7 @@
|
|||
<script type="text/javascript" src="../../../javascripts/lib/ep_etherpad-lite/static/js/timeslider.js?callback=require.define"></script>
|
||||
<script type="text/javascript" src="../../../static/custom/timeslider.js"></script>
|
||||
<script type="text/javascript" >
|
||||
document.domain = document.domain;
|
||||
var clientVars = {};
|
||||
(function () {
|
||||
require.setRootURI("../../../javascripts/src");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue