Ticket #3582: 3582_8.patch
File 3582_8.patch, 16.7 KB (added by , 13 years ago) |
---|
-
_source/plugins/elementspath/plugin.js
124 124 125 125 while ( element ) 126 126 { 127 var ignore = 0; 127 var ignore = 0, 128 name; 129 130 if ( element.data( 'cke-real-element-type' ) ) 131 name = element.data( 'cke-real-element-type' ); 132 else 133 name = element.getName(); 134 128 135 for ( var i = 0; i < filters.length; i++ ) 129 136 { 130 if ( filters[ i ]( element ) === false ) 137 var ret = filters[ i ]( element, name ); 138 if ( ret === false ) 131 139 { 132 140 ignore = 1; 133 141 break; 134 142 } 143 name = ret || name; 135 144 } 136 145 137 146 if ( !ignore ) 138 147 { 139 148 var index = elementsList.push( element ) - 1; 140 var name;141 if ( element.data( 'cke-real-element-type' ) )142 name = element.data( 'cke-real-element-type' );143 else144 name = element.getName();145 149 146 150 // Use this variable to add conditional stuff to the 147 151 // HTML (because we are doing it in reverse order... unshift). -
_source/plugins/htmldataprocessor/plugin.js
95 95 delete blockLikeTags.pre; 96 96 var defaultDataFilterRules = 97 97 { 98 elements : { 99 a : function( element ) 100 { 101 var attrs = element.attributes; 102 if ( attrs && attrs[ 'data-cke-saved-name' ] ) 103 attrs[ 'class' ] = ( attrs[ 'class' ] ? attrs[ 'class' ] + ' ' : '' ) + 'cke_anchor'; 104 } 105 }, 98 elements : {}, 106 99 attributeNames : 107 100 [ 108 101 // Event attributes (onXYZ) must not be directly set. They can become -
_source/plugins/link/dialogs/anchor.js
6 6 CKEDITOR.dialog.add( 'anchor', function( editor ) 7 7 { 8 8 // Function called in onShow to load selected element. 9 var loadElements = function( e ditor, selection, element )9 var loadElements = function( element ) 10 10 { 11 this.editMode = true; 12 this.editObj = element; 11 this._.selectedElement = element; 13 12 14 var attributeValue = this.editObj.getAttribute( 'name' ); 15 if ( attributeValue ) 16 this.setValueOf( 'info','txtName', attributeValue ); 17 else 18 this.setValueOf( 'info','txtName', "" ); 13 var attributeValue = element.data( 'cke-saved-name' ); 14 this.setValueOf( 'info','txtName', attributeValue || '' ); 19 15 }; 20 16 17 function createFakeAnchor( editor, anchor ) 18 { 19 return editor.createFakeElement( anchor, 'cke_anchor', 'a' ); 20 } 21 21 22 return { 22 23 title : editor.lang.anchor.title, 23 24 minWidth : 300, 24 25 minHeight : 60, 25 26 onOk : function() 26 27 { 27 // Always create a new anchor, because of IE BUG. 28 var name = this.getValueOf( 'info', 'txtName' ), 29 element = CKEDITOR.env.ie && !( CKEDITOR.document.$.documentMode >= 8 ) ? 30 editor.document.createElement( '<a name="' + CKEDITOR.tools.htmlEncode( name ) + '">' ) : 31 editor.document.createElement( 'a' ); 28 var name = this.getValueOf( 'info', 'txtName' ); 29 var attributes = 30 { 31 name : name, 32 'data-cke-saved-name' : name 33 }; 32 34 33 // Move contents and attributes of old anchor to new anchor. 34 if ( this.editMode ) 35 if ( this._.selectedElement ) 35 36 { 36 this.editObj.copyAttributes( element, { name : 1 } ); 37 this.editObj.moveChildren( element ); 37 if ( this._.selectedElement.data( 'cke-realelement' ) ) 38 { 39 var newFake = createFakeAnchor( editor, editor.document.createElement( 'a', { attributes: attributes } ) ); 40 newFake.replace( this._.selectedElement ); 41 } 42 else 43 this._.selectedElement.setAttributes( attributes ); 38 44 } 45 else 46 { 47 var sel = editor.getSelection(), 48 range = sel && sel.getRanges()[ 0 ]; 39 49 40 // Set name. 41 element.data( 'cke-saved-name', false ); 42 element.setAttribute( 'name', name ); 50 // Empty anchor 51 if ( range.collapsed ) 52 { 53 var anchor = editor.document.createElement( 'a', { attributes: attributes } ); 43 54 44 // Insert a new anchor. 45 var fakeElement = editor.createFakeElement( element, 'cke_anchor', 'anchor' ); 46 if ( !this.editMode ) 47 editor.insertElement( fakeElement ); 48 else 49 { 50 fakeElement.replace( this.fakeObj ); 51 editor.getSelection().selectElement( fakeElement ); 55 // IE needs the anchor to have a special class. 56 if ( CKEDITOR.env.ie ) 57 { 58 anchor.addClass( 'cke_anchor_empty' ); 59 60 if ( CKEDITOR.env.version < 8 ) 61 anchor.setAttribute( 'contentEditable', 'false' ); 62 } 63 64 // Transform the anchor into a fake element for browsers that need it. 65 if ( CKEDITOR.plugins.link.fakeAnchor ) 66 anchor = createFakeAnchor( editor, anchor ); 67 68 range.insertNode( anchor ); 69 } 70 else 71 { 72 // Apply style. 73 var style = new CKEDITOR.style( { element : 'a', attributes : attributes } ); 74 style.type = CKEDITOR.STYLE_INLINE; 75 style.apply( editor.document ); 76 } 52 77 } 78 }, 53 79 54 return true; 80 onHide : function() 81 { 82 delete this._.selectedElement; 55 83 }, 84 56 85 onShow : function() 57 86 { 58 this.editObj = false;59 this.fakeObj = false;60 this.editMode = false;87 var selection = editor.getSelection(), 88 fullySelected = selection.getSelectedElement(), 89 partialSelected; 61 90 62 var selection = editor.getSelection(); 63 var element = selection.getSelectedElement(); 64 if ( element && element.data( 'cke-real-element-type' ) && element.data( 'cke-real-element-type' ) == 'anchor' ) 91 // Detect the anchor under selection. 92 if ( fullySelected ) 65 93 { 66 this.fakeObj = element; 67 element = editor.restoreRealElement( this.fakeObj ); 68 loadElements.apply( this, [ editor, selection, element ] ); 69 selection.selectElement( this.fakeObj ); 94 if ( CKEDITOR.plugins.link.fakeAnchor ) 95 { 96 var realElement = CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, fullySelected ); 97 realElement && loadElements.call( this, realElement ); 98 this._.selectedElement = fullySelected; 99 } 100 else if ( fullySelected.is( 'a' ) && fullySelected.hasAttribute( 'name' ) ) 101 loadElements.call( this, fullySelected ); 70 102 } 103 else 104 { 105 partialSelected = CKEDITOR.plugins.link.getSelectedLink( editor ); 106 if ( partialSelected ) 107 { 108 loadElements.call( this, partialSelected ); 109 selection.selectElement( partialSelected ); 110 } 111 } 112 71 113 this.getContentElement( 'info', 'txtName' ).focus(); 72 114 }, 73 115 contents : [ -
_source/plugins/link/dialogs/link.js
242 242 } 243 243 244 244 // Find out whether we have any anchors in the editor. 245 // Get all IMG elements in CK document. 246 var elements = editor.document.getElementsByTag( 'img' ), 247 realAnchors = new CKEDITOR.dom.nodeList( editor.document.$.anchors ), 248 anchors = retval.anchors = []; 245 var anchorList = new CKEDITOR.dom.nodeList( editor.document.$.anchors ), 246 anchors = retval.anchors = [], 247 item; 249 248 250 for ( var i = 0 ; i < elements.count(); i++ )249 for ( var i = 0, count = anchorList.count(); i < count; i++ ) 251 250 { 252 var item = elements.getItem( i ); 253 if ( item.data( 'cke-realelement' ) && item.data( 'cke-real-element-type' ) == 'anchor' ) 254 anchors.push( editor.restoreRealElement( item ) ); 255 } 256 257 for ( i = 0 ; i < realAnchors.count() ; i++ ) 258 anchors.push( realAnchors.getItem( i ) ); 259 260 for ( i = 0 ; i < anchors.length ; i++ ) 261 { 262 item = anchors[ i ]; 251 item = anchorList.getItem( i ); 263 252 anchors[ i ] = { name : item.getAttribute( 'name' ), id : item.getAttribute( 'id' ) }; 264 253 } 265 254 266 255 // Record down the selected element in the dialog. 267 256 this._.selectedElement = element; 268 269 257 return retval; 270 258 }; 271 259 … … 1151 1139 ], 1152 1140 onShow : function() 1153 1141 { 1154 this.fakeObj = false;1155 1156 1142 var editor = this.getParentEditor(), 1157 1143 selection = editor.getSelection(), 1158 1144 element = null; … … 1160 1146 // Fill in all the relevant fields if there's already one link selected. 1161 1147 if ( ( element = plugin.getSelectedLink( editor ) ) && element.hasAttribute( 'href' ) ) 1162 1148 selection.selectElement( element ); 1163 else if ( ( element = selection.getSelectedElement() ) && element.is( 'img' )1164 && element.data( 'cke-real-element-type' )1165 && element.data( 'cke-real-element-type' ) == 'anchor' )1166 {1167 this.fakeObj = element;1168 element = editor.restoreRealElement( this.fakeObj );1169 selection.selectElement( this.fakeObj );1170 }1171 1149 else 1172 1150 element = null; 1173 1151 … … 1302 1280 advAttr( 'advAccessKey', 'accessKey' ); 1303 1281 1304 1282 if ( data.adv[ 'advName' ] ) 1305 {1306 1283 attributes[ 'name' ] = attributes[ 'data-cke-saved-name' ] = data.adv[ 'advName' ]; 1307 attributes[ 'class' ] = ( attributes[ 'class' ] ? attributes[ 'class' ] + ' ' : '' ) + 'cke_anchor';1308 }1309 1284 else 1310 1285 removeAttributes = removeAttributes.concat( [ 'data-cke-saved-name', 'name' ] ); 1311 1286 … … 1350 1325 href = element.data( 'cke-saved-href' ), 1351 1326 textView = element.getHtml(); 1352 1327 1353 // IE BUG: Setting the name attribute to an existing link doesn't work.1354 // Must re-create the link from weired syntax to workaround.1355 if ( CKEDITOR.env.ie && !( CKEDITOR.document.$.documentMode >= 8 ) && attributes.name != element.getAttribute( 'name' ) )1356 {1357 var newElement = new CKEDITOR.dom.element( '<a name="' + CKEDITOR.tools.htmlEncode( attributes.name ) + '">',1358 editor.document );1359 1360 selection = editor.getSelection();1361 1362 element.copyAttributes( newElement, { name : 1 } );1363 element.moveChildren( newElement );1364 newElement.replace( element );1365 element = newElement;1366 1367 selection.selectElement( element );1368 }1369 1370 1328 element.setAttributes( attributes ); 1371 1329 element.removeAttributes( removeAttributes ); 1372 1330 // Update text view when user changes protocol (#4612). … … 1376 1334 element.setHtml( data.type == 'email' ? 1377 1335 data.email.address : attributes[ 'data-cke-saved-href' ] ); 1378 1336 } 1379 // Make the element display as an anchor if a name has been set.1380 if ( element.getAttribute( 'name' ) )1381 element.addClass( 'cke_anchor' );1382 else1383 element.removeClass( 'cke_anchor' );1384 1337 1385 if ( this.fakeObj )1386 editor.createFakeElement( element, 'cke_anchor', 'anchor' ).replace( this.fakeObj );1387 1388 1338 delete this._.selectedElement; 1389 1339 } 1390 1340 }, -
_source/plugins/link/plugin.js
30 30 CKEDITOR.dialog.add( 'anchor', this.path + 'dialogs/anchor.js' ); 31 31 32 32 // Add the CSS styles for anchor placeholders. 33 var side = editor.lang.dir == 'rtl' ? 'right' : 'left'; 33 34 var side = ( editor.lang.dir == 'rtl' ? 'right' : 'left' ); 35 var basicCss = 36 'background:url(' + CKEDITOR.getUrl( this.path + 'images/anchor.gif' ) + ') no-repeat ' + side + ' center;' + 37 'border:1px dotted #00f;'; 38 34 39 editor.addCss( 40 'a.cke_anchor,a.cke_anchor_empty' + 41 // IE6 breaks with the following selectors. 42 ( ( CKEDITOR.env.ie && CKEDITOR.env.version < 7 ) ? '' : 43 ',a[name],a[data-cke-saved-name]' ) + 44 '{' + 45 basicCss + 46 'padding-' + side + ':18px;' + 47 // Show the arrow cursor for the anchor image (FF at least). 48 'cursor:auto;' + 49 '}' + 50 'a.cke_anchor_empty' + 51 '{' + 52 // Make empty anchor selectable on IE. 53 'display:inline-block;' + 54 '}' + 35 55 'img.cke_anchor' + 36 56 '{' + 37 'background-image: url(' + CKEDITOR.getUrl( this.path + 'images/anchor.gif' ) + ');' + 38 'background-position: center center;' + 39 'background-repeat: no-repeat;' + 40 'border: 1px solid #a9a9a9;' + 41 'width: 18px !important;' + 42 'height: 18px !important;' + 43 '}\n' + 44 'a.cke_anchor' + 45 '{' + 46 'background-image: url(' + CKEDITOR.getUrl( this.path + 'images/anchor.gif' ) + ');' + 47 'background-position: ' + side + ' center;' + 48 'background-repeat: no-repeat;' + 49 'border: 1px solid #a9a9a9;' + 50 'padding-' + side + ': 18px;' + 51 '}' 52 ); 57 basicCss + 58 'width:16px;' + 59 'min-height:15px;' + 60 // The default line-height on IE. 61 'height:1.15em;' + 62 // Opera works better with "middle" (even if not perfect) 63 'vertical-align:' + ( CKEDITOR.env.opera ? 'middle' : 'text-bottom' ) + ';' + 64 '}'); 53 65 54 66 // Register selection change handler for the unlink button. 55 67 editor.on( 'selectionChange', function( evt ) … … 73 85 if ( !element.isReadOnly() ) 74 86 { 75 87 if ( element.is( 'a' ) ) 76 evt.data.dialog = ( element.getAttribute( 'name' ) && !element.getAttribute( 'href' ) ) ? 'anchor' : 'link'; 77 else if ( element.is( 'img' ) && element.data( 'cke-real-element-type' ) == 'anchor' ) 88 { 89 evt.data.dialog = ( element.getAttribute( 'name' ) && !element.getAttribute( 'href' ) ) ? 'anchor' : 'link'; 90 editor.getSelection().selectElement( element ); 91 } 92 else if ( CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, element ) ) 78 93 evt.data.dialog = 'anchor'; 79 94 } 80 95 }); … … 117 132 if ( !element || element.isReadOnly() ) 118 133 return null; 119 134 120 var isAnchor = ( element.is( 'img' ) && element.data( 'cke-real-element-type' ) == 'anchor');135 var isAnchor = CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, element ); 121 136 122 137 if ( !isAnchor ) 123 138 { … … 139 154 // Register a filter to displaying placeholders after mode change. 140 155 141 156 var dataProcessor = editor.dataProcessor, 142 dataFilter = dataProcessor && dataProcessor.dataFilter; 157 dataFilter = dataProcessor && dataProcessor.dataFilter, 158 htmlFilter = dataProcessor && dataProcessor.htmlFilter, 159 pathFilters = editor._.elementsPath.filters; 143 160 144 161 if ( dataFilter ) 145 162 { … … 150 167 a : function( element ) 151 168 { 152 169 var attributes = element.attributes; 153 if ( attributes.name && !attributes.href ) 154 return editor.createFakeParserElement( element, 'cke_anchor', 'anchor' ); 170 if ( !attributes.name ) 171 return; 172 173 var isEmpty = !element.children.length; 174 175 if ( CKEDITOR.env.ie ) 176 { 177 // IE needs a specific class name to be applied 178 // to the anchors, for appropriate styling. 179 var ieClass = isEmpty ? 'cke_anchor_empty' : 'cke_anchor'; 180 var cls = attributes[ 'class' ]; 181 if ( attributes.name && ( !cls || cls.indexOf( ieClass ) < 0 ) ) 182 attributes[ 'class' ] = ( cls || '' ) + ' ' + ieClass; 183 184 if ( isEmpty && CKEDITOR.env.version < 8 ) 185 { 186 attributes.contenteditable = 'false'; 187 attributes[ 'data-cke-editable' ] = 1; 188 } 189 } 190 else if ( CKEDITOR.plugins.link.fakeAnchor && isEmpty ) 191 return editor.createFakeParserElement( element, 'cke_anchor', 'a' ); 155 192 } 156 193 } 157 194 }); 158 195 } 196 197 if ( CKEDITOR.env.ie && htmlFilter ) 198 { 199 htmlFilter.addRules( 200 { 201 elements : 202 { 203 a : function( element ) 204 { 205 delete element.attributes.contenteditable; 206 } 207 } 208 }); 209 } 210 211 if ( pathFilters ) 212 { 213 pathFilters.push( function( element, name ) 214 { 215 if ( name == 'a' ) 216 { 217 if ( CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, element ) || 218 ( element.getAttribute( 'name' ) && !element.getAttribute( 'href' ) ) ) 219 { 220 return 'anchor'; 221 } 222 } 223 }); 224 } 159 225 }, 160 226 161 227 requires : [ 'fakeobjects' ] … … 196 262 return root.getAscendant( 'a', true ); 197 263 } 198 264 catch( e ) { return null; } 265 }, 266 267 // Opera and WebKit don't make it possible to select empty anchors. Fake 268 // elements must be used for them. 269 fakeAnchor : CKEDITOR.env.opera || CKEDITOR.env.webkit, 270 271 tryRestoreFakeAnchor : function( editor, element ) 272 { 273 if ( element && element.data( 'cke-real-element-type' ) && element.data( 'cke-real-element-type' ) == 'a' ) 274 { 275 var link = editor.restoreRealElement( element ); 276 if ( link.data( 'cke-saved-name' ) ) 277 return link; 278 } 199 279 } 200 280 }; 201 281