mirror of
https://github.com/sparksuite/simplemde-markdown-editor.git
synced 2024-06-14 11:45:25 +02:00
Refactor custom status bar items
This commit is contained in:
parent
a318e44ffe
commit
6b6bb408cf
25
README.md
25
README.md
|
@ -100,7 +100,7 @@ simplemde.value("This text will appear in the editor");
|
||||||
- **spellChecker**: If set to `false`, disable the spell checker. Defaults to `true`.
|
- **spellChecker**: If set to `false`, disable the spell checker. Defaults to `true`.
|
||||||
- **status**: If set to `false`, hide the status bar. Defaults to `true`.
|
- **status**: If set to `false`, hide the status bar. Defaults to `true`.
|
||||||
- Optionally, you can set an array of status bar elements to include, and in what order.
|
- Optionally, you can set an array of status bar elements to include, and in what order.
|
||||||
- **statusCustom**: An object of custom elements to add to the statusbar
|
- **statusCustom**: An object of custom elements to add to the status bar.
|
||||||
- **tabSize**: If set, customize the tab size. Defaults to `2`.
|
- **tabSize**: If set, customize the tab size. Defaults to `2`.
|
||||||
- **toolbar**: If set to `false`, hide the toolbar. Defaults to the [array of icons](#toolbar-icons).
|
- **toolbar**: If set to `false`, hide the toolbar. Defaults to the [array of icons](#toolbar-icons).
|
||||||
- **toolbarTips**: If set to `false`, disable toolbar button tips. Defaults to `true`.
|
- **toolbarTips**: If set to `false`, disable toolbar button tips. Defaults to `true`.
|
||||||
|
@ -156,17 +156,16 @@ var simplemde = new SimpleMDE({
|
||||||
spellChecker: false,
|
spellChecker: false,
|
||||||
status: false,
|
status: false,
|
||||||
status: ["autosave", "lines", "words", "cursor"], // Optional usage
|
status: ["autosave", "lines", "words", "cursor"], // Optional usage
|
||||||
statusCustom: {
|
status: ["autosave", "lines", "words", "cursor", {
|
||||||
countKeyStrokes: { // Counts the total number of keystrokes
|
className: "keystrokes",
|
||||||
defaultValue: function(span) {
|
defaultValue: function(el) {
|
||||||
this.keystrokes = 0;
|
this.keystrokes = 0;
|
||||||
span.innerHTML = "0 Keystrokes";
|
el.innerHTML = "0 Keystrokes";
|
||||||
},
|
},
|
||||||
onUpdate: function(span) {
|
onUpdate: function(el) {
|
||||||
span.innerHTML = ++this.keystrokes + " Keystrokes";
|
el.innerHTML = ++this.keystrokes + " Keystrokes";
|
||||||
}
|
}
|
||||||
}
|
}], // Another optional usage, with a custom status item that counts keystrokes
|
||||||
},
|
|
||||||
tabSize: 4,
|
tabSize: 4,
|
||||||
toolbar: false,
|
toolbar: false,
|
||||||
toolbarTips: false,
|
toolbarTips: false,
|
||||||
|
@ -175,7 +174,7 @@ var simplemde = new SimpleMDE({
|
||||||
|
|
||||||
#### Toolbar icons
|
#### Toolbar icons
|
||||||
|
|
||||||
Below are the built-in toolbar icons (only some of which are enabled by default), which can be reorganized however you like. "Name" is the name of the icon, referenced in the JS. "Action" is either a function or a URL to open. "Class" is the class given to the icon. "Tooltip" is the small tooltip that appears via the `title=""` attribute. Note that shortcut hints are added automatically and reflect the specified "action" if it has a keybind assigned to it (ie. with the value of "action" set to `bold` and that of "tootip" set to "Bold", the final text the user will see - assuming the default shortcuts are unchanged - would be "Bold (Ctrl-B)").
|
Below are the built-in toolbar icons (only some of which are enabled by default), which can be reorganized however you like. "Name" is the name of the icon, referenced in the JS. "Action" is either a function or a URL to open. "Class" is the class given to the icon. "Tooltip" is the small tooltip that appears via the `title=""` attribute. Note that shortcut hints are added automatically and reflect the specified action if it has a keybind assigned to it (i.e. with the value of `action` set to `bold` and that of `tooltip` set to `Bold`, the final text the user will see would be "Bold (Ctrl-B)").
|
||||||
|
|
||||||
Additionally, you can add a separator between any icons by adding `"|"` to the toolbar array.
|
Additionally, you can add a separator between any icons by adding `"|"` to the toolbar array.
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -13884,9 +13884,6 @@ function SimpleMDE(options) {
|
||||||
if(!options.hasOwnProperty("status")) {
|
if(!options.hasOwnProperty("status")) {
|
||||||
options.status = ["autosave", "lines", "words", "cursor"];
|
options.status = ["autosave", "lines", "words", "cursor"];
|
||||||
}
|
}
|
||||||
if(!options.hasOwnProperty("statusCustom")) {
|
|
||||||
options.statusCustom = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Add default preview rendering function
|
// Add default preview rendering function
|
||||||
|
@ -14040,7 +14037,7 @@ SimpleMDE.prototype.render = function(el) {
|
||||||
if(options.toolbar !== false) {
|
if(options.toolbar !== false) {
|
||||||
this.createToolbar();
|
this.createToolbar();
|
||||||
}
|
}
|
||||||
if(options.status !== false || options.statusCustom) {
|
if(options.status !== false) {
|
||||||
this.createStatusbar();
|
this.createStatusbar();
|
||||||
}
|
}
|
||||||
if(options.autosave != undefined && options.autosave.enabled === true) {
|
if(options.autosave != undefined && options.autosave.enabled === true) {
|
||||||
|
@ -14240,97 +14237,118 @@ SimpleMDE.prototype.createToolbar = function(items) {
|
||||||
};
|
};
|
||||||
|
|
||||||
SimpleMDE.prototype.createStatusbar = function(status) {
|
SimpleMDE.prototype.createStatusbar = function(status) {
|
||||||
var customOptions = this.options.statusCustom;
|
// Initialize
|
||||||
status = status || this.options.status;
|
status = status || this.options.status;
|
||||||
var options = this.options;
|
var options = this.options;
|
||||||
|
var cm = this.codemirror;
|
||||||
|
|
||||||
if(!status || status.length === 0) return;
|
|
||||||
|
|
||||||
// Copy the defaults if the status is a boolean true
|
// Make sure the status variable is valid
|
||||||
if(status === true) status = ["autosave", "lines", "words", "cursor"];
|
if(!status || status.length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
// Set up the built-in items
|
||||||
|
var items = [];
|
||||||
|
var i, onUpdate, defaultValue;
|
||||||
|
|
||||||
// Set up the in-built actions: autosave, lines, words, cursor
|
|
||||||
var actions = {};
|
|
||||||
var i, name, onUpdate, defaultValue;
|
|
||||||
for(i = 0; i < status.length; i++) {
|
for(i = 0; i < status.length; i++) {
|
||||||
name = status[i];
|
// Reset some values
|
||||||
|
onUpdate = undefined;
|
||||||
|
defaultValue = undefined;
|
||||||
|
|
||||||
if(name === "words") {
|
|
||||||
defaultValue = function(el) {
|
|
||||||
el.innerHTML = "0";
|
|
||||||
};
|
|
||||||
onUpdate = function(el) {
|
|
||||||
el.innerHTML = wordCount(cm.getValue());
|
|
||||||
};
|
|
||||||
} else if(name === "lines") {
|
|
||||||
defaultValue = function(el) {
|
|
||||||
el.innerHTML = "0";
|
|
||||||
};
|
|
||||||
onUpdate = function(el) {
|
|
||||||
el.innerHTML = cm.lineCount();
|
|
||||||
};
|
|
||||||
} else if(name === "cursor") {
|
|
||||||
defaultValue = function(el) {
|
|
||||||
el.innerHTML = "0:0";
|
|
||||||
};
|
|
||||||
onUpdate = function(el) {
|
|
||||||
pos = cm.getCursor();
|
|
||||||
el.innerHTML = pos.line + ":" + pos.ch;
|
|
||||||
};
|
|
||||||
} else if(name === "autosave") {
|
|
||||||
defaultValue = function(el) {
|
|
||||||
if(options.autosave != undefined && options.autosave.enabled === true) {
|
|
||||||
el.setAttribute("id", "autosaved");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
actions[name] = {
|
|
||||||
onUpdate: onUpdate,
|
|
||||||
defaultValue: defaultValue
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate any user-provided options
|
// Handle if custom or not
|
||||||
for(var key in customOptions) {
|
if(typeof status[i] === "object") {
|
||||||
if(customOptions.hasOwnProperty(key)) {
|
items.push({
|
||||||
var thisOption = customOptions[key];
|
className: status[i].className,
|
||||||
|
defaultValue: status[i].defaultValue,
|
||||||
|
onUpdate: status[i].onUpdate
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var name = status[i];
|
||||||
|
|
||||||
// Copy the option into the combined actions
|
if(name === "words") {
|
||||||
// This will allow the user to override the defaults
|
defaultValue = function(el) {
|
||||||
actions[key] = {
|
el.innerHTML = "0";
|
||||||
defaultValue: thisOption.defaultValue,
|
};
|
||||||
onUpdate: thisOption.onUpdate
|
onUpdate = function(el) {
|
||||||
};
|
el.innerHTML = wordCount(cm.getValue());
|
||||||
|
};
|
||||||
|
} else if(name === "lines") {
|
||||||
|
defaultValue = function(el) {
|
||||||
|
el.innerHTML = "0";
|
||||||
|
};
|
||||||
|
onUpdate = function(el) {
|
||||||
|
el.innerHTML = cm.lineCount();
|
||||||
|
};
|
||||||
|
} else if(name === "cursor") {
|
||||||
|
defaultValue = function(el) {
|
||||||
|
el.innerHTML = "0:0";
|
||||||
|
};
|
||||||
|
onUpdate = function(el) {
|
||||||
|
var pos = cm.getCursor();
|
||||||
|
el.innerHTML = pos.line + ":" + pos.ch;
|
||||||
|
};
|
||||||
|
} else if(name === "autosave") {
|
||||||
|
defaultValue = function(el) {
|
||||||
|
if(options.autosave != undefined && options.autosave.enabled === true) {
|
||||||
|
el.setAttribute("id", "autosaved");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
items.push({
|
||||||
|
className: name,
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
onUpdate: onUpdate
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create element for the status bar
|
||||||
var bar = document.createElement("div");
|
var bar = document.createElement("div");
|
||||||
bar.className = "editor-statusbar";
|
bar.className = "editor-statusbar";
|
||||||
|
|
||||||
var pos, cm = this.codemirror;
|
|
||||||
// Create a new span for each action
|
// Create a new span for each item
|
||||||
for(name in actions) {
|
for(i = 0; i < items.length; i++) {
|
||||||
if(actions.hasOwnProperty(name)) {
|
// Store in temporary variable
|
||||||
var el = document.createElement("span");
|
var item = items[i];
|
||||||
el.className = name;
|
|
||||||
// Ensure the defaultValue is a function
|
|
||||||
if(typeof actions[name].defaultValue === "function") {
|
// Create span element
|
||||||
actions[name].defaultValue(el);
|
var el = document.createElement("span");
|
||||||
}
|
el.className = item.className;
|
||||||
// Ensure the onUpdate is a function
|
|
||||||
if(typeof actions[name].onUpdate === "function") {
|
|
||||||
// Create a closure around the span and the name
|
// Ensure the defaultValue is a function
|
||||||
// of the current action, then execute the onUpdate handler
|
if(typeof item.defaultValue === "function") {
|
||||||
cm.on("update", (function(el, name) {
|
item.defaultValue(el);
|
||||||
return function() {
|
|
||||||
actions[name].onUpdate(el);
|
|
||||||
};
|
|
||||||
}(el, name)));
|
|
||||||
}
|
|
||||||
bar.appendChild(el);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Ensure the onUpdate is a function
|
||||||
|
if(typeof item.onUpdate === "function") {
|
||||||
|
// Create a closure around the span of the current action, then execute the onUpdate handler
|
||||||
|
this.codemirror.on("update", (function(el, item) {
|
||||||
|
console.log(el);
|
||||||
|
console.log(item);
|
||||||
|
console.log("---------------");
|
||||||
|
return function() {
|
||||||
|
item.onUpdate(el);
|
||||||
|
};
|
||||||
|
}(el, item)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Append the item to the status bar
|
||||||
|
bar.appendChild(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Insert the status bar into the DOM
|
||||||
var cmWrapper = this.codemirror.getWrapperElement();
|
var cmWrapper = this.codemirror.getWrapperElement();
|
||||||
cmWrapper.parentNode.insertBefore(bar, cmWrapper.nextSibling);
|
cmWrapper.parentNode.insertBefore(bar, cmWrapper.nextSibling);
|
||||||
return bar;
|
return bar;
|
||||||
|
|
16
dist/simplemde.min.js
vendored
16
dist/simplemde.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1019,9 +1019,6 @@ function SimpleMDE(options) {
|
||||||
if(!options.hasOwnProperty("status")) {
|
if(!options.hasOwnProperty("status")) {
|
||||||
options.status = ["autosave", "lines", "words", "cursor"];
|
options.status = ["autosave", "lines", "words", "cursor"];
|
||||||
}
|
}
|
||||||
if(!options.hasOwnProperty("statusCustom")) {
|
|
||||||
options.statusCustom = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Add default preview rendering function
|
// Add default preview rendering function
|
||||||
|
@ -1175,7 +1172,7 @@ SimpleMDE.prototype.render = function(el) {
|
||||||
if(options.toolbar !== false) {
|
if(options.toolbar !== false) {
|
||||||
this.createToolbar();
|
this.createToolbar();
|
||||||
}
|
}
|
||||||
if(options.status !== false || options.statusCustom) {
|
if(options.status !== false) {
|
||||||
this.createStatusbar();
|
this.createStatusbar();
|
||||||
}
|
}
|
||||||
if(options.autosave != undefined && options.autosave.enabled === true) {
|
if(options.autosave != undefined && options.autosave.enabled === true) {
|
||||||
|
@ -1375,97 +1372,115 @@ SimpleMDE.prototype.createToolbar = function(items) {
|
||||||
};
|
};
|
||||||
|
|
||||||
SimpleMDE.prototype.createStatusbar = function(status) {
|
SimpleMDE.prototype.createStatusbar = function(status) {
|
||||||
var customOptions = this.options.statusCustom;
|
// Initialize
|
||||||
status = status || this.options.status;
|
status = status || this.options.status;
|
||||||
var options = this.options;
|
var options = this.options;
|
||||||
|
var cm = this.codemirror;
|
||||||
|
|
||||||
if(!status || status.length === 0) return;
|
|
||||||
|
|
||||||
// Copy the defaults if the status is a boolean true
|
// Make sure the status variable is valid
|
||||||
if(status === true) status = ["autosave", "lines", "words", "cursor"];
|
if(!status || status.length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
// Set up the built-in items
|
||||||
|
var items = [];
|
||||||
|
var i, onUpdate, defaultValue;
|
||||||
|
|
||||||
// Set up the in-built actions: autosave, lines, words, cursor
|
|
||||||
var actions = {};
|
|
||||||
var i, name, onUpdate, defaultValue;
|
|
||||||
for(i = 0; i < status.length; i++) {
|
for(i = 0; i < status.length; i++) {
|
||||||
name = status[i];
|
// Reset some values
|
||||||
|
onUpdate = undefined;
|
||||||
|
defaultValue = undefined;
|
||||||
|
|
||||||
if(name === "words") {
|
|
||||||
defaultValue = function(el) {
|
|
||||||
el.innerHTML = "0";
|
|
||||||
};
|
|
||||||
onUpdate = function(el) {
|
|
||||||
el.innerHTML = wordCount(cm.getValue());
|
|
||||||
};
|
|
||||||
} else if(name === "lines") {
|
|
||||||
defaultValue = function(el) {
|
|
||||||
el.innerHTML = "0";
|
|
||||||
};
|
|
||||||
onUpdate = function(el) {
|
|
||||||
el.innerHTML = cm.lineCount();
|
|
||||||
};
|
|
||||||
} else if(name === "cursor") {
|
|
||||||
defaultValue = function(el) {
|
|
||||||
el.innerHTML = "0:0";
|
|
||||||
};
|
|
||||||
onUpdate = function(el) {
|
|
||||||
pos = cm.getCursor();
|
|
||||||
el.innerHTML = pos.line + ":" + pos.ch;
|
|
||||||
};
|
|
||||||
} else if(name === "autosave") {
|
|
||||||
defaultValue = function(el) {
|
|
||||||
if(options.autosave != undefined && options.autosave.enabled === true) {
|
|
||||||
el.setAttribute("id", "autosaved");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
actions[name] = {
|
|
||||||
onUpdate: onUpdate,
|
|
||||||
defaultValue: defaultValue
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate any user-provided options
|
// Handle if custom or not
|
||||||
for(var key in customOptions) {
|
if(typeof status[i] === "object") {
|
||||||
if(customOptions.hasOwnProperty(key)) {
|
items.push({
|
||||||
var thisOption = customOptions[key];
|
className: status[i].className,
|
||||||
|
defaultValue: status[i].defaultValue,
|
||||||
|
onUpdate: status[i].onUpdate
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var name = status[i];
|
||||||
|
|
||||||
// Copy the option into the combined actions
|
if(name === "words") {
|
||||||
// This will allow the user to override the defaults
|
defaultValue = function(el) {
|
||||||
actions[key] = {
|
el.innerHTML = "0";
|
||||||
defaultValue: thisOption.defaultValue,
|
};
|
||||||
onUpdate: thisOption.onUpdate
|
onUpdate = function(el) {
|
||||||
};
|
el.innerHTML = wordCount(cm.getValue());
|
||||||
|
};
|
||||||
|
} else if(name === "lines") {
|
||||||
|
defaultValue = function(el) {
|
||||||
|
el.innerHTML = "0";
|
||||||
|
};
|
||||||
|
onUpdate = function(el) {
|
||||||
|
el.innerHTML = cm.lineCount();
|
||||||
|
};
|
||||||
|
} else if(name === "cursor") {
|
||||||
|
defaultValue = function(el) {
|
||||||
|
el.innerHTML = "0:0";
|
||||||
|
};
|
||||||
|
onUpdate = function(el) {
|
||||||
|
var pos = cm.getCursor();
|
||||||
|
el.innerHTML = pos.line + ":" + pos.ch;
|
||||||
|
};
|
||||||
|
} else if(name === "autosave") {
|
||||||
|
defaultValue = function(el) {
|
||||||
|
if(options.autosave != undefined && options.autosave.enabled === true) {
|
||||||
|
el.setAttribute("id", "autosaved");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
items.push({
|
||||||
|
className: name,
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
onUpdate: onUpdate
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create element for the status bar
|
||||||
var bar = document.createElement("div");
|
var bar = document.createElement("div");
|
||||||
bar.className = "editor-statusbar";
|
bar.className = "editor-statusbar";
|
||||||
|
|
||||||
var pos, cm = this.codemirror;
|
|
||||||
// Create a new span for each action
|
// Create a new span for each item
|
||||||
for(name in actions) {
|
for(i = 0; i < items.length; i++) {
|
||||||
if(actions.hasOwnProperty(name)) {
|
// Store in temporary variable
|
||||||
var el = document.createElement("span");
|
var item = items[i];
|
||||||
el.className = name;
|
|
||||||
// Ensure the defaultValue is a function
|
|
||||||
if(typeof actions[name].defaultValue === "function") {
|
// Create span element
|
||||||
actions[name].defaultValue(el);
|
var el = document.createElement("span");
|
||||||
}
|
el.className = item.className;
|
||||||
// Ensure the onUpdate is a function
|
|
||||||
if(typeof actions[name].onUpdate === "function") {
|
|
||||||
// Create a closure around the span and the name
|
// Ensure the defaultValue is a function
|
||||||
// of the current action, then execute the onUpdate handler
|
if(typeof item.defaultValue === "function") {
|
||||||
cm.on("update", (function(el, name) {
|
item.defaultValue(el);
|
||||||
return function() {
|
|
||||||
actions[name].onUpdate(el);
|
|
||||||
};
|
|
||||||
}(el, name)));
|
|
||||||
}
|
|
||||||
bar.appendChild(el);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Ensure the onUpdate is a function
|
||||||
|
if(typeof item.onUpdate === "function") {
|
||||||
|
// Create a closure around the span of the current action, then execute the onUpdate handler
|
||||||
|
this.codemirror.on("update", (function(el, item) {
|
||||||
|
return function() {
|
||||||
|
item.onUpdate(el);
|
||||||
|
};
|
||||||
|
}(el, item)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Append the item to the status bar
|
||||||
|
bar.appendChild(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Insert the status bar into the DOM
|
||||||
var cmWrapper = this.codemirror.getWrapperElement();
|
var cmWrapper = this.codemirror.getWrapperElement();
|
||||||
cmWrapper.parentNode.insertBefore(bar, cmWrapper.nextSibling);
|
cmWrapper.parentNode.insertBefore(bar, cmWrapper.nextSibling);
|
||||||
return bar;
|
return bar;
|
||||||
|
|
Loading…
Reference in a new issue