Ticket #2852: 2852_fakeobjects.patch
File 2852_fakeobjects.patch, 25.1 KB (added by , 16 years ago) |
---|
-
_source/plugins/fakeobjects/plugin.js
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 /** 7 * @fileoverview The "fakeobjects" plugin. It handles placeholder DOM nodes 8 * in WYSIWYG mode. 9 */ 10 11 (function() 12 { 13 var flashExtensionRegex = /\.swf($|#|\?)/i, 14 emptyElements = { base:1,col:1,meta:1,link:1,hr:1,br:1,param:1,img:1,area:1,input:1 }, 15 makeTagOpenerHtml = function( tagName, attributes, selfClosing ) 16 { 17 var attribStr = [], html = [ '<' + tagName ]; 18 for ( var i in attributes ) 19 attribStr.push( i + '="' + CKEDITOR.tools.htmlEncode( attributes[i] ) + '"'); 20 if ( attribStr.length > 0 ) 21 html.push( ' ', attribStr.join( ' ' ) ); 22 if ( emptyElements[ tagName ] || selfClosing ) 23 html.push( ' /' ); 24 html.push( '>' ); 25 return html.join( '' ); 26 }, 27 cssWidthRegex = /width\s*:\s*([0-9]+)\s*(?:[\w%]+)?\s*;?/i, 28 cssHeightRegex = /height\s*:\s*([0-9]+)\s*(?:[\w%]+)?\s*;?/i; 29 30 var copyParser = function() 31 { 32 this._ = { html : null }; 33 this.output = []; 34 35 CKEDITOR.htmlParser.call( this ); 36 }; 37 copyParser.prototype = { 38 onTagOpen : function( tagName, attributes, selfClosing ) 39 { 40 this.output.push( makeTagOpenerHtml( tagName, attributes, selfClosing ) ); 41 }, 42 43 onTagClose : function( tagName ) 44 { 45 if ( !emptyElements[ tagName] ) 46 this.output.push( '</' + tagName + '>' ); 47 }, 48 49 onText : function( text ) 50 { 51 this.output.push( text ); 52 }, 53 54 onComment : function( comment ) 55 { 56 this.output.push( '<!--' + comment + '-->' ); 57 }, 58 59 parse : function( html ) 60 { 61 this._.html = html; 62 return CKEDITOR.htmlParser.prototype.parse.apply( this, arguments ); 63 } 64 }; 65 66 /** 67 * Manages element placeholders in WYSIWYG area. 68 * @constructor 69 * @example 70 */ 71 CKEDITOR.plugins.fakeobjects = function( editor ) 72 { 73 this._ = 74 { 75 editor : editor, 76 objectTypes : [ 77 { 78 match : function( nodeName, attributes ) 79 { 80 return nodeName == 'embed' && 81 ( attributes.type == 'application/x-shockwave-flash' || flashExtensionRegex.test( attributes.src || '' ) ); 82 }, 83 cssClass : 'flash', 84 priority : 10 85 }, 86 { 87 match : function( nodeName, attributes ) 88 { 89 return ( nodeName == 'a' && attributes.name != null && attributes.name != '' ); 90 }, 91 cssClass : 'anchor', 92 priority : 10 93 }, 94 { 95 match : function( nodeName, attributes ) 96 { 97 if ( nodeName == 'div' && attributes.style && attributes.style.pageBreakAfter == 'always' ) 98 if ( attributes.firstChild ) 99 { 100 var element = new CKEDITOR.dom.element( attributes.firstChild ); 101 return ( element && element.getName() == 'span'); 102 } 103 return false; 104 }, 105 cssClass : 'pagebreak', 106 priority : 10 107 }, 108 { 109 match : function( nodeName, attributes ) 110 { 111 return nodeName == 'embed' || nodeName == 'object'; 112 }, 113 cssClass : 'object', 114 priority : 0x100000000 115 } 116 ] 117 }; 118 }; 119 CKEDITOR.plugins.fakeobjects.prototype = 120 { 121 /** 122 * Converts an element into a placeholder <img> element, for adding 123 * into the WYSIWYG area. 124 * @param {CKEDITOR.dom.element} element Input DOM element. 125 * @returns {CKEDITOR.dom.element} The placeholder <img> element. 126 * @example 127 */ 128 protectElement : function( element ) 129 { 130 var $ = element.$.cloneNode( true ), 131 doc = $.ownerDocument, 132 temp = doc.createElement( 'div' ), 133 html; 134 135 // Get the object's HTML code. 136 temp.appendChild( $ ); 137 html = temp.innerHTML; 138 139 // Get the fake element's CSS class. 140 var cssClass = 'unknown'; 141 var realElementType = element.getName(); 142 for ( var i = 0 ; i < this._.objectTypes.length ; i++ ) 143 { 144 if ( this._.objectTypes[i].match( element.getName(), element.$ ) ) 145 { 146 cssClass = 'cke_fakeobject' + ' ' + this._.objectTypes[i].cssClass; 147 realElementType = this._.objectTypes[i].cssClass; 148 break; 149 } 150 } 151 152 // Make the fake element. 153 var fakeRawElement = doc.createElement( 'img' ), 154 cssText = $.style.cssText, 155 widthMatch = cssText.match( cssWidthRegex ), 156 heightMatch = cssText.match( cssHeightRegex ); 157 fakeRawElement.className = cssClass; 158 fakeRawElement.src = CKEDITOR.getUrl( 'images/spacer.gif' ); 159 if ( widthMatch) 160 fakeRawElement.style.width = widthMatch[1] + 'px'; 161 if ( heightMatch ) 162 fakeRawElement.style.height = heightMatch[1] + 'px'; 163 fakeRawElement.setAttribute( '_cke_protected_html', encodeURIComponent( html ) ); 164 fakeRawElement.setAttribute( '_cke_real_element_type', realElementType ); 165 return new CKEDITOR.dom.element( fakeRawElement ); 166 }, 167 168 /** 169 * Converts a placeholder <img> element back to the real element. 170 * @param {CKEDITOR.dom.element} fakeImgElement The placeholder <img>. 171 * @returns {CKEDITOR.dom.element} The real element. 172 * @example 173 */ 174 restoreElement : function( fakeImgElement ) 175 { 176 var html = decodeURIComponent( fakeImgElement.getAttribute( '_cke_protected_html' ) ), 177 realElement = CKEDITOR.dom.element.createFromHtml( html, this._.editor.document ); 178 179 if ( fakeImgElement.$.style.width ) 180 realElement.setStyle( 'width', fakeImgElement.$.style.width ); 181 if ( fakeImgElement.$.style.height ) 182 realElement.setStyle( 'height', fakeImgElement.$.style.height ); 183 184 return realElement; 185 }, 186 187 /** 188 * Converts protectable elements in an HTML string to placeholders. 189 * @param {String} html HTML with protectable elements. 190 * @returns {String} HTML with placeholders. 191 * @example 192 */ 193 protectHtml : function( html ) 194 { 195 var parser = new CKEDITOR.htmlParser(), 196 tagDepth = 0, processedHtml = [], 197 protectedHtml = [], inProtection = false, 198 objectTypes = this._.objectTypes; 199 200 parser.onTagOpen = function( tagName, attributes, selfClosing ) 201 { 202 if ( inProtection ) 203 { 204 protectedHtml.push( makeTagOpenerHtml( tagName, attributes, selfClosing ) ); 205 if ( !( emptyElements[ tagName ] || selfClosing ) ) 206 tagDepth++; 207 if ( tagDepth < 1 ) 208 { 209 inProtection = false; 210 processedHtml.push( encodeURIComponent( protectedHtml.join( '' ) ), '" />' ); 211 protectedHtml = []; 212 } 213 return; 214 } 215 216 for ( var i = 0 ; i < objectTypes.length ; i++ ) 217 { 218 if ( objectTypes[i].match( tagName, attributes ) ) 219 { 220 inProtection = true; 221 tagDepth = 0; 222 223 // Get the original object's width and height. 224 var styles = attributes.style || '', 225 widthMatch = styles.match( cssWidthRegex ), 226 heightMatch = styles.match( cssHeightRegex ); 227 228 // Create the fake <img> tag. 229 processedHtml.push( '<img src="', 230 CKEDITOR.getUrl( 'images/spacer.gif' ), 231 '" ', 232 'class="cke_fakeobject ' + objectTypes[i].cssClass + '" ', 233 '_cke_real_element_type="' + objectTypes[i].cssClass + '"' ); 234 235 if ( widthMatch || heightMatch ) 236 { 237 processedHtml.push( 'style="', 238 widthMatch ? 'width:' + widthMatch[1] + 'px;' : '', 239 heightMatch ? 'height:' + heightMatch[1] + 'px;' : '', 240 '" ' ); 241 } 242 243 processedHtml.push( '_cke_protected_html="' ); 244 arguments.callee.call( this, tagName, attributes, selfClosing ); 245 return; 246 } 247 } 248 249 processedHtml.push( makeTagOpenerHtml( tagName, attributes ) ); 250 }; 251 252 parser.onText = function( text ) 253 { 254 inProtection ? protectedHtml.push( text ) : processedHtml.push( text ); 255 }; 256 257 parser.onComment = function( comment ) 258 { 259 inProtection ? protectedHtml.push( '<!--' + comment + '-->' ) : processedHtml.push( '<!--' + comment + '-->' ); 260 }; 261 262 parser.onTagClose = function( tagName ) 263 { 264 if ( inProtection ) 265 { 266 if ( !emptyElements[ tagName ] ) 267 tagDepth--; 268 protectedHtml.push( '</' + tagName + '>' ); 269 if ( tagDepth < 1 ) 270 { 271 inProtection = false; 272 processedHtml.push( encodeURIComponent( protectedHtml.join( '' ) ), '" />' ); 273 protectedHtml = []; 274 } 275 } 276 else 277 processedHtml.push( '</' + tagName + '>' ); 278 }; 279 280 parser.parse( html ); 281 return processedHtml.join( '' ); 282 }, 283 /** 284 * Updates HTML into a placeholder 285 * @param {CKEDITOR.dom.element} fakeImgElement The placeholder <img>. 286 * @param {CKEDITOR.dom.element} element Input DOM element. 287 * @returns {String} encoded HTML. 288 * @example 289 */ 290 updateFakeElement : function( fakeElement, realElement ) 291 { 292 var $ = realElement.$.cloneNode( true ), 293 doc = $.ownerDocument, 294 temp = doc.createElement( 'div' ), 295 html; 296 297 // Get the object's HTML code. 298 temp.appendChild( $ ); 299 html = temp.innerHTML; 300 fakeElement.setAttribute( '_cke_protected_html', encodeURIComponent( html ) ); 301 return html; 302 }, 303 304 /** 305 * Restores placeholders in an HTML string back to their original elements. 306 * @param {String} html HTML with placeholders. 307 * @returns {String} Restored HTML. 308 * @example 309 */ 310 restoreHtml : function( html ) 311 { 312 var parser = new copyParser(), 313 innerParser = new copyParser(); 314 315 innerParser.onTagOpen = function( tagName, attributes, selfClosing ) 316 { 317 if ( !this.done ) 318 { 319 var styles = attributes.style || ''; 320 321 styles = styles.replace( cssWidthRegex, '' ).replace( cssHeightRegex, '' ); 322 if ( this.width ) 323 styles += 'width:' + this.width + ';'; 324 if ( this.height ) 325 styles += 'height:' + this.height + ';'; 326 attributes.style = styles; 327 328 this.done = true; 329 } 330 331 return copyParser.prototype.onTagOpen.apply( this, arguments ); 332 }; 333 334 parser.onTagOpen = function( tagName, attributes, selfClosing ) 335 { 336 if ( tagName == 'img' && attributes._cke_protected_html !== undefined ) 337 { 338 var styles = attributes.style || '', 339 protectedHtml = decodeURIComponent( attributes._cke_protected_html ), 340 widthMatch = styles.match( cssWidthRegex ), 341 heightMatch = styles.match( cssHeightRegex ); 342 343 if ( widthMatch || heightMatch ) 344 { 345 innerParser.width = widthMatch[1] + 'px'; 346 innerParser.height = heightMatch[1] + 'px'; 347 innerParser.parse( protectedHtml ); 348 protectedHtml = innerParser.output.join( '' ); 349 } 350 351 this.output.push( protectedHtml ); 352 return; 353 } 354 return copyParser.prototype.onTagOpen.apply( this, arguments ); 355 }; 356 357 parser.parse( html ); 358 return parser.output.join( '' ); 359 }, 360 361 /** 362 * Adds an object type to be displayed by placeholders. 363 * @param {Function} matchFunc A predicate function to determine whether 364 * an object needs to be replaced by placeholders or not. The function 365 * should have the following signature: 366 * <blockquote>function( tagName, attributes )</blockquote> 367 * In which tagName is the object's tag name, and attributes is an object 368 * storing all the object's attributes. 369 * @param {String} cssClass The CSS class that should be added to the 370 * placeholder <img> for representing this type of object. 371 * @param {Number} priority (Optional) An integer representing the 372 * priority of this type of object. If an element matches the descriptions 373 * of two object types, the object type of <strong>lower</strong> priority 374 * takes precedance. 375 * @example 376 */ 377 addObjectType : function( matchFunc, cssClass, priority ) 378 { 379 if ( priority === undefined ) 380 priority = 10; 381 382 var obj = { 383 match : matchFunc, 384 cssClass : cssClass, 385 priority : priority 386 }; 387 388 for ( var i = this._.objectTypes.length - 1 ; i >= 0 ; i-- ) 389 { 390 if ( this._.objectTypes[i].priority < priority ) 391 { 392 this._.objectTypes.splice( i + 1, 0, obj ); 393 return; 394 } 395 } 396 397 this._.objectTypes.unshift( obj ); 398 } 399 }; 400 401 CKEDITOR.plugins.add( 'fakeobjects', 402 { 403 init : function( editor, pluginPath ) 404 { 405 editor.fakeobjects = new CKEDITOR.plugins.fakeobjects( editor ); 406 } 407 } ); 408 })(); -
_source/plugins/fakeobjects/plugin.js
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 /** 7 * @fileoverview The "fakeobjects" plugin. It handles placeholder DOM nodes 8 * in WYSIWYG mode. 9 */ 10 11 (function() 12 { 13 var flashExtensionRegex = /\.swf($|#|\?)/i, 14 emptyElements = { base:1,col:1,meta:1,link:1,hr:1,br:1,param:1,img:1,area:1,input:1 }, 15 makeTagOpenerHtml = function( tagName, attributes, selfClosing ) 16 { 17 var attribStr = [], html = [ '<' + tagName ]; 18 for ( var i in attributes ) 19 attribStr.push( i + '="' + CKEDITOR.tools.htmlEncode( attributes[i] ) + '"'); 20 if ( attribStr.length > 0 ) 21 html.push( ' ', attribStr.join( ' ' ) ); 22 if ( emptyElements[ tagName ] || selfClosing ) 23 html.push( ' /' ); 24 html.push( '>' ); 25 return html.join( '' ); 26 }, 27 cssWidthRegex = /width\s*:\s*([0-9]+)\s*(?:[\w%]+)?\s*;?/i, 28 cssHeightRegex = /height\s*:\s*([0-9]+)\s*(?:[\w%]+)?\s*;?/i; 29 30 var copyParser = function() 31 { 32 this._ = { html : null }; 33 this.output = []; 34 35 CKEDITOR.htmlParser.call( this ); 36 }; 37 copyParser.prototype = { 38 onTagOpen : function( tagName, attributes, selfClosing ) 39 { 40 this.output.push( makeTagOpenerHtml( tagName, attributes, selfClosing ) ); 41 }, 42 43 onTagClose : function( tagName ) 44 { 45 if ( !emptyElements[ tagName] ) 46 this.output.push( '</' + tagName + '>' ); 47 }, 48 49 onText : function( text ) 50 { 51 this.output.push( text ); 52 }, 53 54 onComment : function( comment ) 55 { 56 this.output.push( '<!--' + comment + '-->' ); 57 }, 58 59 parse : function( html ) 60 { 61 this._.html = html; 62 return CKEDITOR.htmlParser.prototype.parse.apply( this, arguments ); 63 } 64 }; 65 66 /** 67 * Manages element placeholders in WYSIWYG area. 68 * @constructor 69 * @example 70 */ 71 CKEDITOR.plugins.fakeobjects = function( editor ) 72 { 73 this._ = 74 { 75 editor : editor, 76 objectTypes : [ 77 { 78 match : function( nodeName, attributes ) 79 { 80 return nodeName == 'embed' && 81 ( attributes.type == 'application/x-shockwave-flash' || flashExtensionRegex.test( attributes.src || '' ) ); 82 }, 83 cssClass : 'flash', 84 priority : 10 85 }, 86 { 87 match : function( nodeName, attributes ) 88 { 89 return ( nodeName == 'a' && attributes.name != null && attributes.name != '' ); 90 }, 91 cssClass : 'anchor', 92 priority : 10 93 }, 94 { 95 match : function( nodeName, attributes ) 96 { 97 if ( nodeName == 'div' && attributes.style && attributes.style.pageBreakAfter == 'always' ) 98 if ( attributes.firstChild ) 99 { 100 var element = new CKEDITOR.dom.element( attributes.firstChild ); 101 return ( element && element.getName() == 'span'); 102 } 103 return false; 104 }, 105 cssClass : 'pagebreak', 106 priority : 10 107 }, 108 { 109 match : function( nodeName, attributes ) 110 { 111 return nodeName == 'embed' || nodeName == 'object'; 112 }, 113 cssClass : 'object', 114 priority : 0x100000000 115 } 116 ] 117 }; 118 }; 119 CKEDITOR.plugins.fakeobjects.prototype = 120 { 121 /** 122 * Converts an element into a placeholder <img> element, for adding 123 * into the WYSIWYG area. 124 * @param {CKEDITOR.dom.element} element Input DOM element. 125 * @returns {CKEDITOR.dom.element} The placeholder <img> element. 126 * @example 127 */ 128 protectElement : function( element ) 129 { 130 var $ = element.$.cloneNode( true ), 131 doc = $.ownerDocument, 132 temp = doc.createElement( 'div' ), 133 html; 134 135 // Get the object's HTML code. 136 temp.appendChild( $ ); 137 html = temp.innerHTML; 138 139 // Get the fake element's CSS class. 140 var cssClass = 'unknown'; 141 var realElementType = element.getName(); 142 for ( var i = 0 ; i < this._.objectTypes.length ; i++ ) 143 { 144 if ( this._.objectTypes[i].match( element.getName(), element.$ ) ) 145 { 146 cssClass = 'cke_fakeobject' + ' ' + this._.objectTypes[i].cssClass; 147 realElementType = this._.objectTypes[i].cssClass; 148 break; 149 } 150 } 151 152 // Make the fake element. 153 var fakeRawElement = doc.createElement( 'img' ), 154 cssText = $.style.cssText, 155 widthMatch = cssText.match( cssWidthRegex ), 156 heightMatch = cssText.match( cssHeightRegex ); 157 fakeRawElement.className = cssClass; 158 fakeRawElement.src = CKEDITOR.getUrl( 'images/spacer.gif' ); 159 if ( widthMatch) 160 fakeRawElement.style.width = widthMatch[1] + 'px'; 161 if ( heightMatch ) 162 fakeRawElement.style.height = heightMatch[1] + 'px'; 163 fakeRawElement.setAttribute( '_cke_protected_html', encodeURIComponent( html ) ); 164 fakeRawElement.setAttribute( '_cke_real_element_type', realElementType ); 165 return new CKEDITOR.dom.element( fakeRawElement ); 166 }, 167 168 /** 169 * Converts a placeholder <img> element back to the real element. 170 * @param {CKEDITOR.dom.element} fakeImgElement The placeholder <img>. 171 * @returns {CKEDITOR.dom.element} The real element. 172 * @example 173 */ 174 restoreElement : function( fakeImgElement ) 175 { 176 var html = decodeURIComponent( fakeImgElement.getAttribute( '_cke_protected_html' ) ), 177 realElement = CKEDITOR.dom.element.createFromHtml( html, this._.editor.document ); 178 179 if ( fakeImgElement.$.style.width ) 180 realElement.setStyle( 'width', fakeImgElement.$.style.width ); 181 if ( fakeImgElement.$.style.height ) 182 realElement.setStyle( 'height', fakeImgElement.$.style.height ); 183 184 return realElement; 185 }, 186 187 /** 188 * Converts protectable elements in an HTML string to placeholders. 189 * @param {String} html HTML with protectable elements. 190 * @returns {String} HTML with placeholders. 191 * @example 192 */ 193 protectHtml : function( html ) 194 { 195 var parser = new CKEDITOR.htmlParser(), 196 tagDepth = 0, processedHtml = [], 197 protectedHtml = [], inProtection = false, 198 objectTypes = this._.objectTypes; 199 200 parser.onTagOpen = function( tagName, attributes, selfClosing ) 201 { 202 if ( inProtection ) 203 { 204 protectedHtml.push( makeTagOpenerHtml( tagName, attributes, selfClosing ) ); 205 if ( !( emptyElements[ tagName ] || selfClosing ) ) 206 tagDepth++; 207 if ( tagDepth < 1 ) 208 { 209 inProtection = false; 210 processedHtml.push( encodeURIComponent( protectedHtml.join( '' ) ), '" />' ); 211 protectedHtml = []; 212 } 213 return; 214 } 215 216 for ( var i = 0 ; i < objectTypes.length ; i++ ) 217 { 218 if ( objectTypes[i].match( tagName, attributes ) ) 219 { 220 inProtection = true; 221 tagDepth = 0; 222 223 // Get the original object's width and height. 224 var styles = attributes.style || '', 225 widthMatch = styles.match( cssWidthRegex ), 226 heightMatch = styles.match( cssHeightRegex ); 227 228 // Create the fake <img> tag. 229 processedHtml.push( '<img src="', 230 CKEDITOR.getUrl( 'images/spacer.gif' ), 231 '" ', 232 'class="cke_fakeobject ' + objectTypes[i].cssClass + '" ', 233 '_cke_real_element_type="' + objectTypes[i].cssClass + '"' ); 234 235 if ( widthMatch || heightMatch ) 236 { 237 processedHtml.push( 'style="', 238 widthMatch ? 'width:' + widthMatch[1] + 'px;' : '', 239 heightMatch ? 'height:' + heightMatch[1] + 'px;' : '', 240 '" ' ); 241 } 242 243 processedHtml.push( '_cke_protected_html="' ); 244 arguments.callee.call( this, tagName, attributes, selfClosing ); 245 return; 246 } 247 } 248 249 processedHtml.push( makeTagOpenerHtml( tagName, attributes ) ); 250 }; 251 252 parser.onText = function( text ) 253 { 254 inProtection ? protectedHtml.push( text ) : processedHtml.push( text ); 255 }; 256 257 parser.onComment = function( comment ) 258 { 259 inProtection ? protectedHtml.push( '<!--' + comment + '-->' ) : processedHtml.push( '<!--' + comment + '-->' ); 260 }; 261 262 parser.onTagClose = function( tagName ) 263 { 264 if ( inProtection ) 265 { 266 if ( !emptyElements[ tagName ] ) 267 tagDepth--; 268 protectedHtml.push( '</' + tagName + '>' ); 269 if ( tagDepth < 1 ) 270 { 271 inProtection = false; 272 processedHtml.push( encodeURIComponent( protectedHtml.join( '' ) ), '" />' ); 273 protectedHtml = []; 274 } 275 } 276 else 277 processedHtml.push( '</' + tagName + '>' ); 278 }; 279 280 parser.parse( html ); 281 return processedHtml.join( '' ); 282 }, 283 /** 284 * Updates HTML into a placeholder 285 * @param {CKEDITOR.dom.element} fakeImgElement The placeholder <img>. 286 * @param {CKEDITOR.dom.element} element Input DOM element. 287 * @returns {String} encoded HTML. 288 * @example 289 */ 290 updateFakeElement : function( fakeElement, realElement ) 291 { 292 var $ = realElement.$.cloneNode( true ), 293 doc = $.ownerDocument, 294 temp = doc.createElement( 'div' ), 295 html; 296 297 // Get the object's HTML code. 298 temp.appendChild( $ ); 299 html = temp.innerHTML; 300 fakeElement.setAttribute( '_cke_protected_html', encodeURIComponent( html ) ); 301 return html; 302 }, 303 304 /** 305 * Restores placeholders in an HTML string back to their original elements. 306 * @param {String} html HTML with placeholders. 307 * @returns {String} Restored HTML. 308 * @example 309 */ 310 restoreHtml : function( html ) 311 { 312 var parser = new copyParser(), 313 innerParser = new copyParser(); 314 315 innerParser.onTagOpen = function( tagName, attributes, selfClosing ) 316 { 317 if ( !this.done ) 318 { 319 var styles = attributes.style || ''; 320 321 styles = styles.replace( cssWidthRegex, '' ).replace( cssHeightRegex, '' ); 322 if ( this.width ) 323 styles += 'width:' + this.width + ';'; 324 if ( this.height ) 325 styles += 'height:' + this.height + ';'; 326 attributes.style = styles; 327 328 this.done = true; 329 } 330 331 return copyParser.prototype.onTagOpen.apply( this, arguments ); 332 }; 333 334 parser.onTagOpen = function( tagName, attributes, selfClosing ) 335 { 336 if ( tagName == 'img' && attributes._cke_protected_html !== undefined ) 337 { 338 var styles = attributes.style || '', 339 protectedHtml = decodeURIComponent( attributes._cke_protected_html ), 340 widthMatch = styles.match( cssWidthRegex ), 341 heightMatch = styles.match( cssHeightRegex ); 342 343 if ( widthMatch || heightMatch ) 344 { 345 innerParser.width = widthMatch[1] + 'px'; 346 innerParser.height = heightMatch[1] + 'px'; 347 innerParser.parse( protectedHtml ); 348 protectedHtml = innerParser.output.join( '' ); 349 } 350 351 this.output.push( protectedHtml ); 352 return; 353 } 354 return copyParser.prototype.onTagOpen.apply( this, arguments ); 355 }; 356 357 parser.parse( html ); 358 return parser.output.join( '' ); 359 }, 360 361 /** 362 * Adds an object type to be displayed by placeholders. 363 * @param {Function} matchFunc A predicate function to determine whether 364 * an object needs to be replaced by placeholders or not. The function 365 * should have the following signature: 366 * <blockquote>function( tagName, attributes )</blockquote> 367 * In which tagName is the object's tag name, and attributes is an object 368 * storing all the object's attributes. 369 * @param {String} cssClass The CSS class that should be added to the 370 * placeholder <img> for representing this type of object. 371 * @param {Number} priority (Optional) An integer representing the 372 * priority of this type of object. If an element matches the descriptions 373 * of two object types, the object type of <strong>lower</strong> priority 374 * takes precedance. 375 * @example 376 */ 377 addObjectType : function( matchFunc, cssClass, priority ) 378 { 379 if ( priority === undefined ) 380 priority = 10; 381 382 var obj = { 383 match : matchFunc, 384 cssClass : cssClass, 385 priority : priority 386 }; 387 388 for ( var i = this._.objectTypes.length - 1 ; i >= 0 ; i-- ) 389 { 390 if ( this._.objectTypes[i].priority < priority ) 391 { 392 this._.objectTypes.splice( i + 1, 0, obj ); 393 return; 394 } 395 } 396 397 this._.objectTypes.unshift( obj ); 398 } 399 }; 400 401 CKEDITOR.plugins.add( 'fakeobjects', 402 { 403 init : function( editor, pluginPath ) 404 { 405 editor.fakeobjects = new CKEDITOR.plugins.fakeobjects( editor ); 406 } 407 } ); 408 })();