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