text: ﻿/*
  Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
  For licensing, see LICENSE.html or http://ckeditor.com/license
  */
  
  CKEDITOR.dialog.add( 'colordialog', function( editor )
  	{
  		// Define some shorthands.
  		var $el = CKEDITOR.dom.element,
  			$doc = CKEDITOR.document,
  			lang = editor.lang.colordialog;
  
  		// Reference the dialog.
  		var dialog;
  
  		var spacer =
  		{
  			type : 'html',
  			html : '&nbsp;'
  		};
  
  		var selected;
  
  		function clearSelected()
  		{
  			$doc.getById( selHiColorId ).removeStyle( 'background-color' );
  			dialog.getContentElement( 'picker', 'selectedColor' ).setValue( '' );
  			selected && selected.removeAttribute( 'aria-selected' );
  			selected = null;
  		}
  
  		function updateSelected( evt )
  		{
  			var target = evt.data.getTarget(),
  				color;
  
  			if ( target.getName() == 'td' &&
  				 ( color = target.getChild( 0 ).getHtml() ) )
  			{
  				selected = target;
  				selected.setAttribute( 'aria-selected', true );
  				dialog.getContentElement( 'picker', 'selectedColor' ).setValue( color );
  			}
  		}
  
  		// Basing black-white decision off of luma scheme using the Rec. 709 version
  		function whiteOrBlack( color )
  		{
  			color = color.replace( /^#/, '' );
  			for ( var i = 0, rgb = []; i <= 2; i++ )
  				rgb[i] = parseInt( color.substr( i * 2, 2 ), 16 );
  			var luma = (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]);
  			return '#' + ( luma >= 165 ? '000' : 'fff' );
  		}
  
  		// Distinguish focused and hover states.
  		var focused, hovered;
  
  		// Apply highlight style.
  		function updateHighlight( event )
  		{
  			// Convert to event.
  			!event.name && ( event = new CKEDITOR.event( event ) );
  
  			var isFocus = !(/mouse/).test( event.name ),
  				target = event.data.getTarget(),
  				color;
  
  			if ( target.getName() == 'td' && ( color = target.getChild( 0 ).getHtml() ) )
  			{
  				removeHighlight( event );
  
  				isFocus ? focused = target : hovered = target;
  
  				// Apply outline style to show focus.
  				if ( isFocus )
  				{
  					target.setStyle( 'border-color', whiteOrBlack( color ) );
  					target.setStyle( 'border-style', 'dotted' );
  				}
  
  				$doc.getById( hicolorId ).setStyle( 'background-color', color );
  				$doc.getById( hicolorTextId ).setHtml( color );
  			}
  		}
  
  		function clearHighlight()
  		{
  			var color = focused.getChild( 0 ).getHtml();
  			focused.setStyle( 'border-color', color );
  			focused.setStyle( 'border-style', 'solid' );
  			$doc.getById( hicolorId ).removeStyle( 'background-color' );
  			$doc.getById( hicolorTextId ).setHtml( '&nbsp;' );
  			focused = null;
  		}
  
  		// Remove previously focused style.
  		function removeHighlight( event )
  		{
  			var isFocus = !(/mouse/).test( event.name ),
  				target = isFocus && focused;
  
  			if ( target )
  			{
  				var color = target.getChild( 0 ).getHtml();
  				target.setStyle( 'border-color', color );
  				target.setStyle( 'border-style', 'solid' );
  			}
  
  			if ( ! ( focused || hovered ) )
  			{
  				$doc.getById( hicolorId ).removeStyle( 'background-color' );
  				$doc.getById( hicolorTextId ).setHtml( '&nbsp;' );
  			}
  		}
  
  		function onKeyStrokes( evt )
  		{
  			var domEvt = evt.data;
  
  			var element = domEvt.getTarget();
  			var relative, nodeToMove;
  			var keystroke = domEvt.getKeystroke(),
  				rtl = editor.lang.dir == 'rtl';
  
  			switch ( keystroke )
  			{
  				// UP-ARROW
  				case 38 :
  					// relative is TR
  					if ( ( relative = element.getParent().getPrevious() ) )
  					{
  						nodeToMove = relative.getChild( [ element.getIndex() ] );
  						nodeToMove.focus();
  					}
  					domEvt.preventDefault();
  					break;
  				// DOWN-ARROW
  				case 40 :
  					// relative is TR
  					if ( ( relative = element.getParent().getNext() ) )
  					{
  						nodeToMove = relative.getChild( [ element.getIndex() ] );
  						if ( nodeToMove && nodeToMove.type == 1 )
  						{
  							nodeToMove.focus();
  						}
  					}
  					domEvt.preventDefault();
  					break;
  
  				// SPACE
  				// ENTER
  				case 32 :
  				case 13 :
  					updateSelected( evt );
  					domEvt.preventDefault();
  					break;
  
  				// RIGHT-ARROW
  				case rtl ? 37 : 39 :
  					// relative is TD
  					if ( ( nodeToMove = element.getNext() ) )
  					{
  						if ( nodeToMove.type == 1 )
  						{
  							nodeToMove.focus();
  							domEvt.preventDefault( true );
  						}
  					}
  					// relative is TR
  					else if ( ( relative = element.getParent().getNext() ) )
  					{
  						nodeToMove = relative.getChild( [ 0 ] );
  						if ( nodeToMove && nodeToMove.type == 1 )
  						{
  							nodeToMove.focus();
  							domEvt.preventDefault( true );
  						}
  					}
  					break;
  
  				// LEFT-ARROW
  				case rtl ? 39 : 37 :
  					// relative is TD
  					if ( ( nodeToMove = element.getPrevious() ) )
  					{
  						nodeToMove.focus();
  						domEvt.preventDefault( true );
  					}
  					// relative is TR
  					else if ( ( relative = element.getParent().getPrevious() ) )
  					{
  						nodeToMove = relative.getLast();
  						nodeToMove.focus();
  						domEvt.preventDefault( true );
  					}
  					break;
  				default :
  					// Do not stop not handled events.
  					return;
  			}
  		}
  
  		function createColorTable()
  		{
  			table = CKEDITOR.dom.element.createFromHtml
  			(
  				'<table tabIndex="-1" aria-label="' + lang.options + '"' +
  				' role="grid" style="border-collapse:separate;" cellspacing="0">' +
  				'<caption class="cke_voice_label">' + lang.options + '</caption>' +
  				'<tbody role="presentation"></tbody></table>'
  			);
  
  			table.on( 'mouseover', updateHighlight );
  			table.on( 'mouseout', removeHighlight );
  
  			// Create the base colors array.
  			var aColors = [ '00', '33', '66', '99', 'cc', 'ff' ];
  
  			// This function combines two ranges of three values from the color array into a row.
  			function appendColorRow( rangeA, rangeB )
  			{
  				for ( var i = rangeA ; i < rangeA + 3 ; i++ )
  				{
  					var row = new $el( table.$.insertRow( -1 ) );
  					row.setAttribute( 'role', 'row' );
  
  					for ( var j = rangeB ; j < rangeB + 3 ; j++ )
  					{
  						for ( var n = 0 ; n < 6 ; n++ )
  						{
  							appendColorCell( row.$, '#' + aColors[j] + aColors[n] + aColors[i] );
  						}
  					}
  				}
  			}
  
  			// This function create a single color cell in the color table.
  			function appendColorCell( targetRow, color )
  			{
  				var cell = new $el( targetRow.insertCell( -1 ) );
  				cell.setAttribute( 'class', 'ColorCell' );
  				cell.setAttribute( 'tabIndex', -1 );
  				cell.setAttribute( 'role', 'gridcell' );
  
  				cell.on( 'keydown', onKeyStrokes );
  				cell.on( 'click', updateSelected );
  				cell.on( 'focus', updateHighlight );
  				cell.on( 'blur', removeHighlight );
  
  				cell.setStyle( 'background-color', color );
  				cell.setStyle( 'border', '1px solid ' + color );
  
  				cell.setStyle( 'width', '14px' );
  				cell.setStyle( 'height', '14px' );
  
  				var colorLabel = numbering( 'color_table_cell' );
  				cell.setAttribute( 'aria-labelledby',colorLabel );
  				cell.append( CKEDITOR.dom.element.createFromHtml( '<span id="' + colorLabel + '" class="cke_voice_label">' + color + '</span>', CKEDITOR.document ) );
  			}
  
  			appendColorRow( 0, 0 );
  			appendColorRow( 3, 0 );
  			appendColorRow( 0, 3 );
  			appendColorRow( 3, 3 );
  
  			// Create the last row.
  			var oRow = new $el( table.$.insertRow( -1 ) ) ;
  			oRow.setAttribute( 'role', 'row' );
  
  			// Create the gray scale colors cells.
  			for ( var n = 0 ; n < 6 ; n++ )
  			{
  				appendColorCell( oRow.$, '#' + aColors[n] + aColors[n] + aColors[n] ) ;
  			}
  
  			// Fill the row with black cells.
  			for ( var i = 0 ; i < 12 ; i++ )
  			{
  				appendColorCell( oRow.$, '#000000' ) ;
  			}
  		}
  
  		var numbering = function( id )
  			{
  				return CKEDITOR.tools.getNextId() + '_' + id;
  			},
  			hicolorId = numbering( 'hicolor' ),
  			hicolorTextId = numbering( 'hicolortext' ),
  			selHiColorId = numbering( 'selhicolor' ),
  			table;
  
  		createColorTable();
  
  		return {
  			title : lang.title,
  			minWidth : 360,
  			minHeight : 220,
  			onLoad : function()
  			{
  				// Update reference.
  				dialog = this;
  			},
  			onHide : function()
  			{
  				clearSelected();
  				clearHighlight();
  			},
  			contents : [
  				{
  					id : 'picker',
  					label : lang.title,
  					accessKey : 'I',
  					elements :
  					[
  						{
  							type : 'hbox',
  							padding : 0,
  							widths : [ '70%', '10%', '30%' ],
  							children :
  							[
  								{
  									type : 'html',
  									html :	'<div></div>',
  									onLoad : function()
  									{
  										CKEDITOR.document.getById( this.domId ).append( table );
  									},
  									focus : function()
  									{
  										// Restore the previously focused cell,
  										// otherwise put the initial focus on the first table cell.
  										( focused || this.getElement().getElementsByTag( 'td' ).getItem( 0 ) ).focus();
  									}
  								},
  								spacer,
  								{
  									type : 'vbox',
  									padding : 0,
  									widths : [ '70%', '5%', '25%' ],
  									children :
  									[
  										{
  											type : 'html',
  											html : '<span>' + lang.highlight +'</span>\
  												<div id="' + hicolorId + '" style="border: 1px solid; height: 74px; width: 74px;"></div>\
  												<div id="' + hicolorTextId + '">&nbsp;</div><span>' + lang.selected + '</span>\
  												<div id="' + selHiColorId + '" style="border: 1px solid; height: 20px; width: 74px;"></div>'
  										},
  										{
  											type : 'text',
  											label : lang.selected,
  											labelStyle: 'display:none',
  											id : 'selectedColor',
  											style : 'width: 74px',
  											onChange : function()
  											{
  												// Try to update color preview with new value. If fails, then set it no none.
  												try
  												{
  													$doc.getById( selHiColorId ).setStyle( 'background-color', this.getValue() );
  												}
  												catch ( e )
  												{
  													clearSelected();
  												}
  											}
  										},
  										spacer,
  										{
  											type : 'button',
  											id : 'clear',
  											style : 'margin-top: 5px',
  											label : lang.clear,
  											onClick : clearSelected
  										}
  									]
  								}
  							]
  						}
  					]
  				}
  			]
  		};
  	}
  	);
  