editor-lists.js revision aa2ac226ad6e45232f8416eecc99d2165ce74d03
8346e283ad797ef549be70335d3961f4324901baRyan GroveYUI.add('editor-lists', function(Y) {
8346e283ad797ef549be70335d3961f4324901baRyan Grove
8346e283ad797ef549be70335d3961f4324901baRyan Grove /**
8346e283ad797ef549be70335d3961f4324901baRyan Grove * Handles list manipulation inside the Editor. Adds keyboard manipulation and execCommand support. Adds overrides for the <a href="Plugin.ExecCommand.html#method_COMMANDS.insertorderedlist">insertorderedlist</a> and <a href="Plugin.ExecCommand.html#method_COMMANDS.insertunorderedlist">insertunorderedlist</a> execCommands.
8346e283ad797ef549be70335d3961f4324901baRyan Grove * @module editor
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @submodule editor-lists
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney */
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney /**
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * Handles list manipulation inside the Editor. Adds keyboard manipulation and execCommand support. Adds overrides for the <a href="Plugin.ExecCommand.html#method_COMMANDS.insertorderedlist">insertorderedlist</a> and <a href="Plugin.ExecCommand.html#method_COMMANDS.insertunorderedlist">insertunorderedlist</a> execCommands.
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @class Plugin.EditorLists
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @constructor
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @extends Base
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney */
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney var EditorLists = function() {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney EditorLists.superclass.constructor.apply(this, arguments);
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }, LI = 'li', OL = 'ol', UL = 'ul', HOST = 'host';
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney Y.extend(EditorLists, Y.Base, {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney /**
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * Listener for host's nodeChange event and captures the tabkey interaction only when inside a list node.
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @private
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @method _onNodeChange
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @param {Event} e The Event facade passed from the host.
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney */
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney _onNodeChange: function(e) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney var inst = this.get(HOST).getInstance(), sel, li,
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney newLi, newList, sTab, par, moved = false, tag, focusEnd = false;
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (Y.UA.ie && e.changedType === 'enter') {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (e.changedNode.test(LI + ', ' + LI + ' *')) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney e.changedEvent.halt();
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney e.preventDefault();
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney li = e.changedNode;
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney newLi = inst.Node.create('<' + LI + '>' + EditorLists.NON + '</' + LI + '>');
5b1c89071eae2ae83f92260d7a50f9ad4e574f3dMatt Sweeney
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (!li.test(LI)) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney li = li.ancestor(LI);
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney li.insert(newLi, 'after');
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney sel = new inst.Selection();
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney sel.selectNode(newLi.get('firstChild'), true, false);
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (e.changedType === 'tab') {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (e.changedNode.test(LI + ', ' + LI + ' *')) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney e.changedEvent.halt();
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney e.preventDefault();
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney li = e.changedNode;
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney sTab = e.changedEvent.shiftKey;
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney par = li.ancestor(OL + ',' + UL);
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney tag = UL;
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (par.get('tagName').toLowerCase() === OL) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney tag = OL;
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (!li.test(LI)) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney li = li.ancestor(LI);
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (sTab) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (li.ancestor(LI)) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney li.ancestor(LI).insert(li, 'after');
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney moved = true;
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney focusEnd = true;
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney } else {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney //li.setStyle('border', '1px solid red');
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (li.previous(LI)) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney newList = inst.Node.create('<' + tag + '></' + tag + '>');
8f9dd8c743b57afd427fb6be634aee74466ad400Matt Sweeney li.previous(LI).append(newList);
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney newList.append(li);
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney moved = true;
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (moved) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (!li.test(LI)) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney li = li.ancestor(LI);
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney li.all(EditorLists.REMOVE).remove();
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney if (Y.UA.ie) {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney li = li.append(EditorLists.NON).one(EditorLists.NON_SEL);
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney //Selection here..
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney (new inst.Selection()).selectNode(li, true, focusEnd);
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney },
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney initializer: function() {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney this.get(HOST).on('nodeChange', Y.bind(this._onNodeChange, this));
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney }, {
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney /**
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * The non element placeholder, used for positioning the cursor and filling empty items
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @property REMOVE
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @static
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney */
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney NON: '<span class="yui-non">&nbsp;</span>',
8346e283ad797ef549be70335d3961f4324901baRyan Grove /**
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * The selector query to get all non elements
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @property NONSEL
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @static
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney */
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney NON_SEL: 'span.yui-non',
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney /**
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * The items to removed from a list when a list item is moved, currently removes BR nodes
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @property REMOVE
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @static
8346e283ad797ef549be70335d3961f4324901baRyan Grove */
8346e283ad797ef549be70335d3961f4324901baRyan Grove REMOVE: 'br',
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney /**
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * editorLists
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @property NAME
8ff167b366d7ee96cfc801bb01cd93e3ce573cbfMatt Sweeney * @static
*/
NAME: 'editorLists',
/**
* lists
* @property NS
* @static
*/
NS: 'lists',
ATTRS: {
host: {
value: false
}
}
});
Y.namespace('Plugin');
Y.Plugin.EditorLists = EditorLists;
Y.mix(Y.Plugin.ExecCommand.COMMANDS, {
/**
* Override for the insertunorderedlist method from the <a href="Plugin.EditorLists.html">EditorLists</a> plugin.
* @for ExecCommand
* @method COMMANDS.insertunorderedlist
* @static
* @param {String} cmd The command executed: insertunorderedlist
* @return {Node} Node instance of the item touched by this command.
*/
insertunorderedlist: function(cmd) {
var inst = this.get('host').getInstance(), out;
this.get('host')._execCommand(cmd, '');
},
/**
* Override for the insertorderedlist method from the <a href="Plugin.EditorLists.html">EditorLists</a> plugin.
* @for ExecCommand
* @method COMMANDS.insertorderedlist
* @static
* @param {String} cmd The command executed: insertorderedlist
* @return {Node} Node instance of the item touched by this command.
*/
insertorderedlist: function(cmd) {
var inst = this.get('host').getInstance(), out;
this.get('host')._execCommand(cmd, '');
}
});
}, '@VERSION@' ,{skinnable:false, requires:['editor-base']});