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 (function()
  7 {
  8 	var cssStyle = CKEDITOR.htmlParser.cssStyle,
  9 			cssLength = CKEDITOR.tools.cssLength;
 10 
 11 	var cssLengthRegex = /^((?:\d*(?:\.\d+))|(?:\d+))(.*)?$/i;
 12 
 13 	/*
 14 	 * Replacing the former CSS length value with the later one, with
 15 	 * adjustment to the length  unit.
 16 	 */
 17 	function replaceCssLength( length1, length2 )
 18 	{
 19 		var parts1 = cssLengthRegex.exec( length1 ),
 20 				parts2 = cssLengthRegex.exec( length2 );
 21 
 22 		// Omit pixel length unit when necessary,
 23 		// e.g. replaceCssLength( 10, '20px' ) -> 20
 24 		if ( parts1 )
 25 		{
 26 			if ( !parts1[ 2 ] && parts2[ 2 ] == 'px' )
 27 				return parts2[ 1 ];
 28 			if ( parts1[ 2 ] == 'px' && !parts2[ 2 ] )
 29 				return parts2[ 1 ] + 'px';
 30 		}
 31 
 32 		return length2;
 33 	}
 34 
 35 	var htmlFilterRules =
 36 	{
 37 		elements :
 38 		{
 39 			$ : function( element )
 40 			{
 41 				var attributes = element.attributes,
 42 					realHtml = attributes && attributes[ 'data-cke-realelement' ],
 43 					realFragment = realHtml && new CKEDITOR.htmlParser.fragment.fromHtml( decodeURIComponent( realHtml ) ),
 44 					realElement = realFragment && realFragment.children[ 0 ];
 45 
 46 				// Width/height in the fake object are subjected to clone into the real element.
 47 				if ( realElement && element.attributes[ 'data-cke-resizable' ] )
 48 				{
 49 					var styles = new cssStyle( element ).rules,
 50 						realAttrs = realElement.attributes,
 51 						width = styles.width,
 52 						height = styles.height;
 53 
 54 					width && ( realAttrs.width = replaceCssLength( realAttrs.width, width ) );
 55 					height && ( realAttrs.height = replaceCssLength( realAttrs.height, height ) );
 56 				}
 57 
 58 				return realElement;
 59 			}
 60 		}
 61 	};
 62 
 63 	CKEDITOR.plugins.add( 'fakeobjects',
 64 	{
 65 		requires : [ 'htmlwriter' ],
 66 
 67 		afterInit : function( editor )
 68 		{
 69 			var dataProcessor = editor.dataProcessor,
 70 				htmlFilter = dataProcessor && dataProcessor.htmlFilter;
 71 
 72 			if ( htmlFilter )
 73 				htmlFilter.addRules( htmlFilterRules );
 74 		}
 75 	});
 76 
 77 	CKEDITOR.editor.prototype.createFakeElement = function( realElement, className, realElementType, isResizable )
 78 	{
 79 		var lang = this.lang.fakeobjects,
 80 			label = lang[ realElementType ] || lang.unknown;
 81 
 82 		var attributes =
 83 		{
 84 			'class' : className,
 85 			'data-cke-realelement' : encodeURIComponent( realElement.getOuterHtml() ),
 86 			'data-cke-real-node-type' : realElement.type,
 87 			alt : label,
 88 			title : label,
 89 			align : realElement.getAttribute( 'align' ) || ''
 90 		};
 91 
 92 		// Do not set "src" on high-contrast so the alt text is displayed. (#8945)
 93 		if ( !CKEDITOR.env.hc )
 94 			attributes.src = CKEDITOR.getUrl( 'images/spacer.gif' );
 95 
 96 		if ( realElementType )
 97 			attributes[ 'data-cke-real-element-type' ] = realElementType;
 98 
 99 		if ( isResizable )
100 		{
101 			attributes[ 'data-cke-resizable' ] = isResizable;
102 
103 			var fakeStyle = new cssStyle();
104 
105 			var width = realElement.getAttribute( 'width' ),
106 				height = realElement.getAttribute( 'height' );
107 
108 			width && ( fakeStyle.rules.width = cssLength( width ) );
109 			height && ( fakeStyle.rules.height = cssLength( height ) );
110 			fakeStyle.populate( attributes );
111 		}
112 
113 		return this.document.createElement( 'img', { attributes : attributes } );
114 	};
115 
116 	CKEDITOR.editor.prototype.createFakeParserElement = function( realElement, className, realElementType, isResizable )
117 	{
118 		var lang = this.lang.fakeobjects,
119 			label = lang[ realElementType ] || lang.unknown,
120 			html;
121 
122 		var writer = new CKEDITOR.htmlParser.basicWriter();
123 		realElement.writeHtml( writer );
124 		html = writer.getHtml();
125 
126 		var attributes =
127 		{
128 			'class' : className,
129 			'data-cke-realelement' : encodeURIComponent( html ),
130 			'data-cke-real-node-type' : realElement.type,
131 			alt : label,
132 			title : label,
133 			align : realElement.attributes.align || ''
134 		};
135 
136 		// Do not set "src" on high-contrast so the alt text is displayed. (#8945)
137 		if ( !CKEDITOR.env.hc )
138 			attributes.src = CKEDITOR.getUrl( 'images/spacer.gif' );
139 
140 		if ( realElementType )
141 			attributes[ 'data-cke-real-element-type' ] = realElementType;
142 
143 		if ( isResizable )
144 		{
145 			attributes[ 'data-cke-resizable' ] = isResizable;
146 			var realAttrs = realElement.attributes,
147 				fakeStyle = new cssStyle();
148 
149 			var width = realAttrs.width,
150 				height = realAttrs.height;
151 
152 			width != undefined && ( fakeStyle.rules.width =  cssLength( width ) );
153 			height != undefined && ( fakeStyle.rules.height = cssLength ( height ) );
154 			fakeStyle.populate( attributes );
155 		}
156 
157 		return new CKEDITOR.htmlParser.element( 'img', attributes );
158 	};
159 
160 	CKEDITOR.editor.prototype.restoreRealElement = function( fakeElement )
161 	{
162 		if ( fakeElement.data( 'cke-real-node-type' ) != CKEDITOR.NODE_ELEMENT )
163 			return null;
164 
165 		var element = CKEDITOR.dom.element.createFromHtml(
166 			decodeURIComponent( fakeElement.data( 'cke-realelement' ) ),
167 			this.document );
168 
169 		if ( fakeElement.data( 'cke-resizable') )
170 		{
171 			var width = fakeElement.getStyle( 'width' ),
172 				height = fakeElement.getStyle( 'height' );
173 
174 			width && element.setAttribute( 'width', replaceCssLength( element.getAttribute( 'width' ), width ) );
175 			height && element.setAttribute( 'height', replaceCssLength( element.getAttribute( 'height' ), height ) );
176 		}
177 
178 		return element;
179 	};
180 
181 })();
182