text: ﻿/*
   Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
   For licensing, see LICENSE.html or http://ckeditor.com/license
   */
  
  		(function ()
  		{
  			var meta =
  					{
  						editorFocus: false,
  						modes: {wysiwyg: 1, source: 1}
  					};
  
  			var blurCommand =
  					{
  						exec: function (editor)
  						{
  							editor.container.focusNext(true, editor.tabIndex);
  						}
  					};
  
  			var blurBackCommand =
  					{
  						exec: function (editor)
  						{
  							editor.container.focusPrevious(true, editor.tabIndex);
  						}
  					};
  
  			function selectNextCellCommand(backward)
  			{
  				return {
  					editorFocus: false,
  					canUndo: false,
  					modes: {wysiwyg: 1},
  					exec: function (editor)
  					{
  						if (editor.focusManager.hasFocus)
  						{
  							var sel = editor.getSelection(),
  									ancestor = sel.getCommonAncestor(),
  									cell;
  
  							if ((cell = (ancestor.getAscendant('td', true) || ancestor.getAscendant('th', true))))
  							{
  								var resultRange = new CKEDITOR.dom.range(editor.document),
  										next = CKEDITOR.tools.tryThese(function ()
  										{
  											var row = cell.getParent(),
  													next = row.$.cells[ cell.$.cellIndex + (backward ? -1 : 1) ];
  
  											// Invalid any empty value.
  											next.parentNode.parentNode;
  											return next;
  										},
  												function ()
  												{
  													var row = cell.getParent(),
  															table = row.getAscendant('table'),
  															nextRow = table.$.rows[ row.$.rowIndex + (backward ? -1 : 1) ];
  
  													return nextRow.cells[ backward ? nextRow.cells.length - 1 : 0 ];
  												});
  
  								// Clone one more row at the end of table and select the first newly established cell.
  								if (!(next || backward))
  								{
  									var table = cell.getAscendant('table').$,
  											cells = cell.getParent().$.cells;
  
  									var newRow = new CKEDITOR.dom.element(table.insertRow(-1), editor.document);
  
  									for (var i = 0, count = cells.length; i < count; i++)
  									{
  										var newCell = newRow.append(new CKEDITOR.dom.element(
  												cells[ i ], editor.document).clone(false, false));
  										!CKEDITOR.env.ie && newCell.appendBogus();
  									}
  
  									resultRange.moveToElementEditStart(newRow);
  								} else if (next)
  								{
  									next = new CKEDITOR.dom.element(next);
  									resultRange.moveToElementEditStart(next);
  									// Avoid selecting empty block makes the cursor blind.
  									if (!(resultRange.checkStartOfBlock() && resultRange.checkEndOfBlock()))
  										resultRange.selectNodeContents(next);
  								} else
  									return true;
  
  								resultRange.select(true);
  								return true;
  							}
  						}
  						return false;
  					}
  				};
  			}
  
  			CKEDITOR.plugins.add('tab',
  					{
  						requires: ['keystrokes'],
  
  						init: function (editor)
  						{
  							var tabTools = editor.config.enableTabKeyTools !== false,
  									tabSpaces = editor.config.tabSpaces || 0,
  									tabText = '';
  
  							while (tabSpaces--)
  								tabText += '\xa0';
  
  							if (tabText)
  							{
  								editor.on('key', function (ev)
  								{
  									if (ev.data.keyCode == 9)	// TAB
  									{
  										editor.insertHtml(tabText);
  										ev.cancel();
  									}
  								});
  							}
  
  							if (tabTools)
  							{
  								editor.on('key', function (ev)
  								{
  									if (ev.data.keyCode == 9 && editor.execCommand('selectNextCell') || // TAB
  											ev.data.keyCode == (CKEDITOR.SHIFT + 9) && editor.execCommand('selectPreviousCell'))	// SHIFT+TAB
  										ev.cancel();
  								});
  							}
  
  							if (CKEDITOR.env.webkit || CKEDITOR.env.gecko)
  							{
  								editor.on('key', function (ev)
  								{
  									var keyCode = ev.data.keyCode;
  
  									if (keyCode == 9 && !tabText)				// TAB
  									{
  										ev.cancel();
  										editor.execCommand('blur');
  									}
  
  									if (keyCode == (CKEDITOR.SHIFT + 9))	// SHIFT+TAB
  									{
  										editor.execCommand('blurBack');
  										ev.cancel();
  									}
  								});
  							}
  
  							editor.addCommand('blur', CKEDITOR.tools.extend(blurCommand, meta));
  							editor.addCommand('blurBack', CKEDITOR.tools.extend(blurBackCommand, meta));
  							editor.addCommand('selectNextCell', selectNextCellCommand());
  							editor.addCommand('selectPreviousCell', selectNextCellCommand(true));
  						}
  					});
  		})();
  
  /**
   * Moves the UI focus to the element following this element in the tabindex
   * order.
   * @example
   * var element = CKEDITOR.document.getById( 'example' );
   * element.focusNext();
   */
  CKEDITOR.dom.element.prototype.focusNext = function (ignoreChildren, indexToUse)
  {
  	var $ = this.$,
  			curTabIndex = (indexToUse === undefined ? this.getTabIndex() : indexToUse),
  			passedCurrent, enteredCurrent,
  			elected, electedTabIndex,
  			element, elementTabIndex;
  
  	if (curTabIndex <= 0)
  	{
  		// If this element has tabindex <= 0 then we must simply look for any
  		// element following it containing tabindex=0.
  
  		element = this.getNextSourceNode(ignoreChildren, CKEDITOR.NODE_ELEMENT);
  
  		while (element)
  		{
  			if (element.isVisible() && element.getTabIndex() === 0)
  			{
  				elected = element;
  				break;
  			}
  
  			element = element.getNextSourceNode(false, CKEDITOR.NODE_ELEMENT);
  		}
  	} else
  	{
  		// If this element has tabindex > 0 then we must look for:
  		//		1. An element following this element with the same tabindex.
  		//		2. The first element in source other with the lowest tabindex
  		//		   that is higher than this element tabindex.
  		//		3. The first element with tabindex=0.
  
  		element = this.getDocument().getBody().getFirst();
  
  		while ((element = element.getNextSourceNode(false, CKEDITOR.NODE_ELEMENT)))
  		{
  			if (!passedCurrent)
  			{
  				if (!enteredCurrent && element.equals(this))
  				{
  					enteredCurrent = true;
  
  					// Ignore this element, if required.
  					if (ignoreChildren)
  					{
  						if (!(element = element.getNextSourceNode(true, CKEDITOR.NODE_ELEMENT)))
  							break;
  						passedCurrent = 1;
  					}
  				} else if (enteredCurrent && !this.contains(element))
  					passedCurrent = 1;
  			}
  
  			if (!element.isVisible() || (elementTabIndex = element.getTabIndex()) < 0)
  				continue;
  
  			if (passedCurrent && elementTabIndex == curTabIndex)
  			{
  				elected = element;
  				break;
  			}
  
  			if (elementTabIndex > curTabIndex && (!elected || !electedTabIndex || elementTabIndex < electedTabIndex))
  			{
  				elected = element;
  				electedTabIndex = elementTabIndex;
  			} else if (!elected && elementTabIndex === 0)
  			{
  				elected = element;
  				electedTabIndex = elementTabIndex;
  			}
  		}
  	}
  
  	if (elected)
  		elected.focus();
  };
  
  /**
   * Moves the UI focus to the element before this element in the tabindex order.
   * @example
   * var element = CKEDITOR.document.getById( 'example' );
   * element.focusPrevious();
   */
  CKEDITOR.dom.element.prototype.focusPrevious = function (ignoreChildren, indexToUse)
  {
  	var $ = this.$,
  			curTabIndex = (indexToUse === undefined ? this.getTabIndex() : indexToUse),
  			passedCurrent, enteredCurrent,
  			elected,
  			electedTabIndex = 0,
  			elementTabIndex;
  
  	var element = this.getDocument().getBody().getLast();
  
  	while ((element = element.getPreviousSourceNode(false, CKEDITOR.NODE_ELEMENT)))
  	{
  		if (!passedCurrent)
  		{
  			if (!enteredCurrent && element.equals(this))
  			{
  				enteredCurrent = true;
  
  				// Ignore this element, if required.
  				if (ignoreChildren)
  				{
  					if (!(element = element.getPreviousSourceNode(true, CKEDITOR.NODE_ELEMENT)))
  						break;
  					passedCurrent = 1;
  				}
  			} else if (enteredCurrent && !this.contains(element))
  				passedCurrent = 1;
  		}
  
  		if (!element.isVisible() || (elementTabIndex = element.getTabIndex()) < 0)
  			continue;
  
  		if (curTabIndex <= 0)
  		{
  			// If this element has tabindex <= 0 then we must look for:
  			//		1. An element before this one containing tabindex=0.
  			//		2. The last element with the highest tabindex.
  
  			if (passedCurrent && elementTabIndex === 0)
  			{
  				elected = element;
  				break;
  			}
  
  			if (elementTabIndex > electedTabIndex)
  			{
  				elected = element;
  				electedTabIndex = elementTabIndex;
  			}
  		} else
  		{
  			// If this element has tabindex > 0 we must look for:
  			//		1. An element preceeding this one, with the same tabindex.
  			//		2. The last element in source other with the highest tabindex
  			//		   that is lower than this element tabindex.
  
  			if (passedCurrent && elementTabIndex == curTabIndex)
  			{
  				elected = element;
  				break;
  			}
  
  			if (elementTabIndex < curTabIndex && (!elected || elementTabIndex > electedTabIndex))
  			{
  				elected = element;
  				electedTabIndex = elementTabIndex;
  			}
  		}
  	}
  
  	if (elected)
  		elected.focus();
  };
  
  /**
   * Intructs the editor to add a number of spaces (&amp;nbsp;) to the text when
   * hitting the TAB key. If set to zero, the TAB key will be used to move the
   * cursor focus to the next element in the page, out of the editor focus.
   * @name CKEDITOR.config.tabSpaces
   * @type Number
   * @default 0
   * @example
   * config.tabSpaces = 4;
   */
  
  /**
   * Allow context-sensitive tab key behaviors, including the following scenarios:
   * <h5>When selection is anchored inside <b>table cells</b>:</h5>
   * <ul>
   * 		<li>If TAB is pressed, select the contents of the "next" cell. If in the last cell in the table, add a new row to it and focus its first cell.</li>
   * 		<li>If SHIFT+TAB is pressed, select the contents of the "previous" cell. Do nothing when it's in the first cell.</li>
   * </ul>
   * @name CKEDITOR.config.enableTabKeyTools
   * @type Boolean
   * @default true
   * @example
   * config.enableTabKeyTools = false;
   */
  
  // If the TAB key is not supposed to be enabled for navigation, the following
  // settings could be used alternatively:
  // config.keystrokes.push(
  //	[ CKEDITOR.ALT + 38 /*Arrow Up*/, 'selectPreviousCell' ],
  //	[ CKEDITOR.ALT + 40 /*Arrow Down*/, 'selectNextCell' ]
  // );
  