1 /*
  2 Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
  3 For licensing, see LICENSE.html or http://ckeditor.com/license
  4 */
  5 
  6 CKEDITOR.dialog.add( 'smiley', function( editor )
  7 {
  8 	var config = editor.config,
  9 		lang = editor.lang.smiley,
 10 		images = config.smiley_images,
 11 		columns = config.smiley_columns || 8,
 12 		i;
 13 
 14 	/**
 15 	 * Simulate "this" of a dialog for non-dialog events.
 16 	 * @type {CKEDITOR.dialog}
 17 	 */
 18 	var dialog;
 19 	var onClick = function( evt )
 20 	{
 21 		var target = evt.data.getTarget(),
 22 			targetName = target.getName();
 23 
 24 		if ( targetName == 'a' )
 25 			target = target.getChild( 0 );
 26 		else if ( targetName != 'img' )
 27 			return;
 28 
 29 		var src = target.getAttribute( 'cke_src' ),
 30 			title = target.getAttribute( 'title' );
 31 
 32 		var img = editor.document.createElement( 'img',
 33 			{
 34 				attributes :
 35 				{
 36 					src : src,
 37 					'data-cke-saved-src' : src,
 38 					title : title,
 39 					alt : title,
 40 					width : target.$.width,
 41 					height : target.$.height
 42 				}
 43 			});
 44 
 45 		editor.insertElement( img );
 46 
 47 		dialog.hide();
 48 		evt.data.preventDefault();
 49 	};
 50 
 51 	var onKeydown = CKEDITOR.tools.addFunction( function( ev, element )
 52 	{
 53 		ev = new CKEDITOR.dom.event( ev );
 54 		element = new CKEDITOR.dom.element( element );
 55 		var relative, nodeToMove;
 56 
 57 		var keystroke = ev.getKeystroke(),
 58 			rtl = editor.lang.dir == 'rtl';
 59 		switch ( keystroke )
 60 		{
 61 			// UP-ARROW
 62 			case 38 :
 63 				// relative is TR
 64 				if ( ( relative = element.getParent().getParent().getPrevious() ) )
 65 				{
 66 					nodeToMove = relative.getChild( [element.getParent().getIndex(), 0] );
 67 					nodeToMove.focus();
 68 				}
 69 				ev.preventDefault();
 70 				break;
 71 			// DOWN-ARROW
 72 			case 40 :
 73 				// relative is TR
 74 				if ( ( relative = element.getParent().getParent().getNext() ) )
 75 				{
 76 					nodeToMove = relative.getChild( [element.getParent().getIndex(), 0] );
 77 					if ( nodeToMove )
 78 						nodeToMove.focus();
 79 				}
 80 				ev.preventDefault();
 81 				break;
 82 			// ENTER
 83 			// SPACE
 84 			case 32 :
 85 				onClick( { data: ev } );
 86 				ev.preventDefault();
 87 				break;
 88 
 89 			// RIGHT-ARROW
 90 			case rtl ? 37 : 39 :
 91 				// relative is TD
 92 				if ( ( relative = element.getParent().getNext() ) )
 93 				{
 94 					nodeToMove = relative.getChild( 0 );
 95 					nodeToMove.focus();
 96 					ev.preventDefault(true);
 97 				}
 98 				// relative is TR
 99 				else if ( ( relative = element.getParent().getParent().getNext() ) )
100 				{
101 					nodeToMove = relative.getChild( [0, 0] );
102 					if ( nodeToMove )
103 						nodeToMove.focus();
104 					ev.preventDefault(true);
105 				}
106 				break;
107 
108 			// LEFT-ARROW
109 			case rtl ? 39 : 37 :
110 				// relative is TD
111 				if ( ( relative = element.getParent().getPrevious() ) )
112 				{
113 					nodeToMove = relative.getChild( 0 );
114 					nodeToMove.focus();
115 					ev.preventDefault(true);
116 				}
117 				// relative is TR
118 				else if ( ( relative = element.getParent().getParent().getPrevious() ) )
119 				{
120 					nodeToMove = relative.getLast().getChild( 0 );
121 					nodeToMove.focus();
122 					ev.preventDefault(true);
123 				}
124 				break;
125 			default :
126 				// Do not stop not handled events.
127 				return;
128 		}
129 	});
130 
131 	// Build the HTML for the smiley images table.
132 	var labelId = CKEDITOR.tools.getNextId() + '_smiley_emtions_label';
133 	var html =
134 	[
135 		'<div>' +
136 		'<span id="' + labelId + '" class="cke_voice_label">' + lang.options +'</span>',
137 		'<table role="listbox" aria-labelledby="' + labelId + '" style="width:100%;height:100%" cellspacing="2" cellpadding="2"',
138 		CKEDITOR.env.ie && CKEDITOR.env.quirks ? ' style="position:absolute;"' : '',
139 		'><tbody>'
140 	];
141 
142 	var size = images.length;
143 	for ( i = 0 ; i < size ; i++ )
144 	{
145 		if ( i % columns === 0 )
146 			html.push( '<tr role="presentation">' );
147 
148 		var smileyLabelId = 'cke_smile_label_' + i + '_' + CKEDITOR.tools.getNextNumber();
149 		html.push(
150 			'<td class="cke_dark_background cke_centered" style="vertical-align: middle;" role="presentation">' +
151 				'<a href="javascript:void(0)" role="option"',
152 					' aria-posinset="' + ( i +1 ) + '"',
153 					' aria-setsize="' + size + '"',
154 					' aria-labelledby="' + smileyLabelId + '"',
155 					' class="cke_smile cke_hand" tabindex="-1" onkeydown="CKEDITOR.tools.callFunction( ', onKeydown, ', event, this );">',
156 					'<img class="cke_hand" title="', config.smiley_descriptions[i], '"' +
157 						' cke_src="', CKEDITOR.tools.htmlEncode( config.smiley_path + images[ i ] ), '" alt="', config.smiley_descriptions[i], '"',
158 						' src="', CKEDITOR.tools.htmlEncode( config.smiley_path + images[ i ] ), '"',
159 						// IE BUG: Below is a workaround to an IE image loading bug to ensure the image sizes are correct.
160 						( CKEDITOR.env.ie ? ' onload="this.setAttribute(\'width\', 2); this.removeAttribute(\'width\');" ' : '' ),
161 					'>' +
162 					'<span id="' + smileyLabelId + '" class="cke_voice_label">' +config.smiley_descriptions[ i ]  + '</span>' +
163 				'</a>',
164  			'</td>' );
165 
166 		if ( i % columns == columns - 1 )
167 			html.push( '</tr>' );
168 	}
169 
170 	if ( i < columns - 1 )
171 	{
172 		for ( ; i < columns - 1 ; i++ )
173 			html.push( '<td></td>' );
174 		html.push( '</tr>' );
175 	}
176 
177 	html.push( '</tbody></table></div>' );
178 
179 	var smileySelector =
180 	{
181 		type : 'html',
182 		id : 'smileySelector',
183 		html : html.join( '' ),
184 		onLoad : function( event )
185 		{
186 			dialog = event.sender;
187 		},
188 		focus : function()
189 		{
190 			var self = this;
191 			// IE need a while to move the focus (#6539).
192 			setTimeout( function ()
193 			{
194 				var firstSmile = self.getElement().getElementsByTag( 'a' ).getItem( 0 );
195 				firstSmile.focus();
196 			}, 0 );
197 		},
198 		onClick : onClick,
199 		style : 'width: 100%; border-collapse: separate;'
200 	};
201 
202 	return {
203 		title : editor.lang.smiley.title,
204 		minWidth : 270,
205 		minHeight : 120,
206 		contents : [
207 			{
208 				id : 'tab1',
209 				label : '',
210 				title : '',
211 				expand : true,
212 				padding : 0,
213 				elements : [
214 						smileySelector
215 					]
216 			}
217 		],
218 		buttons : [ CKEDITOR.dialog.cancelButton ]
219 	};
220 } );
221