exec-command.js revision e04e9b42ef212618f77fd4b0f9a71cab4c55d8a0
5911N/A
5911N/A /**
5911N/A * Plugin for the frame module to handle execCommands for Editor
5911N/A * @module editor
5911N/A * @submodule exec-command
5911N/A */
5911N/A /**
5911N/A * Plugin for the frame module to handle execCommands for Editor
5911N/A * @class Plugin.ExecCommand
5911N/A * @extends Base
5911N/A * @constructor
5911N/A */
5911N/A var ExecCommand = function() {
5911N/A ExecCommand.superclass.constructor.apply(this, arguments);
5911N/A };
5911N/A
5911N/A Y.extend(ExecCommand, Y.Base, {
5911N/A _lastKey: null,
5911N/A /**
5911N/A * An internal reference to the instance of the frame plugged into.
5911N/A * @private
5911N/A * @property _inst
5911N/A */
5911N/A _inst: null,
5911N/A /**
5911N/A * Execute a command on the frame's document.
5911N/A * @method command
5911N/A * @param {String} action The action to perform (bold, italic, fontname)
5911N/A * @param {String} value The optional value (helvetica)
5911N/A * @return {Node/NodeList} Should return the Node/Nodelist affected
5911N/A */
5911N/A command: function(action, value) {
5911N/A var fn = ExecCommand.COMMANDS[action];
5911N/A
6532N/A Y.log('execCommand(' + action + '): "' + value + '"', 'info', 'exec-command');
6532N/A if (fn) {
5911N/A return fn.call(this, action, value);
5911N/A } else {
6532N/A return this._command(action, value);
6532N/A }
5911N/A },
5911N/A /**
5911N/A * The private version of execCommand that doesn't filter for overrides.
6532N/A * @private
5911N/A * @method _command
5911N/A * @param {String} action The action to perform (bold, italic, fontname)
5911N/A * @param {String} value The optional value (helvetica)
5911N/A */
5911N/A _command: function(action, value) {
5911N/A var inst = this.getInstance();
5911N/A try {
5911N/A Y.log('Internal execCommand(' + action + '): "' + value + '"', 'info', 'exec-command');
5911N/A inst.config.doc.execCommand(action, null, value);
5911N/A } catch (e) {
5911N/A Y.log(e.message, 'error', 'exec-command');
5911N/A }
5911N/A },
5911N/A /**
6532N/A * Get's the instance of YUI bound to the parent frame
6532N/A * @method getInstance
6532N/A * @return {YUI} The YUI instance bound to the parent frame
5911N/A */
5911N/A getInstance: function() {
5911N/A if (!this._inst) {
6539N/A this._inst = this.get('host').getInstance();
5911N/A }
5911N/A return this._inst;
5911N/A },
5911N/A initializer: function() {
5911N/A Y.mix(this.get('host'), {
5911N/A execCommand: function(action, value) {
5911N/A return this.exec.command(action, value);
5911N/A },
5911N/A _execCommand: function(action, value) {
5911N/A return this.exec._command(action, value);
5911N/A }
5911N/A });
5911N/A
5911N/A this.get('host').on('dom:keypress', Y.bind(function(e) {
5911N/A this._lastKey = e.keyCode;
5911N/A }, this));
5911N/A }
5911N/A }, {
5911N/A /**
5911N/A * execCommand
5911N/A * @property NAME
5911N/A * @static
5911N/A */
5911N/A NAME: 'execCommand',
5911N/A /**
5911N/A * exec
5911N/A * @property NS
5911N/A * @static
5911N/A */
5911N/A NS: 'exec',
5911N/A ATTRS: {
5911N/A host: {
5911N/A value: false
5911N/A }
5911N/A },
5911N/A /**
5911N/A * Static object literal of execCommand overrides
6539N/A * @property COMMANDS
5911N/A * @static
5911N/A */
5911N/A COMMANDS: {
5911N/A /**
5911N/A * Wraps the content with a new element of type (tag)
5911N/A * @method COMMANDS.wrap
5911N/A * @static
5911N/A * @param {String} cmd The command executed: wrap
5911N/A * @param {String} tag The tag to wrap the selection with
5911N/A * @return {NodeList} NodeList of the items touched by this command.
5911N/A */
5911N/A wrap: function(cmd, tag) {
5911N/A var inst = this.getInstance();
5911N/A return (new inst.Selection()).wrapContent(tag);
5911N/A },
5911N/A /**
5911N/A * Inserts the provided HTML at the cursor, should be a single element.
5911N/A * @method COMMANDS.inserthtml
5911N/A * @static
5911N/A * @param {String} cmd The command executed: inserthtml
5911N/A * @param {String} html The html to insert
5911N/A * @return {Node} Node instance of the item touched by this command.
5911N/A */
5911N/A inserthtml: function(cmd, html) {
5911N/A var inst = this.getInstance();
5911N/A if (inst.Selection.hasCursor() || Y.UA.ie) {
5911N/A return (new inst.Selection()).insertContent(html);
6532N/A } else {
5911N/A this._command('inserthtml', html);
5911N/A }
6539N/A },
6539N/A /**
5911N/A * Inserts the provided HTML at the cursor, and focuses the cursor afterwards.
5911N/A * @method COMMANDS.insertandfocus
5911N/A * @static
6539N/A * @param {String} cmd The command executed: insertandfocus
6539N/A * @param {String} html The html to insert
5911N/A * @return {Node} Node instance of the item touched by this command.
5911N/A */
5911N/A insertandfocus: function(cmd, html) {
5911N/A var inst = this.getInstance(), out, sel;
6539N/A if (inst.Selection.hasCursor()) {
5911N/A html += inst.Selection.CURSOR;
5911N/A out = this.command('inserthtml', html);
5911N/A sel = new inst.Selection();
5911N/A sel.focusCursor(true, true);
5911N/A } else {
5911N/A this.command('inserthtml', html);
5911N/A }
5911N/A return out;
5911N/A },
5911N/A /**
5911N/A * Inserts a BR at the current cursor position
5911N/A * @method COMMANDS.insertbr
5911N/A * @static
5911N/A * @param {String} cmd The command executed: insertbr
5911N/A */
5911N/A insertbr: function(cmd) {
5911N/A var inst = this.getInstance(), cur,
5911N/A sel = new inst.Selection();
5911N/A
5911N/A sel.setCursor();
5911N/A cur = sel.getCursor();
6539N/A cur.insert('<br>', 'before');
6539N/A sel.focusCursor(true, false);
6539N/A return cur.previous();
6539N/A },
6539N/A /**
6539N/A * Inserts an image at the cursor position
6539N/A * @method COMMANDS.insertimage
5911N/A * @static
5911N/A * @param {String} cmd The command executed: insertimage
5911N/A * @param {String} img The url of the image to be inserted
5911N/A * @return {Node} Node instance of the item touched by this command.
5911N/A */
5911N/A insertimage: function(cmd, img) {
5911N/A return this.command('inserthtml', '<img src="' + img + '">');
5911N/A },
5911N/A /**
5911N/A * Add a class to all of the elements in the selection
5911N/A * @method COMMANDS.addclass
5911N/A * @static
5911N/A * @param {String} cmd The command executed: addclass
5911N/A * @param {String} cls The className to add
6539N/A * @return {NodeList} NodeList of the items touched by this command.
5911N/A */
5911N/A addclass: function(cmd, cls) {
var inst = this.getInstance();
return (new inst.Selection()).getSelected().addClass(cls);
},
/**
* Remove a class from all of the elements in the selection
* @method COMMANDS.removeclass
* @static
* @param {String} cmd The command executed: removeclass
* @param {String} cls The className to remove
* @return {NodeList} NodeList of the items touched by this command.
*/
removeclass: function(cmd, cls) {
var inst = this.getInstance();
return (new inst.Selection()).getSelected().removeClass(cls);
},
/**
* Adds a background color to the current selection, or creates a new element and applies it
* @method COMMANDS.backcolor
* @static
* @param {String} cmd The command executed: backcolor
* @param {String} val The color value to apply
* @return {NodeList} NodeList of the items touched by this command.
*/
forecolor: function(cmd, val) {
var inst = this.getInstance(),
sel = new inst.Selection(), n;
if (!Y.UA.ie) {
this._command('styleWithCSS', 'true');
}
if (inst.Selection.hasCursor()) {
if (sel.isCollapsed) {
if (sel.anchorNode && (sel.anchorNode.get('innerHTML') === '&nbsp;')) {
sel.anchorNode.setStyle('color', val);
n = sel.anchorNode;
} else {
n = this.command('inserthtml', '<span style="color: ' + val + '">' + inst.Selection.CURSOR + '</span>');
sel.focusCursor(true, true);
}
return n;
} else {
return this._command(cmd, val);
}
} else {
this._command(cmd, val);
}
if (!Y.UA.ie) {
this._command('styleWithCSS', false);
}
},
backcolor: function(cmd, val) {
var inst = this.getInstance(),
sel = new inst.Selection(), n;
if (Y.UA.gecko || Y.UA.opera) {
cmd = 'hilitecolor';
}
if (!Y.UA.ie) {
this._command('styleWithCSS', 'true');
}
if (inst.Selection.hasCursor()) {
if (sel.isCollapsed) {
if (sel.anchorNode && (sel.anchorNode.get('innerHTML') === '&nbsp;')) {
sel.anchorNode.setStyle('backgroundColor', val);
n = sel.anchorNode;
} else {
n = this.command('inserthtml', '<span style="background-color: ' + val + '">' + inst.Selection.CURSOR + '</span>');
sel.focusCursor(true, true);
}
return n;
} else {
return this._command(cmd, val);
}
} else {
this._command(cmd, val);
}
if (!Y.UA.ie) {
this._command('styleWithCSS', false);
}
},
/**
* Sugar method, calles backcolor
* @method COMMANDS.hilitecolor
* @static
* @param {String} cmd The command executed: backcolor
* @param {String} val The color value to apply
* @return {NodeList} NodeList of the items touched by this command.
*/
hilitecolor: function() {
return ExecCommand.COMMANDS.backcolor.apply(this, arguments);
},
/**
* Adds a font name to the current selection, or creates a new element and applies it
* @method COMMANDS.fontname
* @static
* @param {String} cmd The command executed: fontname
* @param {String} val The font name to apply
* @return {NodeList} NodeList of the items touched by this command.
*/
fontname: function(cmd, val) {
this._command('fontname', val);
var inst = this.getInstance(),
sel = new inst.Selection();
if (sel.isCollapsed && (this._lastKey != 32)) {
if (sel.anchorNode.test('font')) {
sel.anchorNode.set('face', val);
}
}
},
/**
* Adds a fontsize to the current selection, or creates a new element and applies it
* @method COMMANDS.fontsize
* @static
* @param {String} cmd The command executed: fontsize
* @param {String} val The font size to apply
* @return {NodeList} NodeList of the items touched by this command.
*/
fontsize: function(cmd, val) {
this._command('fontsize', val);
var inst = this.getInstance(),
sel = new inst.Selection();
if (sel.isCollapsed && (this._lastKey != 32)) {
if (sel.anchorNode.test('font')) {
sel.anchorNode.set('size', val);
} else if (Y.UA.gecko) {
var p = sel.anchorNode.ancestor('p');
if (p) {
p.setStyle('fontSize', '');
}
}
}
}
}
});
Y.namespace('Plugin');
Y.Plugin.ExecCommand = ExecCommand;