Merge pull request #2110 from ether/modularize-toolbar
Modularize toolbar
This commit is contained in:
commit
8cd9b98b76
|
@ -5,4 +5,6 @@
|
|||
@include hooks_server-side
|
||||
@include editorInfo
|
||||
@include changeset_library
|
||||
@include pluginfw
|
||||
@include pluginfw
|
||||
@include toolbar
|
||||
@include editbar
|
|
@ -0,0 +1,28 @@
|
|||
# Editbar
|
||||
srf/static/js/pad_editbar.js
|
||||
|
||||
## isEnabled()
|
||||
|
||||
## disable()
|
||||
|
||||
## toggleDropDown(dropdown, callback)
|
||||
Shows the dropdown `div.popup` whose `id` equals `dropdown`.
|
||||
|
||||
## registerCommand(cmd, callback)
|
||||
Register a handler for a specific command. Commands are fired if the corresponding button is clicked or the corresponding select is changed.
|
||||
|
||||
## registerAceCommand(cmd, callback)
|
||||
Creates an ace callstack and calls the callback with an ace instance: `callback(cmd, ace)`.
|
||||
|
||||
Example:
|
||||
```
|
||||
toolbar.registerAceCommand("insertorderedlist", function (cmd, ace) {
|
||||
ace.ace_doInsertOrderedList();
|
||||
});
|
||||
```
|
||||
|
||||
## registerDropdownCommand(cmd, dropdown)
|
||||
Ties a `div.popup` where `id` equals `dropdown` to a `command` fired by clicking a button.
|
||||
|
||||
## triggerCommand(cmd[, item])
|
||||
Triggers a command (optionally with some internal representation of the toolbar item that triggered it).
|
|
@ -63,7 +63,46 @@ Things in context:
|
|||
|
||||
This hook gets called upon the rendering of an ejs template block. For any specific kind of block, you can change how that block gets rendered by modifying the content object passed in.
|
||||
|
||||
Have a look at `src/templates/pad.html` and `src/templates/timeslider.html` to see which blocks are available.
|
||||
Available blocks in `pad.html` are:
|
||||
|
||||
* `htmlHead` - after `<html>` and immediately before the title tag
|
||||
* `styles` - the style `<link>`s
|
||||
* `body` - the contents of the body tag
|
||||
* `editbarMenuLeft` - the left tool bar (consider using the toolbar controller instead of manually adding html here)
|
||||
* `editbarMenuRight` - right tool bar
|
||||
* `afterEditbar` - allows you to add stuff immediately after the toolbar
|
||||
* `userlist` - the contents of the userlist dropdown
|
||||
* `loading` - the intial loading message
|
||||
* `mySettings` - the left column of the settings dropdown ("My view"); intended for adding checkboxes only
|
||||
* `mySettings.dropdowns` - add your dropdown settings here
|
||||
* `globalSettings` - the right column of the settings dropdown ("Global view")
|
||||
* `importColumn` - import form
|
||||
* `exportColumn` - export form
|
||||
* `modals` - Contains all connectivity messages
|
||||
* `embedPopup` - the embed dropdown
|
||||
* `scripts` - Add your script tags here, if you really have to (consider use client-side hooks instead)
|
||||
|
||||
`timeslider.html` blocks:
|
||||
|
||||
* `timesliderStyles`
|
||||
* `timesliderScripts`
|
||||
* `timesliderBody`
|
||||
* `timesliderTop`
|
||||
* `timesliderEditbarRight`
|
||||
* `modals`
|
||||
|
||||
`index.html` blocks:
|
||||
|
||||
* `indexWrapper` - contains the form for creating new pads
|
||||
|
||||
## padInitToolbar
|
||||
Called from: src/node/hooks/express/specialpages.js
|
||||
|
||||
Things in context:
|
||||
|
||||
1. toolbar - the toolbar controller that will render the toolbar eventually
|
||||
|
||||
Here you can add custom toolbar items that will be available in the toolbar config in `settings.json`. For more about the toolbar controller see the API section.
|
||||
|
||||
## padCreate
|
||||
Called from: src/node/db/Pad.js
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# Toolbar controller
|
||||
src/node/utils/toolbar.js
|
||||
|
||||
## button(opts)
|
||||
* {Object} `opts`
|
||||
* `command` - this command fill be fired on the editbar on click
|
||||
* `localizationId` - will be set as `data-l10-id`
|
||||
* `class` - here you can add additional classes to the button
|
||||
|
||||
Returns: {Button}
|
||||
|
||||
Example:
|
||||
```
|
||||
var orderedlist = toolbar.button({
|
||||
command: "insertorderedlist",
|
||||
localizationId: "pad.toolbar.ol.title",
|
||||
class: "buttonicon-insertorderedlist"
|
||||
})
|
||||
```
|
||||
|
||||
## selectButton(opts)
|
||||
* {Object} `opts`
|
||||
* `id` - id of the menu item
|
||||
* `selectId` - id of the select element
|
||||
* `command` - this command fill be fired on the editbar on change
|
||||
|
||||
Returns: {SelectButton}
|
||||
|
||||
## SelectButton.addOption(value, text, attributes)
|
||||
* {String} value - The value of this option
|
||||
* {String} text - the label text used for this option
|
||||
* {Object} attributes - any additional html attributes go here (e.g. `data-l10n-id`)
|
||||
|
||||
## registerButton(name, item)
|
||||
* {String} name - used to reference the item in the toolbar config in settings.json
|
||||
* {Button|SelectButton} item - the button to add
|
|
@ -103,6 +103,22 @@
|
|||
// restrict socket.io transport methods
|
||||
"socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"],
|
||||
|
||||
/* The toolbar buttons configuration.
|
||||
"toolbar": {
|
||||
"left": [
|
||||
["bold", "italic", "underline", "strikethrough"],
|
||||
["orderedlist", "unorderedlist", "indent", "outdent"],
|
||||
["undo", "redo"],
|
||||
["clearauthorship"]
|
||||
],
|
||||
"right": [
|
||||
["importexport", "timeslider", "savedrevision"],
|
||||
["settings", "embed"],
|
||||
["showusers"]
|
||||
]
|
||||
},
|
||||
*/
|
||||
|
||||
/* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */
|
||||
"loglevel": "INFO",
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
var path = require('path');
|
||||
var eejs = require('ep_etherpad-lite/node/eejs');
|
||||
var toolbar = require("ep_etherpad-lite/node/utils/toolbar");
|
||||
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
||||
|
||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
// expose current stats
|
||||
|
@ -30,8 +32,15 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
|||
|
||||
//serve pad.html under /p
|
||||
args.app.get('/p/:pad', function(req, res, next)
|
||||
{
|
||||
res.send(eejs.require("ep_etherpad-lite/templates/pad.html", {req: req}));
|
||||
{
|
||||
hooks.callAll("padInitToolbar", {
|
||||
toolbar: toolbar
|
||||
});
|
||||
|
||||
res.send(eejs.require("ep_etherpad-lite/templates/pad.html", {
|
||||
req: req,
|
||||
toolbar: toolbar
|
||||
}));
|
||||
});
|
||||
|
||||
//serve timeslider.html under /p/$padname/timeslider
|
||||
|
|
|
@ -79,6 +79,23 @@ exports.dbSettings = { "filename" : path.join(exports.root, "dirty.db") };
|
|||
*/
|
||||
exports.defaultPadText = "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nEtherpad on Github: http:\/\/j.mp/ep-lite\n";
|
||||
|
||||
/**
|
||||
* The toolbar buttons and order.
|
||||
*/
|
||||
exports.toolbar = {
|
||||
left: [
|
||||
["bold", "italic", "underline", "strikethrough"],
|
||||
["orderedlist", "unorderedlist", "indent", "outdent"],
|
||||
["undo", "redo"],
|
||||
["clearauthorship"]
|
||||
],
|
||||
right: [
|
||||
["importexport", "timeslider", "savedrevision"],
|
||||
["settings", "embed"],
|
||||
["showusers"]
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* A flag that requires any user to have a valid session (via the api) before accessing a pad
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
/**
|
||||
* The Toolbar Module creates and renders the toolbars and buttons
|
||||
*/
|
||||
var _ = require("underscore")
|
||||
, tagAttributes
|
||||
, tag
|
||||
, defaultButtons
|
||||
, Button
|
||||
, ButtonsGroup
|
||||
, Separator
|
||||
, defaultButtonAttributes;
|
||||
|
||||
defaultButtonAttributes = function (name, overrides) {
|
||||
return {
|
||||
command: name,
|
||||
localizationId: "pad.toolbar." + name + ".title",
|
||||
class: "buttonicon-" + name
|
||||
};
|
||||
};
|
||||
|
||||
tag = function (name, attributes, contents) {
|
||||
var aStr = tagAttributes(attributes);
|
||||
|
||||
if (_.isString(contents) && contents.length > 0) {
|
||||
return '<' + name + aStr + '>' + contents + '</' + name + '>';
|
||||
}
|
||||
else {
|
||||
return '<' + name + aStr + '></' + name + '>';
|
||||
}
|
||||
};
|
||||
|
||||
tagAttributes = function (attributes) {
|
||||
attributes = _.reduce(attributes || {}, function (o, val, name) {
|
||||
if (!_.isUndefined(val)) {
|
||||
o[name] = val;
|
||||
}
|
||||
return o;
|
||||
}, {});
|
||||
|
||||
return " " + _.map(attributes, function (val, name) {
|
||||
return "" + name + '="' + _.escape(val) + '"';
|
||||
}).join(" ");
|
||||
};
|
||||
|
||||
ButtonsGroup = function () {
|
||||
this.buttons = [];
|
||||
};
|
||||
|
||||
ButtonsGroup.fromArray = function (array) {
|
||||
var btnGroup = new this;
|
||||
_.each(array, function (btnName) {
|
||||
btnGroup.addButton(Button.load(btnName));
|
||||
});
|
||||
return btnGroup;
|
||||
};
|
||||
|
||||
ButtonsGroup.prototype.addButton = function (button) {
|
||||
this.buttons.push(button);
|
||||
return this;
|
||||
};
|
||||
|
||||
ButtonsGroup.prototype.render = function () {
|
||||
if (this.buttons.length == 1) {
|
||||
this.buttons[0].grouping = "";
|
||||
}
|
||||
else {
|
||||
_.first(this.buttons).grouping = "grouped-left";
|
||||
_.last(this.buttons).grouping = "grouped-right";
|
||||
_.each(this.buttons.slice(1, -1), function (btn) {
|
||||
btn.grouping = "grouped-middle"
|
||||
});
|
||||
}
|
||||
|
||||
return _.map(this.buttons, function (btn) {
|
||||
return btn.render();
|
||||
}).join("\n");
|
||||
};
|
||||
|
||||
Button = function (attributes) {
|
||||
this.attributes = attributes;
|
||||
};
|
||||
|
||||
Button.load = function (btnName) {
|
||||
var button = module.exports.availableButtons[btnName];
|
||||
if (button.constructor === Button || button.constructor === SelectButton) {
|
||||
return button;
|
||||
}
|
||||
else {
|
||||
return new Button(button);
|
||||
}
|
||||
};
|
||||
|
||||
_.extend(Button.prototype, {
|
||||
grouping: "",
|
||||
|
||||
render: function () {
|
||||
var liAttributes = {
|
||||
"data-type": "button",
|
||||
"data-key": this.attributes.command,
|
||||
};
|
||||
return tag("li", liAttributes,
|
||||
tag("a", { "class": this.grouping, "data-l10n-id": this.attributes.localizationId },
|
||||
tag("span", { "class": "buttonicon " + this.attributes.class })
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
SelectButton = function (attributes) {
|
||||
this.attributes = attributes;
|
||||
this.options = [];
|
||||
};
|
||||
|
||||
_.extend(SelectButton.prototype, Button.prototype, {
|
||||
addOption: function (value, text, attributes) {
|
||||
this.options.push({
|
||||
value: value,
|
||||
text: text,
|
||||
attributes: attributes
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
select: function (attributes) {
|
||||
var self = this
|
||||
, options = [];
|
||||
|
||||
_.each(this.options, function (opt) {
|
||||
var a = _.extend({
|
||||
value: opt.value
|
||||
}, opt.attributes);
|
||||
|
||||
options.push( tag("option", a, opt.text) );
|
||||
});
|
||||
return tag("select", attributes, options.join(""));
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var attributes = {
|
||||
id: this.attributes.id,
|
||||
"data-key": this.attributes.command,
|
||||
"data-type": "select"
|
||||
};
|
||||
return tag("li", attributes,
|
||||
this.select({ id: this.attributes.selectId })
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Separator = function () {};
|
||||
Separator.prototype.render = function () {
|
||||
return tag("li", { "class": "separator" });
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
availableButtons: {
|
||||
bold: defaultButtonAttributes("bold"),
|
||||
italic: defaultButtonAttributes("italic"),
|
||||
underline: defaultButtonAttributes("underline"),
|
||||
strikethrough: defaultButtonAttributes("strikethrough"),
|
||||
|
||||
orderedlist: {
|
||||
command: "insertorderedlist",
|
||||
localizationId: "pad.toolbar.ol.title",
|
||||
class: "buttonicon-insertorderedlist"
|
||||
},
|
||||
|
||||
unorderedlist: {
|
||||
command: "insertunorderedlist",
|
||||
localizationId: "pad.toolbar.ul.title",
|
||||
class: "buttonicon-insertunorderedlist"
|
||||
},
|
||||
|
||||
indent: defaultButtonAttributes("indent"),
|
||||
outdent: {
|
||||
command: "outdent",
|
||||
localizationId: "pad.toolbar.unindent.title",
|
||||
class: "buttonicon-outdent"
|
||||
},
|
||||
|
||||
undo: defaultButtonAttributes("undo"),
|
||||
redo: defaultButtonAttributes("redo"),
|
||||
|
||||
clearauthorship: {
|
||||
command: "clearauthorship",
|
||||
localizationId: "pad.toolbar.clearAuthorship.title",
|
||||
class: "buttonicon-clearauthorship"
|
||||
},
|
||||
|
||||
importexport: {
|
||||
command: "import_export",
|
||||
localizationId: "pad.toolbar.import_export.title",
|
||||
class: "buttonicon-import_export"
|
||||
},
|
||||
|
||||
timeslider: {
|
||||
command: "showTimeSlider",
|
||||
localizationId: "pad.toolbar.timeslider.title",
|
||||
class: "buttonicon-history"
|
||||
},
|
||||
|
||||
savedrevision: defaultButtonAttributes("savedRevision"),
|
||||
settings: defaultButtonAttributes("settings"),
|
||||
embed: defaultButtonAttributes("embed"),
|
||||
showusers: defaultButtonAttributes("showusers")
|
||||
},
|
||||
|
||||
registerButton: function (buttonName, buttonInfo) {
|
||||
this.availableButtons[buttonName] = buttonInfo;
|
||||
},
|
||||
|
||||
button: function (attributes) {
|
||||
return new Button(attributes);
|
||||
},
|
||||
separator: function () {
|
||||
return (new Separator).render();
|
||||
},
|
||||
selectButton: function (attributes) {
|
||||
return new SelectButton(attributes);
|
||||
},
|
||||
menu: function (buttons) {
|
||||
var groups = _.map(buttons, function (group) {
|
||||
return ButtonsGroup.fromArray(group).render();
|
||||
});
|
||||
return groups.join(this.separator());
|
||||
}
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
@ -20,18 +20,60 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var hooks = require('./pluginfw/hooks');
|
||||
var padutils = require('./pad_utils').padutils;
|
||||
var padeditor = require('./pad_editor').padeditor;
|
||||
var padsavedrevs = require('./pad_savedrevs');
|
||||
|
||||
function indexOf(array, value) {
|
||||
for (var i = 0, ii = array.length; i < ii; i++) {
|
||||
if (array[i] == value) {
|
||||
return i;
|
||||
}
|
||||
var ToolbarItem = function (element) {
|
||||
this.$el = element;
|
||||
};
|
||||
|
||||
ToolbarItem.prototype.getCommand = function () {
|
||||
return this.$el.attr("data-key");
|
||||
};
|
||||
|
||||
ToolbarItem.prototype.getValue = function () {
|
||||
if (this.isSelect()) {
|
||||
return this.$el.find("select").val();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
ToolbarItem.prototype.setValue = function (val) {
|
||||
if (this.isSelect()) {
|
||||
return this.$el.find("select").val(val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ToolbarItem.prototype.getType = function () {
|
||||
return this.$el.attr("data-type");
|
||||
};
|
||||
|
||||
ToolbarItem.prototype.isSelect = function () {
|
||||
return this.getType() == "select";
|
||||
};
|
||||
|
||||
ToolbarItem.prototype.isButton = function () {
|
||||
return this.getType() == "button";
|
||||
};
|
||||
|
||||
ToolbarItem.prototype.bind = function (callback) {
|
||||
var self = this;
|
||||
|
||||
if (self.isButton()) {
|
||||
self.$el.click(function (event) {
|
||||
callback(self.getCommand(), self);
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
else if (self.isSelect()) {
|
||||
self.$el.find("select").change(function () {
|
||||
callback(self.getCommand(), self);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var padeditbar = (function()
|
||||
{
|
||||
|
@ -95,17 +137,24 @@ var padeditbar = (function()
|
|||
}());
|
||||
|
||||
var self = {
|
||||
init: function()
|
||||
{
|
||||
init: function() {
|
||||
var self = this;
|
||||
self.dropdowns = [];
|
||||
|
||||
$("#editbar .editbarbutton").attr("unselectable", "on"); // for IE
|
||||
$("#editbar").removeClass("disabledtoolbar").addClass("enabledtoolbar");
|
||||
$("#editbar [data-key]").each(function (i, e) {
|
||||
$(e).click(function (event) {
|
||||
self.toolbarClick($(e).attr('data-key'));
|
||||
event.preventDefault();
|
||||
$("#editbar [data-key]").each(function () {
|
||||
(new ToolbarItem($(this))).bind(function (command, item) {
|
||||
self.triggerCommand(command, item);
|
||||
});
|
||||
});
|
||||
|
||||
registerDefaultCommands(self);
|
||||
|
||||
hooks.callAll("postToolbarInit", {
|
||||
toolbar: self,
|
||||
ace: padeditor.ace
|
||||
});
|
||||
},
|
||||
isEnabled: function()
|
||||
{
|
||||
|
@ -116,89 +165,45 @@ var padeditbar = (function()
|
|||
{
|
||||
$("#editbar").addClass('disabledtoolbar').removeClass("enabledtoolbar");
|
||||
},
|
||||
toolbarClick: function(cmd)
|
||||
{
|
||||
if (self.isEnabled())
|
||||
{
|
||||
if(cmd == "showusers")
|
||||
{
|
||||
self.toggleDropDown("users");
|
||||
}
|
||||
else if (cmd == 'settings')
|
||||
{
|
||||
self.toggleDropDown("settings");
|
||||
}
|
||||
else if (cmd == 'connectivity')
|
||||
{
|
||||
self.toggleDropDown("connectivity");
|
||||
}
|
||||
else if (cmd == 'embed')
|
||||
{
|
||||
self.setEmbedLinks();
|
||||
$('#linkinput').focus().select();
|
||||
self.toggleDropDown("embed");
|
||||
}
|
||||
else if (cmd == 'import_export')
|
||||
{
|
||||
self.toggleDropDown("importexport");
|
||||
}
|
||||
else if (cmd == 'savedRevision')
|
||||
{
|
||||
padsavedrevs.saveNow();
|
||||
}
|
||||
else
|
||||
{
|
||||
padeditor.ace.callWithAce(function(ace)
|
||||
{
|
||||
if (cmd == 'bold' || cmd == 'italic' || cmd == 'underline' || cmd == 'strikethrough') ace.ace_toggleAttributeOnSelection(cmd);
|
||||
else if (cmd == 'undo' || cmd == 'redo') ace.ace_doUndoRedo(cmd);
|
||||
else if (cmd == 'insertunorderedlist') ace.ace_doInsertUnorderedList();
|
||||
else if (cmd == 'insertorderedlist') ace.ace_doInsertOrderedList();
|
||||
else if (cmd == 'indent')
|
||||
{
|
||||
ace.ace_doIndentOutdent(false);
|
||||
}
|
||||
else if (cmd == 'outdent')
|
||||
{
|
||||
ace.ace_doIndentOutdent(true);
|
||||
}
|
||||
else if (cmd == 'clearauthorship')
|
||||
{
|
||||
if ((!(ace.ace_getRep().selStart && ace.ace_getRep().selEnd)) || ace.ace_isCaret())
|
||||
{
|
||||
if (window.confirm(html10n.get("pad.editbar.clearcolors")))
|
||||
{
|
||||
ace.ace_performDocumentApplyAttributesToCharRange(0, ace.ace_getRep().alltext.length, [
|
||||
['author', '']
|
||||
]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ace.ace_setAttributeOnSelection('author', '');
|
||||
}
|
||||
}
|
||||
}, cmd, true);
|
||||
}
|
||||
commands: {},
|
||||
registerCommand: function (cmd, callback) {
|
||||
this.commands[cmd] = callback;
|
||||
return this;
|
||||
},
|
||||
registerDropdownCommand: function (cmd, dropdown) {
|
||||
dropdown = dropdown || cmd;
|
||||
self.dropdowns.push(dropdown)
|
||||
this.registerCommand(cmd, function () {
|
||||
self.toggleDropDown(dropdown);
|
||||
});
|
||||
},
|
||||
registerAceCommand: function (cmd, callback) {
|
||||
this.registerCommand(cmd, function (cmd, ace) {
|
||||
ace.callWithAce(function (ace) {
|
||||
callback(cmd, ace);
|
||||
}, cmd, true);
|
||||
});
|
||||
},
|
||||
triggerCommand: function (cmd, item) {
|
||||
if (self.isEnabled() && this.commands[cmd]) {
|
||||
this.commands[cmd](cmd, padeditor.ace, item);
|
||||
}
|
||||
if(padeditor.ace) padeditor.ace.focus();
|
||||
},
|
||||
toggleDropDown: function(moduleName, cb)
|
||||
{
|
||||
var modules = ["settings", "connectivity", "importexport", "embed", "users"];
|
||||
|
||||
// hide all modules and remove highlighting of all buttons
|
||||
if(moduleName == "none")
|
||||
{
|
||||
var returned = false
|
||||
for(var i=0;i<modules.length;i++)
|
||||
for(var i=0;i<self.dropdowns.length;i++)
|
||||
{
|
||||
//skip the userlist
|
||||
if(modules[i] == "users")
|
||||
if(self.dropdowns[i] == "users")
|
||||
continue;
|
||||
|
||||
var module = $("#" + modules[i]);
|
||||
|
||||
|
||||
var module = $("#" + self.dropdowns[i]);
|
||||
|
||||
if(module.css('display') != "none")
|
||||
{
|
||||
$("#" + modules[i] + "link").removeClass("selected");
|
||||
|
@ -208,22 +213,22 @@ var padeditbar = (function()
|
|||
}
|
||||
if(!returned && cb) return cb();
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
// hide all modules that are not selected and remove highlighting
|
||||
// respectively add highlighting to the corresponding button
|
||||
for(var i=0;i<modules.length;i++)
|
||||
for(var i=0;i<self.dropdowns.length;i++)
|
||||
{
|
||||
var module = $("#" + modules[i]);
|
||||
|
||||
var module = $("#" + self.dropdowns[i]);
|
||||
|
||||
if(module.css('display') != "none")
|
||||
{
|
||||
$("#" + modules[i] + "link").removeClass("selected");
|
||||
$("#" + self.dropdowns[i] + "link").removeClass("selected");
|
||||
module.slideUp("fast");
|
||||
}
|
||||
else if(modules[i]==moduleName)
|
||||
else if(self.dropdowns[i]==moduleName)
|
||||
{
|
||||
$("#" + modules[i] + "link").addClass("selected");
|
||||
$("#" + self.dropdowns[i] + "link").addClass("selected");
|
||||
module.slideDown("fast", cb);
|
||||
}
|
||||
}
|
||||
|
@ -257,6 +262,77 @@ var padeditbar = (function()
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
function aceAttributeCommand(cmd, ace) {
|
||||
ace.ace_toggleAttributeOnSelection(cmd);
|
||||
}
|
||||
|
||||
function registerDefaultCommands(toolbar) {
|
||||
toolbar.registerDropdownCommand("showusers", "users");
|
||||
toolbar.registerDropdownCommand("settings");
|
||||
toolbar.registerDropdownCommand("connectivity");
|
||||
toolbar.registerDropdownCommand("import_export", "importexport");
|
||||
toolbar.registerDropdownCommand("embed");
|
||||
|
||||
toolbar.registerCommand("embed", function () {
|
||||
toolbar.setEmbedLinks();
|
||||
$('#linkinput').focus().select();
|
||||
toolbar.toggleDropDown("embed");
|
||||
});
|
||||
|
||||
toolbar.registerCommand("savedRevision", function () {
|
||||
padsavedrevs.saveNow();
|
||||
});
|
||||
|
||||
toolbar.registerCommand("showTimeSlider", function () {
|
||||
document.location = document.location + "/timeslider";
|
||||
});
|
||||
|
||||
toolbar.registerAceCommand("bold", aceAttributeCommand);
|
||||
toolbar.registerAceCommand("italic", aceAttributeCommand);
|
||||
toolbar.registerAceCommand("underline", aceAttributeCommand);
|
||||
toolbar.registerAceCommand("strikethrough", aceAttributeCommand);
|
||||
|
||||
toolbar.registerAceCommand("undo", function (cmd, ace) {
|
||||
ace.ace_doUndoRedo(cmd);
|
||||
});
|
||||
|
||||
toolbar.registerAceCommand("redo", function (cmd) {
|
||||
ace.ace_doUndoRedo(cmd);
|
||||
});
|
||||
|
||||
toolbar.registerAceCommand("insertunorderedlist", function (cmd, ace) {
|
||||
ace.ace_doInsertUnorderedList();
|
||||
});
|
||||
|
||||
toolbar.registerAceCommand("insertorderedlist", function (cmd, ace) {
|
||||
ace.ace_doInsertOrderedList();
|
||||
});
|
||||
|
||||
toolbar.registerAceCommand("indent", function (cmd, ace) {
|
||||
if (!ace.ace_doIndentOutdent(false)) {
|
||||
ace.ace_doInsertUnorderedList();
|
||||
}
|
||||
});
|
||||
|
||||
toolbar.registerAceCommand("outdent", function (cmd, ace) {
|
||||
ace.ace_doIndentOutdent(true);
|
||||
});
|
||||
|
||||
toolbar.registerAceCommand("clearauthorship", function (cmd, ace) {
|
||||
if ((!(ace.ace_getRep().selStart && ace.ace_getRep().selEnd)) || ace.ace_isCaret()) {
|
||||
if (window.confirm(html10n.get("pad.editbar.clearcolors"))) {
|
||||
ace.ace_performDocumentApplyAttributesToCharRange(0, ace.ace_getRep().alltext.length, [
|
||||
['author', '']
|
||||
]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ace.ace_setAttributeOnSelection('author', '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return self;
|
||||
}());
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<%
|
||||
var settings = require("ep_etherpad-lite/node/utils/Settings")
|
||||
, hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks')
|
||||
, langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs
|
||||
;
|
||||
%>
|
||||
<!doctype html>
|
||||
<% e.begin_block("htmlHead"); %>
|
||||
|
@ -54,103 +56,15 @@
|
|||
<div id="overlay">
|
||||
<div id="overlay-inner"></div>
|
||||
</div>
|
||||
|
||||
<ul class="menu_left">
|
||||
<% e.begin_block("editbarMenuLeft"); %>
|
||||
<li class="acl-write" id="bold" data-key="bold">
|
||||
<a class="grouped-left" data-l10n-id="pad.toolbar.bold.title">
|
||||
<span class="buttonicon buttonicon-bold"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write" id="italic" data-key="italic">
|
||||
<a class="grouped-middle" data-l10n-id="pad.toolbar.italic.title">
|
||||
<span class="buttonicon buttonicon-italic"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write" id="underline" data-key="underline">
|
||||
<a class="grouped-middle" data-l10n-id="pad.toolbar.underline.title">
|
||||
<span class="buttonicon buttonicon-underline"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write" id="strikethrough" data-key="strikethrough">
|
||||
<a class="grouped-right" data-l10n-id="pad.toolbar.strikethrough.title">
|
||||
<span class="buttonicon buttonicon-strikethrough"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write separator"></li>
|
||||
<li class="acl-write" id="oderedlist" data-key="insertorderedlist">
|
||||
<a class="grouped-left" data-l10n-id="pad.toolbar.ol.title">
|
||||
<span class="buttonicon buttonicon-insertorderedlist"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write" id="unoderedlist" data-key="insertunorderedlist">
|
||||
<a class="grouped-middle" data-l10n-id="pad.toolbar.ul.title">
|
||||
<span class="buttonicon buttonicon-insertunorderedlist"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write" id="indent" data-key="indent">
|
||||
<a class="grouped-middle" data-l10n-id="pad.toolbar.indent.title">
|
||||
<span class="buttonicon buttonicon-indent"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write" id="outdent" data-key="outdent">
|
||||
<a class="grouped-right" data-l10n-id="pad.toolbar.unindent.title">
|
||||
<span class="buttonicon buttonicon-outdent"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write separator"></li>
|
||||
<li class="acl-write" id="undo" data-key="undo">
|
||||
<a class="grouped-left" data-l10n-id="pad.toolbar.undo.title">
|
||||
<span class="buttonicon buttonicon-undo"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write" id="redo" data-key="redo">
|
||||
<a class="grouped-right" data-l10n-id="pad.toolbar.redo.title">
|
||||
<span class="buttonicon buttonicon-redo"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write separator"></li>
|
||||
<li class="acl-write" id="clearAuthorship" data-key="clearauthorship">
|
||||
<a data-l10n-id="pad.toolbar.clearAuthorship.title">
|
||||
<span class="buttonicon buttonicon-clearauthorship"></span>
|
||||
</a>
|
||||
</li>
|
||||
<%- toolbar.menu(settings.toolbar.left) %>
|
||||
<% e.end_block(); %>
|
||||
</ul>
|
||||
<ul class="menu_right">
|
||||
<% e.begin_block("editbarMenuRight"); %>
|
||||
<li data-key="import_export">
|
||||
<a class="grouped-left" id="importexportlink" data-l10n-id="pad.toolbar.import_export.title">
|
||||
<span class="buttonicon buttonicon-import_export"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="document.location = document.location.pathname+ '/timeslider'">
|
||||
<a id="timesliderlink" class="grouped-middle" data-l10n-id="pad.toolbar.timeslider.title">
|
||||
<span class="buttonicon buttonicon-history"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write" data-key="savedRevision">
|
||||
<a class="grouped-right" id="revisionlink" data-l10n-id="pad.toolbar.savedRevision.title">
|
||||
<span class="buttonicon buttonicon-savedRevision"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="acl-write separator"></li>
|
||||
<li class="acl-write" data-key="settings">
|
||||
<a class="grouped-left" id="settingslink" data-l10n-id="pad.toolbar.settings.title">
|
||||
<span class="buttonicon buttonicon-settings"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li data-key="embed">
|
||||
<a class="grouped-right" id="embedlink" data-l10n-id="pad.toolbar.embed.title">
|
||||
<span class="grouped-right buttonicon buttonicon-embed"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="separator"></li>
|
||||
<li id="usericon" data-key="showusers">
|
||||
<a data-l10n-id="pad.toolbar.showusers.title">
|
||||
<span class="buttonicon buttonicon-showusers"></span>
|
||||
<span id="online_count">1</span>
|
||||
</a>
|
||||
</li>
|
||||
<%- toolbar.menu(settings.toolbar.right) %>
|
||||
<% e.end_block(); %>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -295,7 +209,7 @@
|
|||
<% e.end_block(); %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="connectivity" class="popup">
|
||||
<% e.begin_block("modals"); %>
|
||||
<div class="connected visible">
|
||||
|
@ -411,7 +325,7 @@
|
|||
<% e.begin_block("scripts"); %>
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
// Display errors on page load to the user
|
||||
// Display errors on page load to the user
|
||||
// (Gets overridden by padutils.setupGlobalExceptionHandler)
|
||||
var originalHandler = window.onerror;
|
||||
window.onerror = function(msg, url, line) {
|
||||
|
@ -424,7 +338,7 @@
|
|||
};
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" src="../static/js/require-kernel.js"></script>
|
||||
<script type="text/javascript" src="../socket.io/socket.io.js"></script>
|
||||
|
||||
|
@ -439,10 +353,10 @@
|
|||
var clientVars = {};
|
||||
(function () {
|
||||
var pathComponents = location.pathname.split('/');
|
||||
|
||||
|
||||
// Strip 'p' and the padname from the pathname and set as baseURL
|
||||
var baseURL = pathComponents.slice(0,pathComponents.length-2).join('/') + '/';
|
||||
|
||||
|
||||
require.setRootURI(baseURL + "javascripts/src");
|
||||
require.setLibraryURI(baseURL + "javascripts/lib");
|
||||
require.setGlobalKeyPath("require");
|
||||
|
|
Loading…
Reference in New Issue