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( 'cellProperties', function( editor ) 7 { 8 var langTable = editor.lang.table, 9 langCell = langTable.cell, 10 langCommon = editor.lang.common, 11 validate = CKEDITOR.dialog.validate, 12 widthPattern = /^(\d+(?:\.\d+)?)(px|%)$/, 13 heightPattern = /^(\d+(?:\.\d+)?)px$/, 14 bind = CKEDITOR.tools.bind, 15 spacer = { type : 'html', html : ' ' }, 16 rtl = editor.lang.dir == 'rtl'; 17 18 /** 19 * 20 * @param dialogName 21 * @param callback [ childDialog ] 22 */ 23 function getDialogValue( dialogName, callback ) 24 { 25 var onOk = function() 26 { 27 releaseHandlers( this ); 28 callback( this, this._.parentDialog ); 29 this._.parentDialog.changeFocus(); 30 }; 31 var onCancel = function() 32 { 33 releaseHandlers( this ); 34 this._.parentDialog.changeFocus(); 35 }; 36 var releaseHandlers = function( dialog ) 37 { 38 dialog.removeListener( 'ok', onOk ); 39 dialog.removeListener( 'cancel', onCancel ); 40 }; 41 var bindToDialog = function( dialog ) 42 { 43 dialog.on( 'ok', onOk ); 44 dialog.on( 'cancel', onCancel ); 45 }; 46 editor.execCommand( dialogName ); 47 if ( editor._.storedDialogs.colordialog ) 48 bindToDialog( editor._.storedDialogs.colordialog ); 49 else 50 { 51 CKEDITOR.on( 'dialogDefinition', function( e ) 52 { 53 if ( e.data.name != dialogName ) 54 return; 55 56 var definition = e.data.definition; 57 58 e.removeListener(); 59 definition.onLoad = CKEDITOR.tools.override( definition.onLoad, function( orginal ) 60 { 61 return function() 62 { 63 bindToDialog( this ); 64 definition.onLoad = orginal; 65 if ( typeof orginal == 'function' ) 66 orginal.call( this ); 67 }; 68 } ); 69 }); 70 } 71 } 72 73 return { 74 title : langCell.title, 75 minWidth : CKEDITOR.env.ie && CKEDITOR.env.quirks? 450 : 410, 76 minHeight : CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.quirks )? 230 : 220, 77 contents : [ 78 { 79 id : 'info', 80 label : langCell.title, 81 accessKey : 'I', 82 elements : 83 [ 84 { 85 type : 'hbox', 86 widths : [ '40%', '5%', '40%' ], 87 children : 88 [ 89 { 90 type : 'vbox', 91 padding : 0, 92 children : 93 [ 94 { 95 type : 'hbox', 96 widths : [ '70%', '30%' ], 97 children : 98 [ 99 { 100 type : 'text', 101 id : 'width', 102 width: '100px', 103 label : langCommon.width, 104 validate : validate[ 'number' ]( langCell.invalidWidth ), 105 106 // Extra labelling of width unit type. 107 onLoad : function() 108 { 109 var widthType = this.getDialog().getContentElement( 'info', 'widthType' ), 110 labelElement = widthType.getElement(), 111 inputElement = this.getInputElement(), 112 ariaLabelledByAttr = inputElement.getAttribute( 'aria-labelledby' ); 113 114 inputElement.setAttribute( 'aria-labelledby', [ ariaLabelledByAttr, labelElement.$.id ].join( ' ' ) ); 115 }, 116 117 setup : function( element ) 118 { 119 var widthAttr = parseInt( element.getAttribute( 'width' ), 10 ), 120 widthStyle = parseInt( element.getStyle( 'width' ), 10 ); 121 122 !isNaN( widthAttr ) && this.setValue( widthAttr ); 123 !isNaN( widthStyle ) && this.setValue( widthStyle ); 124 }, 125 commit : function( element ) 126 { 127 var value = parseInt( this.getValue(), 10 ), 128 unit = this.getDialog().getValueOf( 'info', 'widthType' ); 129 130 if ( !isNaN( value ) ) 131 element.setStyle( 'width', value + unit ); 132 else 133 element.removeStyle( 'width' ); 134 135 element.removeAttribute( 'width' ); 136 }, 137 'default' : '' 138 }, 139 { 140 type : 'select', 141 id : 'widthType', 142 label : editor.lang.table.widthUnit, 143 labelStyle: 'visibility:hidden', 144 'default' : 'px', 145 items : 146 [ 147 [ langTable.widthPx, 'px' ], 148 [ langTable.widthPc, '%' ] 149 ], 150 setup : function( selectedCell ) 151 { 152 var widthMatch = widthPattern.exec( selectedCell.getStyle( 'width' ) || selectedCell.getAttribute( 'width' ) ); 153 if ( widthMatch ) 154 this.setValue( widthMatch[2] ); 155 } 156 } 157 ] 158 }, 159 { 160 type : 'hbox', 161 widths : [ '70%', '30%' ], 162 children : 163 [ 164 { 165 type : 'text', 166 id : 'height', 167 label : langCommon.height, 168 width: '100px', 169 'default' : '', 170 validate : validate[ 'number' ]( langCell.invalidHeight ), 171 172 // Extra labelling of height unit type. 173 onLoad : function() 174 { 175 var heightType = this.getDialog().getContentElement( 'info', 'htmlHeightType' ), 176 labelElement = heightType.getElement(), 177 inputElement = this.getInputElement(), 178 ariaLabelledByAttr = inputElement.getAttribute( 'aria-labelledby' ); 179 180 inputElement.setAttribute( 'aria-labelledby', [ ariaLabelledByAttr, labelElement.$.id ].join( ' ' ) ); 181 }, 182 183 setup : function( element ) 184 { 185 var heightAttr = parseInt( element.getAttribute( 'height' ), 10 ), 186 heightStyle = parseInt( element.getStyle( 'height' ), 10 ); 187 188 !isNaN( heightAttr ) && this.setValue( heightAttr ); 189 !isNaN( heightStyle ) && this.setValue( heightStyle ); 190 }, 191 commit : function( element ) 192 { 193 var value = parseInt( this.getValue(), 10 ); 194 195 if ( !isNaN( value ) ) 196 element.setStyle( 'height', CKEDITOR.tools.cssLength( value ) ); 197 else 198 element.removeStyle( 'height' ); 199 200 element.removeAttribute( 'height' ); 201 } 202 }, 203 { 204 id : 'htmlHeightType', 205 type : 'html', 206 html : '<br />'+ langTable.widthPx 207 } 208 ] 209 }, 210 spacer, 211 { 212 type : 'select', 213 id : 'wordWrap', 214 label : langCell.wordWrap, 215 'default' : 'yes', 216 items : 217 [ 218 [ langCell.yes, 'yes' ], 219 [ langCell.no, 'no' ] 220 ], 221 setup : function( element ) 222 { 223 var wordWrapAttr = element.getAttribute( 'noWrap' ), 224 wordWrapStyle = element.getStyle( 'white-space' ); 225 226 if ( wordWrapStyle == 'nowrap' || wordWrapAttr ) 227 this.setValue( 'no' ); 228 }, 229 commit : function( element ) 230 { 231 if ( this.getValue() == 'no' ) 232 element.setStyle( 'white-space', 'nowrap' ); 233 else 234 element.removeStyle( 'white-space' ); 235 236 element.removeAttribute( 'noWrap' ); 237 } 238 }, 239 spacer, 240 { 241 type : 'select', 242 id : 'hAlign', 243 label : langCell.hAlign, 244 'default' : '', 245 items : 246 [ 247 [ langCommon.notSet, '' ], 248 [ langCommon.alignLeft, 'left' ], 249 [ langCommon.alignCenter, 'center' ], 250 [ langCommon.alignRight, 'right' ] 251 ], 252 setup : function( element ) 253 { 254 var alignAttr = element.getAttribute( 'align' ), 255 textAlignStyle = element.getStyle( 'text-align'); 256 257 this.setValue( textAlignStyle || alignAttr || '' ); 258 }, 259 commit : function( selectedCell ) 260 { 261 var value = this.getValue(); 262 263 if ( value ) 264 selectedCell.setStyle( 'text-align', value ); 265 else 266 selectedCell.removeStyle( 'text-align' ); 267 268 selectedCell.removeAttribute( 'align' ); 269 } 270 }, 271 { 272 type : 'select', 273 id : 'vAlign', 274 label : langCell.vAlign, 275 'default' : '', 276 items : 277 [ 278 [ langCommon.notSet, '' ], 279 [ langCommon.alignTop, 'top' ], 280 [ langCommon.alignMiddle, 'middle' ], 281 [ langCommon.alignBottom, 'bottom' ], 282 [ langCell.alignBaseline, 'baseline' ] 283 ], 284 setup : function( element ) 285 { 286 var vAlignAttr = element.getAttribute( 'vAlign' ), 287 vAlignStyle = element.getStyle( 'vertical-align' ); 288 289 switch( vAlignStyle ) 290 { 291 // Ignore all other unrelated style values.. 292 case 'top': 293 case 'middle': 294 case 'bottom': 295 case 'baseline': 296 break; 297 default: 298 vAlignStyle = ''; 299 } 300 301 this.setValue( vAlignStyle || vAlignAttr || '' ); 302 }, 303 commit : function( element ) 304 { 305 var value = this.getValue(); 306 307 if ( value ) 308 element.setStyle( 'vertical-align', value ); 309 else 310 element.removeStyle( 'vertical-align' ); 311 312 element.removeAttribute( 'vAlign' ); 313 } 314 } 315 ] 316 }, 317 spacer, 318 { 319 type : 'vbox', 320 padding : 0, 321 children : 322 [ 323 { 324 type : 'select', 325 id : 'cellType', 326 label : langCell.cellType, 327 'default' : 'td', 328 items : 329 [ 330 [ langCell.data, 'td' ], 331 [ langCell.header, 'th' ] 332 ], 333 setup : function( selectedCell ) 334 { 335 this.setValue( selectedCell.getName() ); 336 }, 337 commit : function( selectedCell ) 338 { 339 selectedCell.renameNode( this.getValue() ); 340 } 341 }, 342 spacer, 343 { 344 type : 'text', 345 id : 'rowSpan', 346 label : langCell.rowSpan, 347 'default' : '', 348 validate : validate.integer( langCell.invalidRowSpan ), 349 setup : function( selectedCell ) 350 { 351 var attrVal = parseInt( selectedCell.getAttribute( 'rowSpan' ), 10 ); 352 if ( attrVal && attrVal != 1 ) 353 this.setValue( attrVal ); 354 }, 355 commit : function( selectedCell ) 356 { 357 var value = parseInt( this.getValue(), 10 ); 358 if ( value && value != 1 ) 359 selectedCell.setAttribute( 'rowSpan', this.getValue() ); 360 else 361 selectedCell.removeAttribute( 'rowSpan' ); 362 } 363 }, 364 { 365 type : 'text', 366 id : 'colSpan', 367 label : langCell.colSpan, 368 'default' : '', 369 validate : validate.integer( langCell.invalidColSpan ), 370 setup : function( element ) 371 { 372 var attrVal = parseInt( element.getAttribute( 'colSpan' ), 10 ); 373 if ( attrVal && attrVal != 1 ) 374 this.setValue( attrVal ); 375 }, 376 commit : function( selectedCell ) 377 { 378 var value = parseInt( this.getValue(), 10 ); 379 if ( value && value != 1 ) 380 selectedCell.setAttribute( 'colSpan', this.getValue() ); 381 else 382 selectedCell.removeAttribute( 'colSpan' ); 383 } 384 }, 385 spacer, 386 { 387 type : 'hbox', 388 padding : 0, 389 widths : [ '60%', '40%' ], 390 children : 391 [ 392 { 393 type : 'text', 394 id : 'bgColor', 395 label : langCell.bgColor, 396 'default' : '', 397 setup : function( element ) 398 { 399 var bgColorAttr = element.getAttribute( 'bgColor' ), 400 bgColorStyle = element.getStyle( 'background-color' ); 401 402 this.setValue( bgColorStyle || bgColorAttr ); 403 }, 404 commit : function( selectedCell ) 405 { 406 var value = this.getValue(); 407 408 if ( value ) 409 selectedCell.setStyle( 'background-color', this.getValue() ); 410 else 411 selectedCell.removeStyle( 'background-color' ); 412 413 selectedCell.removeAttribute( 'bgColor'); 414 } 415 }, 416 { 417 type : 'button', 418 id : 'bgColorChoose', 419 "class" : 'colorChooser', 420 label : langCell.chooseColor, 421 onLoad : function() 422 { 423 // Stick the element to the bottom (#5587) 424 this.getElement().getParent().setStyle( 'vertical-align', 'bottom' ); 425 }, 426 onClick : function() 427 { 428 var self = this; 429 getDialogValue( 'colordialog', function( colorDialog ) 430 { 431 self.getDialog().getContentElement( 'info', 'bgColor' ).setValue( 432 colorDialog.getContentElement( 'picker', 'selectedColor' ).getValue() 433 ); 434 } ); 435 } 436 } 437 ] 438 }, 439 spacer, 440 { 441 type : 'hbox', 442 padding : 0, 443 widths : [ '60%', '40%' ], 444 children : 445 [ 446 { 447 type : 'text', 448 id : 'borderColor', 449 label : langCell.borderColor, 450 'default' : '', 451 setup : function( element ) 452 { 453 var borderColorAttr = element.getAttribute( 'borderColor' ), 454 borderColorStyle = element.getStyle( 'border-color' ); 455 456 this.setValue( borderColorStyle || borderColorAttr ); 457 }, 458 commit : function( selectedCell ) 459 { 460 var value = this.getValue(); 461 if ( value ) 462 selectedCell.setStyle( 'border-color', this.getValue() ); 463 else 464 selectedCell.removeStyle( 'border-color' ); 465 466 selectedCell.removeAttribute( 'borderColor'); 467 } 468 }, 469 { 470 type : 'button', 471 id : 'borderColorChoose', 472 "class" : 'colorChooser', 473 label : langCell.chooseColor, 474 style : ( rtl ? 'margin-right' : 'margin-left' ) + ': 10px', 475 onLoad : function() 476 { 477 // Stick the element to the bottom (#5587) 478 this.getElement().getParent().setStyle( 'vertical-align', 'bottom' ); 479 }, 480 onClick : function() 481 { 482 var self = this; 483 getDialogValue( 'colordialog', function( colorDialog ) 484 { 485 self.getDialog().getContentElement( 'info', 'borderColor' ).setValue( 486 colorDialog.getContentElement( 'picker', 'selectedColor' ).getValue() 487 ); 488 } ); 489 } 490 } 491 ] 492 } 493 ] 494 } 495 ] 496 } 497 ] 498 } 499 ], 500 onShow : function() 501 { 502 this.cells = CKEDITOR.plugins.tabletools.getSelectedCells( 503 this._.editor.getSelection() ); 504 this.setupContent( this.cells[ 0 ] ); 505 }, 506 onOk : function() 507 { 508 var selection = this._.editor.getSelection(), 509 bookmarks = selection.createBookmarks(); 510 511 var cells = this.cells; 512 for ( var i = 0 ; i < cells.length ; i++ ) 513 this.commitContent( cells[ i ] ); 514 515 this._.editor.forceNextSelectionCheck(); 516 selection.selectBookmarks( bookmarks ); 517 this._.editor.selectionChange(); 518 } 519 }; 520 } ); 521