Editor: YUI Editor with AlloyUI Toolbar
This example uses the AlloyUI Toolbar module from the YUI 3 Gallery to add a GUI to EditorBase.
Working with EditorBase
EditorBase is not a fully functional Editor, it's simply the base utility under the hood that will be used to create an Editor. In this example
we will show how to setup EditorBase and use the AlloyUI Toolbar Gallery module to interact with the it.
Setting up the HTML Source
The first step is to create the markup for our toolbar and our container for the Editor. Here we are creating a wrapper for the entire editor that includes a toolbar with Font Family and Font Size select lists and a container to render the Editor.
<div id="editor_cont"> <div id="toolbar"> <h2 tabindex="-1">Text Editing Tools</h2> <select id="fontname"> <option selected> </option> <option>Arial</option> <option>Arial Black</option> <option>Comic Sans MS</option> <option>Courier New</option> <option>Lucida Console</option> <option>Tahoma</option> <option>Times New Roman</option> <option>Trebuchet MS</option> <option>Verdana</option> </select> <select id="fontsize"> <option selected> </option> <option value="1">10</option> <option value="2">13</option> <option value="3">16</option> <option value="4">18</option> <option value="5">24</option> <option value="6">32</option> <option value="7">48</option> </select> </div> <div id="editor"></div> </div>
<div id="editor_cont"> <div id="toolbar"> <h2 tabindex="-1">Text Editing Tools</h2> <select id="fontname"> <option selected> </option> <option>Arial</option> <option>Arial Black</option> <option>Comic Sans MS</option> <option>Courier New</option> <option>Lucida Console</option> <option>Tahoma</option> <option>Times New Roman</option> <option>Trebuchet MS</option> <option>Verdana</option> </select> <select id="fontsize"> <option selected> </option> <option value="1">10</option> <option value="2">13</option> <option value="3">16</option> <option value="4">18</option> <option value="5">24</option> <option value="6">32</option> <option value="7">48</option> </select> </div> <div id="editor"></div> </div>
Creating the Editor
In this step we are going to do the inital render of the Editor, set it's content and focus it when it's ready.
YUI().use('editor', 'editor-lists', 'createlink-base', function(Y) { //Create the Base Editor var editor = new Y.EditorBase({ content: '<strong>This is <em>a test</em></strong> <strong>This is <em>a test</em></strong> ' }); //Focusing the Editor when the frame is ready.. editor.on('frame:ready', function() { this.focus(); }); //Rendering the Editor. editor.render('#editor'); });
YUI().use('editor', 'editor-lists', 'createlink-base', function(Y) { //Create the Base Editor var editor = new Y.EditorBase({ content: '<strong>This is <em>a test</em></strong> <strong>This is <em>a test</em></strong> ' }); //Focusing the Editor when the frame is ready.. editor.on('frame:ready', function() { this.focus(); }); //Rendering the Editor. editor.render('#editor'); });
Adding the Toolbar
Now we need to add the AlloyUI Toolbar Gallery module and render it with the buttons we want to add. Then we will listen for a button click event and call the execCommand method on the Editor to invoke that action.
YUIConfig.modules = { 'gallery-aui-skin-base': { fullpath: 'http://yui.yahooapis.com/gallery-2010.06.07-17-52/build/gallery-aui-skin-base/css/gallery-aui-skin-base-min.css', type: 'css' }, 'gallery-aui-skin-classic': { fullpath: 'http://yui.yahooapis.com/gallery-2010.06.07-17-52/build/gallery-aui-skin-classic/css/gallery-aui-skin-classic-min.css', type: 'css', requires: ['gallery-aui-skin-base'] } }; YUI(YUIConfig).use('gallery-aui-toolbar', 'editor', 'editor-lists', 'createlink-base', function(Y) { //Create the Base Editor //SNIPPED FROM ABOVE //Creating a new AlloyUI Toolbar var toolbar = new Y.Toolbar({ activeState: true, children: [ { icon: 'bold' }, { icon: 'italic' }, { icon: 'underline' }, { icon: 'createlink' } ] } ).render('#toolbar'); //Listening for a button click on the Toolbar and firing an execCommand toolbar.on('buttonitem:click', function(e) { var cmd = e.target.get('icon'); editor.focus(); var ex_return = editor.execCommand(cmd, ''); }); });
YUIConfig.modules = { 'gallery-aui-skin-base': { fullpath: 'http://yui.yahooapis.com/gallery-2010.06.07-17-52/build/gallery-aui-skin-base/css/gallery-aui-skin-base-min.css', type: 'css' }, 'gallery-aui-skin-classic': { fullpath: 'http://yui.yahooapis.com/gallery-2010.06.07-17-52/build/gallery-aui-skin-classic/css/gallery-aui-skin-classic-min.css', type: 'css', requires: ['gallery-aui-skin-base'] } }; YUI(YUIConfig).use('gallery-aui-toolbar', 'editor', 'editor-lists', 'createlink-base', function(Y) { //Create the Base Editor //SNIPPED FROM ABOVE //Creating a new AlloyUI Toolbar var toolbar = new Y.Toolbar({ activeState: true, children: [ { icon: 'bold' }, { icon: 'italic' }, { icon: 'underline' }, { icon: 'createlink' } ] } ).render('#toolbar'); //Listening for a button click on the Toolbar and firing an execCommand toolbar.on('buttonitem:click', function(e) { var cmd = e.target.get('icon'); editor.focus(); var ex_return = editor.execCommand(cmd, ''); }); });
Hooking up the Events
First we will listen for a nodeChange event from the Editor (scoped to 2 DOM events) and call a method
called updateButtons, which will update the toolbar's state to reflect that of the Editor. We will also attach a
listener to the select lists to update the font family/size in the Editor.
//Create the Base Editor var editor = new Y.EditorBase({ content: '<strong>This is <em>a test</em></strong> <strong>This is <em>a test</em></strong> ' }); //Hookup the Toolbar changes editor.after('nodeChange', function(e) { //Scoping the toolbar update to only a couple nodeChange events. //So it doesn't happen too often switch (e.changedType) { case 'keyup': case 'mousedown': updateButtons(e); break; } }); //Caching a reference to the options var f_options = Y.all('#fontname option'); var s_options = Y.all('#fontsize option'); //Updating the toolbar with the current Editor state var updateButtons = function(e) { var tar = e.changedNode; if (tar) { var cmds = e.commands; //Resetting the buttons to their proper states based on the commands from the event toolbar.each(function(b) { var st = false; if (cmds[b.get('icon')]) { st = true; } b.StateInteraction.set('active', st); }); var fname = e.fontFamily, size = e.fontSize; //Updating the font family select f_options.item(0).set('selected', true); f_options.each(function(v) { var val = v.get('value').toLowerCase(); if (val === fname.toLowerCase()) { v.set('selected', true); } }); //Updating the font size select s_options.item(0).set('selected', true); size = size.replace('px', ''); s_options.each(function(v) { var val = v.get('value').toLowerCase(), txt = v.get('text'); if (size === txt) { v.set('selected', true); } }); } }; //Listening for the change event on the 2 select boxes Y.delegate('change', function(e) { var cmd = e.currentTarget.get('id'), val = e.currentTarget.get('value'); editor.focus(); var ex_return = editor.execCommand(cmd, val); }, '#toolbar', 'select');
//Create the Base Editor
var editor = new Y.EditorBase({
content: '<strong>This is <em>a test</em></strong> <strong>This is <em>a test</em></strong> '
});
//Hookup the Toolbar changes
editor.after('nodeChange', function(e) {
//Scoping the toolbar update to only a couple nodeChange events.
//So it doesn't happen too often
switch (e.changedType) {
case 'keyup':
case 'mousedown':
updateButtons(e);
break;
}
});
//Caching a reference to the options
var f_options = Y.all('#fontname option');
var s_options = Y.all('#fontsize option');
//Updating the toolbar with the current Editor state
var updateButtons = function(e) {
var tar = e.changedNode;
if (tar) {
var cmds = e.commands;
//Resetting the buttons to their proper states based on the commands from the event
toolbar.each(function(b) {
var st = false;
if (cmds[b.get('icon')]) {
st = true;
}
b.StateInteraction.set('active', st);
});
var fname = e.fontFamily,
size = e.fontSize;
//Updating the font family select
f_options.item(0).set('selected', true);
f_options.each(function(v) {
var val = v.get('value').toLowerCase();
if (val === fname.toLowerCase()) {
v.set('selected', true);
}
});
//Updating the font size select
s_options.item(0).set('selected', true);
size = size.replace('px', '');
s_options.each(function(v) {
var val = v.get('value').toLowerCase(),
txt = v.get('text');
if (size === txt) {
v.set('selected', true);
}
});
}
};
//Listening for the change event on the 2 select boxes
Y.delegate('change', function(e) {
var cmd = e.currentTarget.get('id'),
val = e.currentTarget.get('value');
editor.focus();
var ex_return = editor.execCommand(cmd, val);
}, '#toolbar', 'select');
Making look pretty
Here is the CSS used in this example to make the toolbar and the Editor look similar to the YUI 2 SimpleEditor.
#editor_cont { width: 600px; border: 1px solid #999; margin: 2em; } #editor { height: 265px; } #toolbar { border-bottom: 1px solid #999; background-color: #F2F2F2; min-height: 25px; position: relative; } #toolbar select { position: relative; top: -4px; margin-right: 7px; } #fontname { margin-left: 7px; } #toolbar .yui3-icon { background: url("http://yui.yahooapis.com/2.8.1/build/editor/assets/skins/sam/editor-sprite.gif") no-repeat scroll 30px 30px transparent; } #toolbar .yui3-icon-bold { background-position: 0 -1px; } #toolbar .yui3-icon-italic { background-position:0 -37px; } #toolbar .yui3-icon-underline { background-position:0 -73px; } #toolbar .yui3-icon-createlink { background-position:0 -794px; } #toolbar .yui3-state-default, #toolbar .yui3-state-active, #toolbar .yui3-state-hover { margin-left: -1px; border-color: #808080; background:url("http://yui.yahooapis.com/2.8.1/build/assets/skins/sam/sprite.png") repeat-x scroll 0 0 transparent; } #toolbar .yui3-state-active { background-position: 0 -1700px; } #toolbar .yui3-state-hover { background-position: 0 -1300px; } #toolbar h2 { letter-spacing:0; margin:0; color:#000000; font-size:100%; font-weight:bold; margin: 0; margin-bottom: 7px; padding: 0.3em 1em; text-align:left; background:url("http://yui.yahooapis.com/2.8.1/build/assets/skins/sam/sprite.png") repeat-x scroll 0 -206px transparent; }
#editor_cont { width: 600px; border: 1px solid #999; margin: 2em; } #editor { height: 265px; } #toolbar { border-bottom: 1px solid #999; background-color: #F2F2F2; min-height: 25px; position: relative; } #toolbar select { position: relative; top: -4px; margin-right: 7px; } #fontname { margin-left: 7px; } #toolbar .yui3-icon { background: url("http://yui.yahooapis.com/2.8.1/build/editor/assets/skins/sam/editor-sprite.gif") no-repeat scroll 30px 30px transparent; } #toolbar .yui3-icon-bold { background-position: 0 -1px; } #toolbar .yui3-icon-italic { background-position:0 -37px; } #toolbar .yui3-icon-underline { background-position:0 -73px; } #toolbar .yui3-icon-createlink { background-position:0 -794px; } #toolbar .yui3-state-default, #toolbar .yui3-state-active, #toolbar .yui3-state-hover { margin-left: -1px; border-color: #808080; background:url("http://yui.yahooapis.com/2.8.1/build/assets/skins/sam/sprite.png") repeat-x scroll 0 0 transparent; } #toolbar .yui3-state-active { background-position: 0 -1700px; } #toolbar .yui3-state-hover { background-position: 0 -1300px; } #toolbar h2 { letter-spacing:0; margin:0; color:#000000; font-size:100%; font-weight:bold; margin: 0; margin-bottom: 7px; padding: 0.3em 1em; text-align:left; background:url("http://yui.yahooapis.com/2.8.1/build/assets/skins/sam/sprite.png") repeat-x scroll 0 -206px transparent; }
Full Javascript Source
var YUIConfig = {}; YUIConfig.modules = { 'gallery-aui-skin-base': { fullpath: 'http://yui.yahooapis.com/gallery-2010.06.07-17-52/build/gallery-aui-skin-base/css/gallery-aui-skin-base-min.css', type: 'css' }, 'gallery-aui-skin-classic': { fullpath: 'http://yui.yahooapis.com/gallery-2010.06.07-17-52/build/gallery-aui-skin-classic/css/gallery-aui-skin-classic-min.css', type: 'css', requires: ['gallery-aui-skin-base'] } }; YUI(YUIConfig).use('gallery-aui-toolbar', 'node', 'editor', 'editor-lists', 'createlink-base', function(Y) { //Create the Base Editor var editor = new Y.EditorBase({ content: '<strong>This is <em>a test</em></strong> <strong>This is <em>a test</em></strong> ' }); //Hookup the Toolbar changes editor.after('nodeChange', function(e) { //Scoping the toolbar update to only a couple nodeChange events. //So it doesn't happen too often switch (e.changedType) { case 'keyup': case 'mousedown': updateButtons(e); break; } }); //Focusing the Editor when the frame is ready.. editor.on('frame:ready', function() { this.focus(); }); //Rendering the Editor. editor.render('#editor'); //Creating a new AlloyUI Toolbar var toolbar = new Y.Toolbar({ activeState: true, children: [ { icon: 'bold' }, { icon: 'italic' }, { icon: 'underline' }, { icon: 'createlink' } ] } ).render('#toolbar'); //Listening for a button click on the Toolbar and firing an execCommand toolbar.on('buttonitem:click', function(e) { var cmd = e.target.get('icon'); editor.focus(); var ex_return = editor.execCommand(cmd, ''); }); //Listening for the change event on the 2 select boxes Y.delegate('change', function(e) { var cmd = e.currentTarget.get('id'), val = e.currentTarget.get('value'); editor.focus(); var ex_return = editor.execCommand(cmd, val); }, '#toolbar', 'select'); //Caching a reference to the options var f_options = Y.all('#fontname option'); var s_options = Y.all('#fontsize option'); //Updating the toolbar with the current Editor state var updateButtons = function(e) { var tar = e.changedNode; if (tar) { var cmds = e.commands; //Resetting the buttons to their proper states based on the commands from the event toolbar.each(function(b) { var st = false; if (cmds[b.get('icon')]) { st = true; } b.StateInteraction.set('active', st); }); var fname = e.fontFamily, size = e.fontSize; //Updating the font family select f_options.item(0).set('selected', true); f_options.each(function(v) { var val = v.get('value').toLowerCase(); if (val === fname.toLowerCase()) { v.set('selected', true); } }); //Updating the font size select s_options.item(0).set('selected', true); size = size.replace('px', ''); s_options.each(function(v) { var val = v.get('value').toLowerCase(), txt = v.get('text'); if (size === txt) { v.set('selected', true); } }); } }; });
var YUIConfig = {}; YUIConfig.modules = { 'gallery-aui-skin-base': { fullpath: 'http://yui.yahooapis.com/gallery-2010.06.07-17-52/build/gallery-aui-skin-base/css/gallery-aui-skin-base-min.css', type: 'css' }, 'gallery-aui-skin-classic': { fullpath: 'http://yui.yahooapis.com/gallery-2010.06.07-17-52/build/gallery-aui-skin-classic/css/gallery-aui-skin-classic-min.css', type: 'css', requires: ['gallery-aui-skin-base'] } }; YUI(YUIConfig).use('gallery-aui-toolbar', 'node', 'editor', 'editor-lists', 'createlink-base', function(Y) { //Create the Base Editor var editor = new Y.EditorBase({ content: '<strong>This is <em>a test</em></strong> <strong>This is <em>a test</em></strong> ' }); //Hookup the Toolbar changes editor.after('nodeChange', function(e) { //Scoping the toolbar update to only a couple nodeChange events. //So it doesn't happen too often switch (e.changedType) { case 'keyup': case 'mousedown': updateButtons(e); break; } }); //Focusing the Editor when the frame is ready.. editor.on('frame:ready', function() { this.focus(); }); //Rendering the Editor. editor.render('#editor'); //Creating a new AlloyUI Toolbar var toolbar = new Y.Toolbar({ activeState: true, children: [ { icon: 'bold' }, { icon: 'italic' }, { icon: 'underline' }, { icon: 'createlink' } ] } ).render('#toolbar'); //Listening for a button click on the Toolbar and firing an execCommand toolbar.on('buttonitem:click', function(e) { var cmd = e.target.get('icon'); editor.focus(); var ex_return = editor.execCommand(cmd, ''); }); //Listening for the change event on the 2 select boxes Y.delegate('change', function(e) { var cmd = e.currentTarget.get('id'), val = e.currentTarget.get('value'); editor.focus(); var ex_return = editor.execCommand(cmd, val); }, '#toolbar', 'select'); //Caching a reference to the options var f_options = Y.all('#fontname option'); var s_options = Y.all('#fontsize option'); //Updating the toolbar with the current Editor state var updateButtons = function(e) { var tar = e.changedNode; if (tar) { var cmds = e.commands; //Resetting the buttons to their proper states based on the commands from the event toolbar.each(function(b) { var st = false; if (cmds[b.get('icon')]) { st = true; } b.StateInteraction.set('active', st); }); var fname = e.fontFamily, size = e.fontSize; //Updating the font family select f_options.item(0).set('selected', true); f_options.each(function(v) { var val = v.get('value').toLowerCase(); if (val === fname.toLowerCase()) { v.set('selected', true); } }); //Updating the font size select s_options.item(0).set('selected', true); size = size.replace('px', ''); s_options.each(function(v) { var val = v.get('value').toLowerCase(), txt = v.get('text'); if (size === txt) { v.set('selected', true); } }); } }; });

