- |
- |
- |
- |
- |
Plugins are currently in beta. We don't anticipate any major changes as we have been working on this for more than half a year but we don't guarantee it won't change. Use this at your own risk.
In SnapEditor, plugins are just a concept. There is no plugin object. Plugins are just a group of features packaged together. Each feature can stand on its own.
If you are looking to just create a custom button, skip down to the Buttons feature.
Use actions to share functions in SnapEditor.
Add actions to the SnapEditor.actions
object.
SnapEditor.actions.say = function(e, text) {
e.api.insert("<p>" + text + "</p>");
};
Execute actions at any time from the API object. To
execute an action, call the api.execAction()
function.
function (e) {
e.api.execAction("say", e, text);
}
The first argument to api.execAction()
is the name of the action you want to execute.
The extra arguments are passed through to the action.
To keep things consistent, the first extra argument should always be a SnapEditor event object. This way, the action always has access to the API.
Buttons are declared first, then added. Buttons may be added to other buttons. In this case, the button will trigger a menu with the other buttons in it.
Button objects may contain the following keys.
text, html, action, items
text
is used for the title when hovering over a button. It is also used for the label if the button
is included in a menu and does not have an html
key.
html
is only used when the button is included in a menu. It is used as the label.
This is only optional if items
is not specified.
action
specifies a function to execute when the button is clicked. The function will receive a
SnapEditor event object.
{
api: <SnapEditor API Object>
}
The action may also be a String which corresponds to the name of a predefined action.
items
tells SnapEditor that this button will trigger a menu.
items
is an array of Strings that correspond to the names of each button to include in the menu.
When items
is specified, action
is ignored since the behaviour of the button is to show
a menu.
Declare buttons by adding the button to the SnapEditor.buttons
object.
// Add an action to be used.
SnapEditor.actions.sayBye = function (e) {
e.api.insert("<p>Bye</p>");
};
// Declaring a button.
SnapEditor.buttons.sayHi = {
text: "Say Hi",
action: function (e) {
e.api.insert("<p>Hi</p>");
}
}
// Declaring a button with a predefined action.
SnapEditor.buttons.sayBye = {
text: "Say Bye",
action: "sayBye"
}
// Declaring a button with custom HTML for menus.
SnapEditor.buttons.sayWorld = {
text: "Say World",
html: '<span class="shout">Say World</span>',
action: function (e) {
e.api.insert("<p>World</p>");
},
}
// Declaring a button that triggers a menu with other buttons.
SnapEditor.buttons.say = {
text: "Say",
items: ["sayHi", "sayBye", "sayWorld"]
}
After declaring a button, you can add the button to the global SnapEditor default config or a particular instance of SnapEditor.
// Add to the global SnapEditor default config.
SnapEditor.config.buttons.push("say");
// Add to a particular instance of SnapEditor by overriding the default.
var editor = new SnapEditor.InPlace("editor", {
buttons: ["bold", "italic", "say"]
});
// Add to a particular instance of SnapEditor by appending to the default.
var editor = new SnapEditor.InPlace("editor", {
buttons: SnapEditor.config.buttons.concat(["say"])
});
The button will have a classname of the following form.
snapeditor_toolbar_icon_<snake case of button name>
Due to CSS selector strength, to override the default icon, an extra classname needs to be used.
.snapeditor_toolbar .snapeditor_toolbar_icon_<snake case of button name>
Icons should be 26px by 26px.
Example.
// JavaScript
SnapEditor.buttons.sayHi = {
text: "Say Hi",
action: function (e) {
e.api.insert("<p>Hi</p>");
}
}
// CSS
.snapeditor_toolbar .snapeditor_toolbar_icon_say_hi {
background-image: url("say_hi.png");
}
For a full example that includes shortcuts, go the Custom Buttons example.
Shortcuts are declared first, then added. Shortcuts are used to execute an action.
Shortcut objects must contain the following keys.
key, action
key
specifies the keyboard shortcut to be used. When specifying a combination of keys, separate the
keys by a '+'.
The following are the available keys for use.
alt, ctrl, shift,
0-9, a-z,
backspace, delete, esc, enter, space, tab,
up, down, left, right,
home, end, pageup, pagedown
action
refers to the name of the predefined action to execute.
Declare shortcuts by adding the shortcut to the SnapEditor.shortcuts
object.
// Add an action to be used.
SnapEditor.actions.sayHi = function (e) {
e.api.insert("<p>Hi</p>");
};
// Declare the shortcut for the action.
SnapEditor.shortcuts.sayHi = {
key: "ctrl+h",
action: "sayHi"
}
After declaring a shortcut, you can add the shortcut to the global SnapEditor default config or a particular instance of SnapEditor.
// Add to the global SnapEditor default config.
SnapEditor.config.shortcuts.push("sayHi");
// Add to a particular instance of SnapEditor by overriding the default.
// Do this with care as you will lose other shortcuts.
var editor = new SnapEditor.InPlace("editor", {
shortcut: ["sayHi"]
});
// Add to a particular instance of SnapEditor by appending to the default.
// This is preferred.
var editor = new SnapEditor.InPlace("editor", {
shortcut: SnapEditor.config.shortcuts.concat(["sayHi"])
});
If there is a button that references the same action as the shortcut, SnapEditor will automatically include the shortcut in the button's title.
SnapEditor provides a way to easily create dialogs that can be used for various purposes, such as being triggered by an action.
Add dialogs to the SnapEditor.dialogs
object.
SnapEditor.dialogs.sayHi = {
html: "Hi"
}
Dialog objects may contain the following keys.
title, html, css, width, height, onSetup, onOpen, onClose
title
is used for the title of the dialog box. If title
is set to an empty string "",
the title bar shows but with no title. If title
is not specified or set to null
, the
title bar is not rendered.
html
is used for the content of the dialog. It can either be a string or a function that returns a
string.
css
is used to style the dialog. It can either be a string or a function that returns a string.
width
is used to set the width of the content.
height
is used to set the height of the content.
onSetup
is a function that gets called the first time the dialog is set up. The function gets a
Dialog event object that contains a reference to the dialog.
Note that there is no reference to the SnapEditor API at
this point as the setup is called in a general manner.
{
onSetup: function (e) {
e.dialog.setTitle("All set up");
}
}
onOpen
is a function that gets called whenever the dialog is opened. The function gets a Dialog
event object that contains a reference to the dialog
and the SnapEditor
API. It also gets any other arguments that are passed through when opening
a dialog.
{
onOpen: function (e, arg1, arg2) {
e.dialog.setTitle("Opening");
e.api.getContents();
}
}
onClose
is a function that gets called whenever the dialog is closed. The function gets a Dialog
event object that contains a reference to the dialog
and the SnapEditor
API.
{
onClose function (e) {
e.dialog.setTitle("Closing");
e.api.getContents();
}
}
The Dialog object has the following functions.
setTitle(), setHTML(), on(), find(), close()
setTitle()
setTitle([title])
setTitle()
sets the title of the dialog. If an empty string "" is given, the title bar shows but
with no title. If no title
is given or is null, the title bar is not rendered.
setHTML()
setHTML(html)
setHTML()
sets the content of the dialog.
on()
on(selector, event, handler)
on()
attaches the given handler
to the given event
on the elements inside
the dialog content that match the given selector
.
The handler
is given a Dialog event object that contains a reference to the dialog,
the SnapEditor API,
and the original DOM event.
dialog.on("a.cancel", "click", function (e) {
e.domEvent.preventDefault();
e.api.getContents();
e.dialog.close();
});
find()
find(selector)
find()
returns an array of all elements inside the dialog content that matches the given
selector
.
find()
returns an array even if there is a single match or no matches.
var inputs = dialog.find("input[type=text]");
close()
close()
close()
closes the dialog.
api.openDialog("sayHi", e, arg1, arg2);
The first argument to api.openDialog()
is the name of the dialog you want to open.
The extra arguments are passed through to the action.
To keep things consistent, the first extra argument should always be a SnapEditor event object. This way, the dialog always has access to the API.
dialog.close();
api.closeDialog("sayHi");
The first way to close a dialog is to call the close()
function of the Dialog
object if you have one.
The other way to close a dialog is to call api.closeDialog()
. The only argument to
api.closeDialog()
is the name of the dialog you want to close.
Behaviours affect the way SnapEditor works. They are triggered by attaching themselves to SnapEditor events.
Behaviours are declared first, then added.
Behaviour objects are made up of SnapEditor event names without the snapeditor
namespace. "on" is
appended to the name to make it clear we're dealing with events. This makes up the key. The values are functions
that will receive a SnapEditor event object which will contain a SnapEditor API
object as an argument.
// We'll use the "snapeditor.activate" event as an example.
{
onActivate: function (e) {
console.log(e.api.getContents());
}
}
Declare behaviours by adding the behaviour to the SnapEditor.behaviours
object.
SnapEditor.behaviours.say = {
onActivate: function (e) {
console.log("Activated with content: " + e.api.getContents());
},
onUpdate: function (e) {
// Reposition a custom dialog.
}
}
After declaring a behaviour, you can add the behaviour to the global SnapEditor default config or a particular instance of SnapEditor.
// Add to the global SnapEditor default config.
SnapEditor.config.behaviours.push("say");
// Add to a particular instance of SnapEditor by overriding the default.
// This is never recommended as the default behaviours of SnapEditor will be removed.
var editor = new SnapEditor.InPlace("editor", {
behaviour: ["say"]
});
// Add to a particular instance of SnapEditor by appending to the default.
// This is the proper way of adding behaviours.
var editor = new SnapEditor.InPlace("editor", {
behaviour: SnapEditor.config.behaviours.concat(["say"])
});
Here is an example of a custom button.
<!DOCTYPE html>
<html>
<head>
<style>
/* Set the icon for the custom button. */
.snapeditor_toolbar .snapeditor_toolbar_icon_say_hi {
background-image: url("say_hi.png");
}
</style>
</head>
<body>
<div id="editor">
<p>This is an in-place editor!</p>
</div>
<script type="text/javascript" src="/snapeditor/snapeditor.js"></script>
<script type="text/javascript">
// Declare all the needed features.
SnapEditor.actions.sayHi = function (e) { e.api.insert("<p>Hi</p>"); };
SnapEditor.buttons.sayHi = {
text: "Say Hi",
action: "sayHi"
};
SnapEditor.shortcuts.sayHi = {
key: "ctrl+alt+h",
action: "sayHi"
};
var inPlaceEditor = new SnapEditor.InPlace("editor", {
// Add the button and shortcut.
buttons: SnapEditor.config.buttons.concat(["sayHi"]),
shortcuts: SnapEditor.config.shortcuts.concat(["sayHi"])
});
</script>
</body>
</html>
As mentioned at the beginning of this doc, plugins are just a concept. There is no plugin object. Plugins are conceptual groupings of the above features.
One way to group the features together for a plugin is to put them into a single JavaScript file.
Because the features are all attached to global objects, we suggest namespacing all features with the name of your plugin as to not collide with other features.
Here is an example of a "Say" plugin in a file called say.js
. We will be using "say" as the
namespace. Note that this plugin uses all the features. However, you don't have to.
// Declare the actions.
SnapEditor.actions.sayHi = function (e) { e.api.insert("<p>Hi</p>"); };
SnapEditor.actions.sayBye = function (e) { e.api.insert("<p>Bye</p>"); };
SnapEditor.actions.sayWorld = function (e) { e.api.insert("<p>World</p>"); };
// Declare the buttons.
SnapEditor.buttons.sayHi = {
text: "Say Hi",
html: '<span class="hi">Say Hi</span>',
action: "sayHi"
};
SnapEditor.buttons.sayBye = {
text: "Say Bye",
html: '<span class="bye">Say Bye</span>',
action: "sayBye"
};
SnapEditor.buttons.sayWorld = {
text: "Say World",
html: '<span class="world">Say World</span>',
action: "sayWorld"
};
SnapEditor.buttons.say = {
text: "Say",
items: ["sayHi", "sayBye", "sayWorld"] // menu of buttons
};
// Declare behaviours.
SnapEditor.behaviours.say {
onActivate: function (e) {
console.log("From the Say plugin: Hi!");
},
onClean: function (e) {
console.log("From the Say plugin: I see you're cleaning the content!");
}
}
Note that shortcuts are not specified. This is recommended as you're not sure what other plugins the developer may decide to add. If you specify shortcuts in your plugin, it may collide with other ones that the developer is already using. We recommend that shortcuts be left to the developer to determine.
Now the developer can include it on the page.
<!DOCTYPE html>
<html>
<body>
<div id="editor">
<p>This is an in-place editor!</p>
</div>
<script type="text/javascript" src="/snapeditor/snapeditor.js"></script>
<script type="text/javascript" src="/snapeditor/plugins/say.js"></script>
<script type="text/javascript">
// Declare the shortcuts.
SnapEditor.shortcuts.sayHi = {
key: "ctrl+alt+h",
action: "sayHi"
};
SnapEditor.shortcuts.sayBye = {
key: "ctrl+alt+b",
action: "sayBye"
};
SnapEditor.shortcuts.sayWorld = {
key: "ctrl+alt+w",
action: "sayWorld"
};
// In this example, we've decided to add the features directly to the global SnapEditor default config.
SnapEditor.config.buttons.push("say");
SnapEditor.config.behaviours.push("say");
SnapEditor.config.shortcuts.push("sayHi");
SnapEditor.config.shortcuts.push("sayBye");
SnapEditor.config.shortcuts.push("sayWorld");
var inPlaceEditor = new SnapEditor.InPlace("editor");
</script>
</body>
</html>