*/\r
var dialog,\r
lang = editor.lang.specialChar;\r
+\r
+ var insertSpecialChar = function ( specialChar )\r
+ {\r
+ var selection = editor.getSelection(),\r
+ ranges = selection.getRanges( true ),\r
+ range, textNode;\r
+\r
+ editor.fire( 'saveSnapshot' );\r
+\r
+ for ( var i = ranges.length - 1; i >= 0 ; i-- )\r
+ {\r
+ range = ranges[ i ];\r
+ range.deleteContents();\r
+\r
+ textNode = CKEDITOR.dom.element.createFromHtml( specialChar );\r
+ range.insertNode( textNode );\r
+ }\r
+\r
+ if ( range )\r
+ {\r
+ range.moveToPosition( textNode, CKEDITOR.POSITION_AFTER_END );\r
+ range.select();\r
+ }\r
+\r
+ editor.fire( 'saveSnapshot' );\r
+ };\r
+\r
var onChoice = function( evt )\r
{\r
var target, value;\r
{\r
target.removeClass( "cke_light_background" );\r
dialog.hide();\r
- editor.insertHtml( value );\r
+\r
+ // Firefox has bug on insert chars into a element use its own API. (#5170)\r
+ if ( CKEDITOR.env.gecko )\r
+ insertSpecialChar( value );\r
+ else\r
+ editor.insertHtml( value );\r
}\r
};\r
\r
var element = ev.getTarget();\r
var relative, nodeToMove;\r
var keystroke = ev.getKeystroke();\r
+ var rtl = editor.lang.dir == 'rtl';\r
\r
switch ( keystroke )\r
{\r
break;\r
\r
// RIGHT-ARROW\r
- case 39 :\r
+ case rtl ? 37 : 39 :\r
// TAB\r
case 9 :\r
// relative is TD\r
break;\r
\r
// LEFT-ARROW\r
- case 37 :\r
+ case rtl ? 39 : 37 :\r
// SHIFT + TAB\r
case CKEDITOR.SHIFT + 9 :\r
// relative is TD\r
var columns = this.definition.charColumns,\r
chars = this.definition.chars;\r
\r
- var html = [ '<table role="listbox" aria-labelledby="specialchar_table_label"' +\r
+ var charsTableLabel = CKEDITOR.tools.getNextId() + '_specialchar_table_label';\r
+ var html = [ '<table role="listbox" aria-labelledby="' + charsTableLabel + '"' +\r
' style="width: 320px; height: 100%; border-collapse: separate;"' +\r
' align="center" cellspacing="2" cellpadding="2" border="0">' ];\r
\r
// Use character in case description unavailable.\r
charDesc = charDesc || character;\r
\r
+ var charLabelId = 'cke_specialchar_label_' + i + '_' + CKEDITOR.tools.getNextNumber();\r
+\r
html.push(\r
- '<td class="cke_dark_background" style="cursor: default">' +\r
+ '<td class="cke_dark_background" style="cursor: default" role="presentation">' +\r
'<a href="javascript: void(0);" role="option"' +\r
' aria-posinset="' + ( i +1 ) + '"',\r
' aria-setsize="' + size + '"',\r
- ' aria-labelledby="cke_specialchar_label_' + i + '"',\r
+ ' aria-labelledby="' + charLabelId + '"',\r
' style="cursor: inherit; display: block; height: 1.25em; margin-top: 0.25em; text-align: center;" title="', CKEDITOR.tools.htmlEncode( charDesc ), '"' +\r
' onkeydown="CKEDITOR.tools.callFunction( ' + onKeydown + ', event, this )"' +\r
' onclick="CKEDITOR.tools.callFunction(' + onClick + ', this); return false;"' +\r
'<span style="margin: 0 auto;cursor: inherit">' +\r
character +\r
'</span>' +\r
- '<span class="cke_voice_label" id="cke_specialchar_label_' + i + '">' +\r
+ '<span class="cke_voice_label" id="' + charLabelId + '">' +\r
charDesc +\r
'</span></a>');\r
}\r
html.push( '</tr>' );\r
}\r
\r
- html.push( '</tbody></table>', '<span id="specialchar_table_label" class="cke_voice_label">' + editor.lang.common.options +'</span>' );\r
+ html.push( '</tbody></table>', '<span id="' + charsTableLabel + '" class="cke_voice_label">' + lang.options +'</span>' );\r
\r
this.getContentElement( 'info', 'charContainer' ).getElement().setHtml( html.join( '' ) );\r
},\r
{\r
firstChar.focus();\r
onFocus( null, firstChar );\r
- });\r
+ }, 0 );\r
},\r
onShow : function()\r
{\r
{\r
firstChar.focus();\r
onFocus( null, firstChar );\r
- });\r
+ }, 0 );\r
},\r
onLoad : function( event )\r
{\r