1/** 2 * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. 3 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license 4 */ 5 6CKEDITOR.dialog.add( 'cellProperties', function( editor ) { 7 var langTable = editor.lang.table, 8 langCell = langTable.cell, 9 langCommon = editor.lang.common, 10 validate = CKEDITOR.dialog.validate, 11 widthPattern = /^(\d+(?:\.\d+)?)(px|%)$/, 12 spacer = { type: 'html', html: ' ' }, 13 hiddenSpacer, 14 rtl = editor.lang.dir == 'rtl', 15 colorDialog = editor.plugins.colordialog; 16 17 // Returns a function, which runs regular "setup" for all selected cells to find out 18 // whether the initial value of the field would be the same for all cells. If so, 19 // the value is displayed just as if a regular "setup" was executed. Otherwise, 20 // i.e. when there are several cells of different value of the property, a field 21 // gets empty value. 22 // 23 // * @param {Function} setup Setup function which returns a value instead of setting it. 24 // * @returns {Function} A function to be used in dialog definition. 25 function setupCells( setup ) { 26 return function( cells ) { 27 var fieldValue = setup( cells[ 0 ] ); 28 29 // If one of the cells would have a different value of the 30 // property, set the empty value for a field. 31 for ( var i = 1; i < cells.length; i++ ) { 32 if ( setup( cells[ i ] ) !== fieldValue ) { 33 fieldValue = null; 34 break; 35 } 36 } 37 38 // Setting meaningful or empty value only makes sense 39 // when setup returns some value. Otherwise, a *default* value 40 // is used for that field. 41 if ( typeof fieldValue != 'undefined' ) { 42 this.setValue( fieldValue ); 43 44 // The only way to have an empty select value in Firefox is 45 // to set a negative selectedIndex. 46 if ( CKEDITOR.env.gecko && this.type == 'select' && !fieldValue ) 47 this.getInputElement().$.selectedIndex = -1; 48 } 49 }; 50 } 51 52 // Reads the unit of width property of the table cell. 53 // 54 // * @param {CKEDITOR.dom.element} cell An element representing table cell. 55 // * @returns {String} A unit of width: 'px', '%' or undefined if none. 56 function getCellWidthType( cell ) { 57 var match = widthPattern.exec( 58 cell.getStyle( 'width' ) || cell.getAttribute( 'width' ) ); 59 60 if ( match ) 61 return match[ 2 ]; 62 } 63 64 return { 65 title: langCell.title, 66 minWidth: CKEDITOR.env.ie && CKEDITOR.env.quirks ? 450 : 410, 67 minHeight: CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.quirks ) ? 230 : 220, 68 contents: [ { 69 id: 'info', 70 label: langCell.title, 71 accessKey: 'I', 72 elements: [ { 73 type: 'hbox', 74 widths: [ '40%', '5%', '40%' ], 75 children: [ { 76 type: 'vbox', 77 padding: 0, 78 children: [ 79 80 81 hiddenSpacer = { 82 type: 'html', 83 id: 'hiddenSpacer', 84 html: ' ', 85 style: 'display: none' 86 }, 87 spacer, 88 { 89 type: 'select', 90 id: 'hAlign', 91 label: langCell.hAlign, 92 'default': '', 93 items: [ 94 [ langCommon.notSet, '' ], 95 [ langCommon.left, 'left' ], 96 [ langCommon.center, 'center' ], 97 [ langCommon.right, 'right' ] 98 ], 99 setup: setupCells( function( element ) { 100 var alignAttr = element.getAttribute( 'align' ), 101 textAlignStyle = element.getStyle( 'text-align' ); 102 103 return textAlignStyle || alignAttr || ''; 104 } ), 105 commit: function( selectedCell ) { 106 var value = this.getValue(); 107 108 if ( value ) { 109 selectedCell.setStyle( 'text-align', value ); 110 selectedCell.setAttribute('class', value + 'align'); 111 } 112 else { 113 selectedCell.removeStyle( 'text-align' ); 114 selectedCell.removeAttribute( 'align' ); 115 } 116 } 117 }, 118 ] 119 }, 120 spacer, 121 { 122 type: 'vbox', 123 padding: 0, 124 children: [ { 125 type: 'select', 126 id: 'cellType', 127 label: langCell.cellType, 128 'default': 'td', 129 items: [ 130 [ langCell.data, 'td' ], 131 [ langCell.header, 'th' ] 132 ], 133 setup: setupCells( function( selectedCell ) { 134 return selectedCell.getName(); 135 } ), 136 commit: function( selectedCell ) { 137 selectedCell.renameNode( this.getValue() ); 138 } 139 }, 140 spacer, 141 { 142 type: 'text', 143 id: 'rowSpan', 144 label: langCell.rowSpan, 145 'default': '', 146 validate: validate.integer( langCell.invalidRowSpan ), 147 setup: setupCells( function( selectedCell ) { 148 var attrVal = parseInt( selectedCell.getAttribute( 'rowSpan' ), 10 ); 149 if ( attrVal && attrVal != 1 ) 150 return attrVal; 151 } ), 152 commit: function( selectedCell ) { 153 var value = parseInt( this.getValue(), 10 ); 154 if ( value && value != 1 ) 155 selectedCell.setAttribute( 'rowSpan', this.getValue() ); 156 else 157 selectedCell.removeAttribute( 'rowSpan' ); 158 } 159 }, 160 { 161 type: 'text', 162 id: 'colSpan', 163 label: langCell.colSpan, 164 'default': '', 165 validate: validate.integer( langCell.invalidColSpan ), 166 setup: setupCells( function( element ) { 167 var attrVal = parseInt( element.getAttribute( 'colSpan' ), 10 ); 168 if ( attrVal && attrVal != 1 ) 169 return attrVal; 170 } ), 171 commit: function( selectedCell ) { 172 var value = parseInt( this.getValue(), 10 ); 173 if ( value && value != 1 ) 174 selectedCell.setAttribute( 'colSpan', this.getValue() ); 175 else 176 selectedCell.removeAttribute( 'colSpan' ); 177 } 178 }, 179 ] 180 } ] 181 } ] 182 } ], 183 onShow: function() { 184 this.cells = CKEDITOR.plugins.tabletools.getSelectedCells( this._.editor.getSelection() ); 185 this.setupContent( this.cells ); 186 }, 187 onOk: function() { 188 var selection = this._.editor.getSelection(), 189 bookmarks = selection.createBookmarks(); 190 191 var cells = this.cells; 192 for ( var i = 0; i < cells.length; i++ ) 193 this.commitContent( cells[ i ] ); 194 195 this._.editor.forceNextSelectionCheck(); 196 selection.selectBookmarks( bookmarks ); 197 this._.editor.selectionChange(); 198 }, 199 onLoad: function() { 200 var saved = {}; 201 202 // Prevent from changing cell properties when the field's value 203 // remains unaltered, i.e. when selected multiple cells and dialog loaded 204 // only the properties of the first cell (https://dev.ckeditor.com/ticket/11439). 205 this.foreach( function( field ) { 206 if ( !field.setup || !field.commit ) 207 return; 208 209 // Save field's value every time after "setup" is called. 210 field.setup = CKEDITOR.tools.override( field.setup, function( orgSetup ) { 211 return function() { 212 orgSetup.apply( this, arguments ); 213 saved[ field.id ] = field.getValue(); 214 }; 215 } ); 216 217 // Compare saved value with actual value. Update cell only if value has changed. 218 field.commit = CKEDITOR.tools.override( field.commit, function( orgCommit ) { 219 return function() { 220 if ( saved[ field.id ] !== field.getValue() ) 221 orgCommit.apply( this, arguments ); 222 }; 223 } ); 224 } ); 225 } 226 }; 227} ); 228