editor-base-debug.js revision 7058d70d5189510fab628ef8d64bb50dd726a941
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * Base class for Editor. Handles the business logic of Editor, no GUI involved only utility methods and events.
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * @module editor
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * @submodule editor-base
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * Base class for Editor. Handles the business logic of Editor, no GUI involved only utility methods and events.
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * @class EditorBase
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * @for EditorBase
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * @extends Base
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * @constructor
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass var EditorBase = function() {
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass EditorBase.superclass.constructor.apply(this, arguments);
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * Internal reference to the Y.Frame instance
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * @property frame
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass initializer: function() {
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass frame.after('ready', Y.bind(this._afterFrameReady, this));
162527ab925c04aa8d6bbf78d0484a133a8076f1Dav Glass var styles = ['color', 'fontSize', 'fontFamily', 'backgroundColor', 'fontStyle' ],
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass * The default handler for the nodeChange event.
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass * @method _defNodeChangeFn
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass * @param {Event} e The event
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass Y.log('Default nodeChange function: ' + e.changedType, 'info', 'editor');
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass case 'backspace-up':
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass if (inst.Selection.getText(item) === '' && !item.test('p')) {
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass sel.selectNode(inst.one('body > p').get('firstChild'));
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass } catch (e) {}
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass } else if (item.test('p') && item.get('innerHTML').length === 0) {
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass case 'enter-up':
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass var prev = e.changedNode.previous(), lc, lc2, found = false;
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass if (!e.changedNode.test('li, li *') && !e.changedEvent.shiftKey) {
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass Y.log('Overriding TAB key to insert HTML', 'info', 'editor');
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass this.execCommand('inserthtml', ' ');
0523d0a8daaa474f0214203f8cbb0bc4a88e2964Dav Glass //Bold and Italic styles
5432371fbb6d790a76159481f0dd16e806812153Dav Glass if (s.textDecoration.toLowerCase() == 'underline') {
162527ab925c04aa8d6bbf78d0484a133a8076f1Dav Glass if (s.textDecoration.toLowerCase() == 'line-through') {
162527ab925c04aa8d6bbf78d0484a133a8076f1Dav Glass var family2 = n.getStyle('fontFamily').split(',')[0].toLowerCase();
5432371fbb6d790a76159481f0dd16e806812153Dav Glass fColor = EditorBase.FILTER_RGB(n.getStyle('color'));
5432371fbb6d790a76159481f0dd16e806812153Dav Glass var bColor2 = EditorBase.FILTER_RGB(n.getStyle('backgroundColor'));
f7aa62ea2e8cf43fbb9d83db5060db540ff1893fDav Glass //TODO Dont' like this, not dynamic enough..
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass * Walk the dom tree from this node up to body, returning a reversed array of parents.
6dbc2e0b2c23ae7763959af9762fc50c84dbd937Dav Glass * @method getDomPath
96c1e6aab172b57cf3566abee931c26676990044Dav Glass * @param {Node} node The Node to start from
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass while (node !== null) {
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass if (node.test('html') || node.test('doc') || !node.get('tagName')) {
162527ab925c04aa8d6bbf78d0484a133a8076f1Dav Glass //Check to see if we get el.nodeName and nodeType
162527ab925c04aa8d6bbf78d0484a133a8076f1Dav Glass if (node.get('nodeName') && node.get('nodeType') && (node.get('nodeType') == 1)) {
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * After frame ready, bind mousedown & keyup listeners
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * @method _afterFrameReady
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass this.frame.on('mousedown', Y.bind(this._onFrameMouseDown, this));
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass this.frame.on('keyup', Y.bind(this._onFrameKeyUp, this));
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass this.frame.on('keydown', Y.bind(this._onFrameKeyDown, this));
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * Fires nodeChange event
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * @method _onFrameMouseDown
d0bccce76452becc96b65acaaa684aa6fabaf386Dav Glass this.fire('nodeChange', { changedNode: e.frameTarget, changedType: 'mousedown', changedEvent: e });
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * Fires nodeChange event for keyup on specific keys
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * @method _onFrameKeyUp
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass _onFrameKeyUp: function(e) {
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass this.fire('nodeChange', { changedNode: sel.anchorNode, changedType: 'keyup', selection: sel, changedEvent: e });
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass this.fire('nodeChange', { changedNode: sel.anchorNode, changedType: EditorBase.NC_KEYS[e.keyCode] + '-up', selection: sel, changedEvent: e });
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * Fires nodeChange event
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass * @method _onFrameKeyDown
d2a5a45ff58ab15a8ee0339edcd03f0243373d59Dav Glass _onFrameKeyDown: function(e) {
this.fire('nodeChange', { changedNode: sel.anchorNode, changedType: EditorBase.NC_KEYS[e.keyCode], changedEvent: e });
this.fire('nodeChange', { changedNode: sel.anchorNode, changedType: EditorBase.NC_KEYS[e.keyCode] + '-down', changedEvent: e });
* @return {Node/NodeList} The Node or Nodelist affected by the command. Only returns on override commands, not browser defined commands.
switch (cmd) {
return ret;
getInstance: function() {
destructor: function() {
* @param {Selector/HTMLElement/Node} node The node to append the Editor to
focus: function() {
show: function() {
hide: function() {
getContent: function() {
return html;
* @description Converts an RGB color string to a hex color, example: rgb(0, 255, 0) converts to #00ff00
var exp = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi");
return css;
TAG2CMD: {
NC_KEYS: {
STRINGS: {
ATTRS: {
content: {
getter: function() {
dir: {
writeOnce: true,
extracss: {
value: false,
if (this.frame) {
return css;
* <dt>changedType</dt><dd>The type of change: mousedown, mouseup, right, left, backspace, tab, enter, etc..</dd>
* <dt>commands</dt><dd>The list of execCommands that belong to this change and the dompath that's associated with the changedNode</dd>
* <dt>classNames</dt><dd>An array of classNames that are applied to the changedNode and all of it's parents</dd>