1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 CKEDITOR.plugins.add( 'button', 7 { 8 beforeInit : function( editor ) 9 { 10 editor.ui.addHandler( CKEDITOR.UI_BUTTON, CKEDITOR.ui.button.handler ); 11 } 12 }); 13 14 /** 15 * Button UI element. 16 * @constant 17 * @example 18 */ 19 CKEDITOR.UI_BUTTON = 1; 20 21 /** 22 * Represents a button UI element. This class should not be called directly. To 23 * create new buttons use {@link CKEDITOR.ui.prototype.addButton} instead. 24 * @constructor 25 * @param {Object} definition The button definition. 26 * @example 27 */ 28 CKEDITOR.ui.button = function( definition ) 29 { 30 // Copy all definition properties to this object. 31 CKEDITOR.tools.extend( this, definition, 32 // Set defaults. 33 { 34 title : definition.label, 35 className : definition.className || ( definition.command && 'cke_button_' + definition.command ) || '', 36 click : definition.click || function( editor ) 37 { 38 editor.execCommand( definition.command ); 39 } 40 }); 41 42 this._ = {}; 43 }; 44 45 /** 46 * Transforms a button definition in a {@link CKEDITOR.ui.button} instance. 47 * @type Object 48 * @example 49 */ 50 CKEDITOR.ui.button.handler = 51 { 52 create : function( definition ) 53 { 54 return new CKEDITOR.ui.button( definition ); 55 } 56 }; 57 58 CKEDITOR.ui.button.prototype = 59 { 60 canGroup : true, 61 62 /** 63 * Renders the button. 64 * @param {CKEDITOR.editor} editor The editor instance which this button is 65 * to be used by. 66 * @param {Array} output The output array to which append the HTML relative 67 * to this button. 68 * @example 69 */ 70 render : function( editor, output ) 71 { 72 var env = CKEDITOR.env; 73 74 var id = this._.id = 'cke_' + CKEDITOR.tools.getNextNumber(); 75 this._.editor = editor; 76 77 var instance = 78 { 79 id : id, 80 button : this, 81 editor : editor, 82 focus : function() 83 { 84 var element = CKEDITOR.document.getById( id ); 85 element.focus(); 86 }, 87 execute : function() 88 { 89 this.button.click( editor ); 90 } 91 }; 92 93 var clickFn = CKEDITOR.tools.addFunction( instance.execute, instance ); 94 95 var index = CKEDITOR.ui.button._.instances.push( instance ) - 1; 96 97 var classes = ''; 98 99 // Get the command name. 100 var command = this.command; 101 102 if ( command ) 103 { 104 // Get the command instance. 105 command = editor.getCommand( command ); 106 107 if ( command ) 108 { 109 command.on( 'state', function() 110 { 111 this.setState( command.state ); 112 }, this); 113 114 classes += 'cke_' + ( 115 command.state == CKEDITOR.TRISTATE_ON ? 'on' : 116 command.state == CKEDITOR.TRISTATE_DISABLED ? 'disabled' : 117 'off' ); 118 } 119 } 120 121 if ( !command ) 122 classes += 'cke_off'; 123 124 if ( this.className ) 125 classes += ' ' + this.className; 126 127 output.push( 128 '<span class="cke_button">', 129 '<a id="', id, '"' + 130 ' class="', classes, '" href="javascript:void(\'', ( this.title || '' ).replace( "'", '' ), '\')"' + 131 ' title="', this.title, '"' + 132 ' tabindex="-1"' + 133 ' role="button"' + 134 ' hidefocus="true"' ); 135 136 // Some browsers don't cancel key events in the keydown but in the 137 // keypress. 138 // TODO: Check if really needed for Gecko+Mac. 139 if ( env.opera || ( env.gecko && env.mac ) ) 140 { 141 output.push( 142 ' onkeypress="return false;"' ); 143 } 144 145 // With Firefox, we need to force the button to redraw, otherwise it 146 // will remain in the focus state. 147 if ( env.gecko ) 148 { 149 output.push( 150 ' onblur="this.style.cssText = this.style.cssText;"' ); 151 } 152 153 output.push( 154 ' onkeydown="return CKEDITOR.ui.button._.keydown(', index, ', event);"' + 155 ' onfocus="return CKEDITOR.ui.button._.focus(', index, ', event);"' + 156 ' onclick="CKEDITOR.tools.callFunction(', clickFn, ', this); return false;">' + 157 '<span class="cke_icon"' ); 158 159 if ( this.icon ) 160 { 161 var offset = ( this.iconOffset || 0 ) * -16; 162 output.push( ' style="background-image:url(', CKEDITOR.getUrl( this.icon ), ');background-position:0 ' + offset + 'px;"' ); 163 } 164 165 output.push( 166 '></span>' + 167 '<span class="cke_label">', this.label, '</span>' ); 168 169 if ( this.hasArrow ) 170 { 171 output.push( 172 '<span class="cke_buttonarrow"></span>' ); 173 } 174 175 output.push( 176 '</a>', 177 '</span>' ); 178 179 if ( this.onRender ) 180 this.onRender(); 181 182 return instance; 183 }, 184 185 setState : function( state ) 186 { 187 if ( this._.state == state ) 188 return; 189 190 var element = CKEDITOR.document.getById( this._.id ); 191 192 if ( element ) 193 { 194 element.setState( state ); 195 196 var htmlTitle = this.title, 197 unavailable = this._.editor.lang.common.unavailable, 198 labelElement = element.getChild( 1 ); 199 200 if ( state == CKEDITOR.TRISTATE_DISABLED ) 201 htmlTitle = unavailable.replace( '%1', this.title ); 202 203 labelElement.setHtml( htmlTitle ); 204 } 205 206 this._.state = state; 207 } 208 }; 209 210 /** 211 * Handles a button click. 212 * @private 213 */ 214 CKEDITOR.ui.button._ = 215 { 216 instances : [], 217 218 keydown : function( index, ev ) 219 { 220 var instance = CKEDITOR.ui.button._.instances[ index ]; 221 222 if ( instance.onkey ) 223 { 224 ev = new CKEDITOR.dom.event( ev ); 225 return ( instance.onkey( instance, ev.getKeystroke() ) !== false ); 226 } 227 }, 228 229 focus : function( index, ev ) 230 { 231 var instance = CKEDITOR.ui.button._.instances[ index ], 232 retVal; 233 234 if ( instance.onfocus ) 235 retVal = ( instance.onfocus( instance, new CKEDITOR.dom.event( ev ) ) !== false ); 236 237 // FF2: prevent focus event been bubbled up to editor container, which caused unexpected editor focus. 238 if ( CKEDITOR.env.gecko && CKEDITOR.env.version < 10900 ) 239 ev.preventBubble(); 240 return retVal; 241 } 242 }; 243 244 /** 245 * Adds a button definition to the UI elements list. 246 * @param {String} The button name. 247 * @param {Object} The button definition. 248 * @example 249 * editorInstance.ui.addButton( 'MyBold', 250 * { 251 * label : 'My Bold', 252 * command : 'bold' 253 * }); 254 */ 255 CKEDITOR.ui.prototype.addButton = function( name, definition ) 256 { 257 this.add( name, CKEDITOR.UI_BUTTON, definition ); 258 }; 259