JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.6.3
[ckeditor.git] / _source / plugins / colordialog / dialogs / colordialog.js
index 61d411b..a8e83f5 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.\r
 For licensing, see LICENSE.html or http://ckeditor.com/license\r
 */\r
 \r
@@ -8,7 +8,6 @@ CKEDITOR.dialog.add( 'colordialog', function( editor )
                // Define some shorthands.\r
                var $el = CKEDITOR.dom.element,\r
                        $doc = CKEDITOR.document,\r
-                       $tools = CKEDITOR.tools,\r
                        lang = editor.lang.colordialog;\r
 \r
                // Reference the dialog.\r
@@ -20,34 +19,66 @@ CKEDITOR.dialog.add( 'colordialog', function( editor )
                        html : ' '\r
                };\r
 \r
+               var selected;\r
+\r
                function clearSelected()\r
                {\r
                        $doc.getById( selHiColorId ).removeStyle( 'background-color' );\r
                        dialog.getContentElement( 'picker', 'selectedColor' ).setValue( '' );\r
+                       selected && selected.removeAttribute( 'aria-selected' );\r
+                       selected = null;\r
                }\r
 \r
                function updateSelected( evt )\r
                {\r
-                       if ( ! ( evt instanceof CKEDITOR.dom.event ) )\r
-                               evt = new CKEDITOR.dom.event( evt );\r
-\r
-                       var target = evt.getTarget(),\r
+                       var target = evt.data.getTarget(),\r
                                color;\r
 \r
-                       if ( target.getName() == 'a' && ( color = target.getChild( 0 ).getHtml() ) )\r
+                       if ( target.getName() == 'td' &&\r
+                                ( color = target.getChild( 0 ).getHtml() ) )\r
+                       {\r
+                               selected = target;\r
+                               selected.setAttribute( 'aria-selected', true );\r
                                dialog.getContentElement( 'picker', 'selectedColor' ).setValue( color );\r
+                       }\r
+               }\r
+\r
+               // Basing black-white decision off of luma scheme using the Rec. 709 version\r
+               function whiteOrBlack( color )\r
+               {\r
+                       color = color.replace( /^#/, '' );\r
+                       for ( var i = 0, rgb = []; i <= 2; i++ )\r
+                               rgb[i] = parseInt( color.substr( i * 2, 2 ), 16 );\r
+                       var luma = (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]);\r
+                       return '#' + ( luma >= 165 ? '000' : 'fff' );\r
                }\r
 \r
+               // Distinguish focused and hover states.\r
+               var focused, hovered;\r
+\r
+               // Apply highlight style.\r
                function updateHighlight( event )\r
                {\r
-                       if ( ! ( event instanceof CKEDITOR.dom.event ) )\r
-                               event = event.data;\r
+                       // Convert to event.\r
+                       !event.name && ( event = new CKEDITOR.event( event ) );\r
 \r
-                       var target = event.getTarget(),\r
-                                       color;\r
+                       var isFocus = !(/mouse/).test( event.name ),\r
+                               target = event.data.getTarget(),\r
+                               color;\r
 \r
-                       if ( target.getName() == 'a' && ( color = target.getChild( 0 ).getHtml() ) )\r
+                       if ( target.getName() == 'td' && ( color = target.getChild( 0 ).getHtml() ) )\r
                        {\r
+                               removeHighlight( event );\r
+\r
+                               isFocus ? focused = target : hovered = target;\r
+\r
+                               // Apply outline style to show focus.\r
+                               if ( isFocus )\r
+                               {\r
+                                       target.setStyle( 'border-color', whiteOrBlack( color ) );\r
+                                       target.setStyle( 'border-style', 'dotted' );\r
+                               }\r
+\r
                                $doc.getById( hicolorId ).setStyle( 'background-color', color );\r
                                $doc.getById( hicolorTextId ).setHtml( color );\r
                        }\r
@@ -55,22 +86,41 @@ CKEDITOR.dialog.add( 'colordialog', function( editor )
 \r
                function clearHighlight()\r
                {\r
+                       var color = focused.getChild( 0 ).getHtml();\r
+                       focused.setStyle( 'border-color', color );\r
+                       focused.setStyle( 'border-style', 'solid' );\r
                        $doc.getById( hicolorId ).removeStyle( 'background-color' );\r
                        $doc.getById( hicolorTextId ).setHtml( '&nbsp;' );\r
+                       focused = null;\r
                }\r
 \r
-               var onMouseout = $tools.addFunction( clearHighlight ),\r
-                       onClick = updateSelected,\r
-                       onClickHandler = CKEDITOR.tools.addFunction( onClick ),\r
-                       onFocus = updateHighlight,\r
-                       onBlur = clearHighlight;\r
+               // Remove previously focused style.\r
+               function removeHighlight( event )\r
+               {\r
+                       var isFocus = !(/mouse/).test( event.name ),\r
+                               target = isFocus && focused;\r
+\r
+                       if ( target )\r
+                       {\r
+                               var color = target.getChild( 0 ).getHtml();\r
+                               target.setStyle( 'border-color', color );\r
+                               target.setStyle( 'border-style', 'solid' );\r
+                       }\r
+\r
+                       if ( ! ( focused || hovered ) )\r
+                       {\r
+                               $doc.getById( hicolorId ).removeStyle( 'background-color' );\r
+                               $doc.getById( hicolorTextId ).setHtml( '&nbsp;' );\r
+                       }\r
+               }\r
 \r
-               var onKeydownHandler = CKEDITOR.tools.addFunction( function( ev )\r
+               function onKeyStrokes( evt )\r
                {\r
-                       ev = new CKEDITOR.dom.event( ev );\r
-                       var element = ev.getTarget();\r
+                       var domEvt = evt.data;\r
+\r
+                       var element = domEvt.getTarget();\r
                        var relative, nodeToMove;\r
-                       var keystroke = ev.getKeystroke(),\r
+                       var keystroke = domEvt.getKeystroke(),\r
                                rtl = editor.lang.dir == 'rtl';\r
 \r
                        switch ( keystroke )\r
@@ -78,100 +128,93 @@ CKEDITOR.dialog.add( 'colordialog', function( editor )
                                // UP-ARROW\r
                                case 38 :\r
                                        // relative is TR\r
-                                       if ( ( relative = element.getParent().getParent().getPrevious() ) )\r
+                                       if ( ( relative = element.getParent().getPrevious() ) )\r
                                        {\r
-                                               nodeToMove = relative.getChild( [element.getParent().getIndex(), 0] );\r
+                                               nodeToMove = relative.getChild( [ element.getIndex() ] );\r
                                                nodeToMove.focus();\r
-                                               onBlur( ev, element );\r
-                                               onFocus( ev, nodeToMove );\r
                                        }\r
-                                       ev.preventDefault();\r
+                                       domEvt.preventDefault();\r
                                        break;\r
                                // DOWN-ARROW\r
                                case 40 :\r
                                        // relative is TR\r
-                                       if ( ( relative = element.getParent().getParent().getNext() ) )\r
+                                       if ( ( relative = element.getParent().getNext() ) )\r
                                        {\r
-                                               nodeToMove = relative.getChild( [ element.getParent().getIndex(), 0 ] );\r
+                                               nodeToMove = relative.getChild( [ element.getIndex() ] );\r
                                                if ( nodeToMove && nodeToMove.type == 1 )\r
                                                {\r
                                                        nodeToMove.focus();\r
-                                                       onBlur( ev, element );\r
-                                                       onFocus( ev, nodeToMove );\r
                                                }\r
                                        }\r
-                                       ev.preventDefault();\r
+                                       domEvt.preventDefault();\r
                                        break;\r
+\r
                                // SPACE\r
-                               // ENTER is already handled as onClick\r
+                               // ENTER\r
                                case 32 :\r
-                                       onClick( ev );\r
-                                       ev.preventDefault();\r
+                               case 13 :\r
+                                       updateSelected( evt );\r
+                                       domEvt.preventDefault();\r
                                        break;\r
 \r
                                // RIGHT-ARROW\r
                                case rtl ? 37 : 39 :\r
                                        // relative is TD\r
-                                       if ( ( relative = element.getParent().getNext() ) )\r
+                                       if ( ( nodeToMove = element.getNext() ) )\r
                                        {\r
-                                               nodeToMove = relative.getChild( 0 );\r
                                                if ( nodeToMove.type == 1 )\r
                                                {\r
                                                        nodeToMove.focus();\r
-                                                       onBlur( ev, element );\r
-                                                       onFocus( ev, nodeToMove );\r
-                                                       ev.preventDefault( true );\r
+                                                       domEvt.preventDefault( true );\r
                                                }\r
-                                               else\r
-                                                       onBlur( null, element );\r
                                        }\r
                                        // relative is TR\r
-                                       else if ( ( relative = element.getParent().getParent().getNext() ) )\r
+                                       else if ( ( relative = element.getParent().getNext() ) )\r
                                        {\r
-                                               nodeToMove = relative.getChild( [ 0, 0 ] );\r
+                                               nodeToMove = relative.getChild( [ 0 ] );\r
                                                if ( nodeToMove && nodeToMove.type == 1 )\r
                                                {\r
                                                        nodeToMove.focus();\r
-                                                       onBlur( ev, element );\r
-                                                       onFocus( ev, nodeToMove );\r
-                                                       ev.preventDefault( true );\r
+                                                       domEvt.preventDefault( true );\r
                                                }\r
-                                               else\r
-                                                       onBlur( null, element );\r
                                        }\r
                                        break;\r
 \r
                                // LEFT-ARROW\r
                                case rtl ? 39 : 37 :\r
                                        // relative is TD\r
-                                       if ( ( relative = element.getParent().getPrevious() ) )\r
+                                       if ( ( nodeToMove = element.getPrevious() ) )\r
                                        {\r
-                                               nodeToMove = relative.getChild( 0 );\r
                                                nodeToMove.focus();\r
-                                               onBlur( ev, element );\r
-                                               onFocus( ev, nodeToMove );\r
-                                               ev.preventDefault( true );\r
+                                               domEvt.preventDefault( true );\r
                                        }\r
                                        // relative is TR\r
-                                       else if ( ( relative = element.getParent().getParent().getPrevious() ) )\r
+                                       else if ( ( relative = element.getParent().getPrevious() ) )\r
                                        {\r
-                                               nodeToMove = relative.getLast().getChild( 0 );\r
+                                               nodeToMove = relative.getLast();\r
                                                nodeToMove.focus();\r
-                                               onBlur( ev, element );\r
-                                               onFocus( ev, nodeToMove );\r
-                                               ev.preventDefault( true );\r
+                                               domEvt.preventDefault( true );\r
                                        }\r
-                                       else\r
-                                               onBlur( null, element );\r
                                        break;\r
                                default :\r
                                        // Do not stop not handled events.\r
                                        return;\r
                        }\r
-               });\r
+               }\r
 \r
                function createColorTable()\r
                {\r
+                       table = CKEDITOR.dom.element.createFromHtml\r
+                       (\r
+                               '<table tabIndex="-1" aria-label="' + lang.options + '"' +\r
+                               ' role="grid" style="border-collapse:separate;" cellspacing="0">' +\r
+                               '<caption class="cke_voice_label">' + lang.options + '</caption>' +\r
+                               '<tbody role="presentation"></tbody></table>'\r
+                       );\r
+\r
+                       table.on( 'mouseover', updateHighlight );\r
+                       table.on( 'mouseout', removeHighlight );\r
+\r
                        // Create the base colors array.\r
                        var aColors = [ '00', '33', '66', '99', 'cc', 'ff' ];\r
 \r
@@ -180,13 +223,14 @@ CKEDITOR.dialog.add( 'colordialog', function( editor )
                        {\r
                                for ( var i = rangeA ; i < rangeA + 3 ; i++ )\r
                                {\r
-                                       var row = table.$.insertRow( -1 );\r
+                                       var row = new $el( table.$.insertRow( -1 ) );\r
+                                       row.setAttribute( 'role', 'row' );\r
 \r
                                        for ( var j = rangeB ; j < rangeB + 3 ; j++ )\r
                                        {\r
                                                for ( var n = 0 ; n < 6 ; n++ )\r
                                                {\r
-                                                       appendColorCell( row, '#' + aColors[j] + aColors[n] + aColors[i] );\r
+                                                       appendColorCell( row.$, '#' + aColors[j] + aColors[n] + aColors[i] );\r
                                                }\r
                                        }\r
                                }\r
@@ -197,20 +241,23 @@ CKEDITOR.dialog.add( 'colordialog', function( editor )
                        {\r
                                var cell = new $el( targetRow.insertCell( -1 ) );\r
                                cell.setAttribute( 'class', 'ColorCell' );\r
+                               cell.setAttribute( 'tabIndex', -1 );\r
+                               cell.setAttribute( 'role', 'gridcell' );\r
+\r
+                               cell.on( 'keydown', onKeyStrokes );\r
+                               cell.on( 'click', updateSelected );\r
+                               cell.on( 'focus', updateHighlight );\r
+                               cell.on( 'blur', removeHighlight );\r
+\r
                                cell.setStyle( 'background-color', color );\r
+                               cell.setStyle( 'border', '1px solid ' + color );\r
 \r
-                               cell.setStyle( 'width', '15px' );\r
-                               cell.setStyle( 'height', '15px' );\r
-\r
-                               var index = cell.$.cellIndex + 1 + 18 * targetRow.rowIndex;\r
-                               cell.append( CKEDITOR.dom.element.createFromHtml(\r
-                                               '<a href="javascript: void(0);" role="option"' +\r
-                                               ' aria-posinset="' + index + '"' +\r
-                                               ' aria-setsize="' + 13 * 18 + '"' +\r
-                                               ' style="cursor: pointer;display:block;width:100%;height:100% " title="'+ CKEDITOR.tools.htmlEncode( color )+ '"' +\r
-                                               ' onkeydown="CKEDITOR.tools.callFunction( ' + onKeydownHandler + ', event, this )"' +\r
-                                               ' onclick="CKEDITOR.tools.callFunction(' + onClickHandler + ', event, this ); return false;"' +\r
-                                               ' tabindex="-1"><span class="cke_voice_label">' + color + '</span>&nbsp;</a>', CKEDITOR.document ) );\r
+                               cell.setStyle( 'width', '14px' );\r
+                               cell.setStyle( 'height', '14px' );\r
+\r
+                               var colorLabel = numbering( 'color_table_cell' );\r
+                               cell.setAttribute( 'aria-labelledby',colorLabel );\r
+                               cell.append( CKEDITOR.dom.element.createFromHtml( '<span id="' + colorLabel + '" class="cke_voice_label">' + color + '</span>', CKEDITOR.document ) );\r
                        }\r
 \r
                        appendColorRow( 0, 0 );\r
@@ -219,25 +266,22 @@ CKEDITOR.dialog.add( 'colordialog', function( editor )
                        appendColorRow( 3, 3 );\r
 \r
                        // Create the last row.\r
-                       var oRow = table.$.insertRow(-1) ;\r
+                       var oRow = new $el( table.$.insertRow( -1 ) ) ;\r
+                       oRow.setAttribute( 'role', 'row' );\r
 \r
                        // Create the gray scale colors cells.\r
                        for ( var n = 0 ; n < 6 ; n++ )\r
                        {\r
-                               appendColorCell( oRow, '#' + aColors[n] + aColors[n] + aColors[n] ) ;\r
+                               appendColorCell( oRow.$, '#' + aColors[n] + aColors[n] + aColors[n] ) ;\r
                        }\r
 \r
                        // Fill the row with black cells.\r
                        for ( var i = 0 ; i < 12 ; i++ )\r
                        {\r
-                               appendColorCell( oRow, '#000000' ) ;\r
+                               appendColorCell( oRow.$, '#000000' ) ;\r
                        }\r
                }\r
 \r
-               var table = new $el( 'table' );\r
-               createColorTable();\r
-               var html = table.getHtml();\r
-\r
                var numbering = function( id )\r
                        {\r
                                return CKEDITOR.tools.getNextId() + '_' + id;\r
@@ -245,7 +289,9 @@ CKEDITOR.dialog.add( 'colordialog', function( editor )
                        hicolorId = numbering( 'hicolor' ),\r
                        hicolorTextId = numbering( 'hicolortext' ),\r
                        selHiColorId = numbering( 'selhicolor' ),\r
-                       tableLabelId = numbering( 'color_table_label' );\r
+                       table;\r
+\r
+               createColorTable();\r
 \r
                return {\r
                        title : lang.title,\r
@@ -256,6 +302,11 @@ CKEDITOR.dialog.add( 'colordialog', function( editor )
                                // Update reference.\r
                                dialog = this;\r
                        },\r
+                       onHide : function()\r
+                       {\r
+                               clearSelected();\r
+                               clearHighlight();\r
+                       },\r
                        contents : [\r
                                {\r
                                        id : 'picker',\r
@@ -271,20 +322,16 @@ CKEDITOR.dialog.add( 'colordialog', function( editor )
                                                        [\r
                                                                {\r
                                                                        type : 'html',\r
-                                                                       html :  '<table role="listbox" aria-labelledby="' + tableLabelId + '" onmouseout="CKEDITOR.tools.callFunction( ' + onMouseout + ' );">' +\r
-                                                                                       ( !CKEDITOR.env.webkit ? html : '' ) +\r
-                                                                               '</table><span id="' + tableLabelId + '" class="cke_voice_label">' + lang.options +'</span>',\r
+                                                                       html :  '<div></div>',\r
                                                                        onLoad : function()\r
                                                                        {\r
-                                                                               var table = CKEDITOR.document.getById( this.domId );\r
-                                                                               table.on( 'mouseover', updateHighlight );\r
-                                                                               // In WebKit, the table content must be inserted after this event call (#6150)\r
-                                                                               CKEDITOR.env.webkit && table.setHtml( html );\r
+                                                                               CKEDITOR.document.getById( this.domId ).append( table );\r
                                                                        },\r
-                                                                       focus: function()\r
+                                                                       focus : function()\r
                                                                        {\r
-                                                                               var firstColor = this.getElement().getElementsByTag( 'a' ).getItem( 0 );\r
-                                                                               firstColor.focus();\r
+                                                                               // Restore the previously focused cell,\r
+                                                                               // otherwise put the initial focus on the first table cell.\r
+                                                                               ( focused || this.getElement().getElementsByTag( 'td' ).getItem( 0 ) ).focus();\r
                                                                        }\r
                                                                },\r
                                                                spacer,\r