      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 (function()
      7 {
      8 	function protectFormStyles( formElement )
      9 	{
     10 		if ( !formElement || formElement.type != CKEDITOR.NODE_ELEMENT || formElement.getName() != 'form' )
     11 			return [];
     12
     13 		var hijackRecord = [];
     14 		var hijackNames = [ 'style', 'className' ];
     15 		for ( var i = 0 ; i < hijackNames.length ; i++ )
     16 		{
     17 			var name = hijackNames[i];
     18 			var $node = formElement.$.elements.namedItem( name );
     19 			if ( $node )
     20 			{
     21 				var hijackNode = new CKEDITOR.dom.element( $node );
     22 				hijackRecord.push( [ hijackNode, hijackNode.nextSibling ] );
     23 				hijackNode.remove();
     24 			}
     25 		}
     26
     27 		return hijackRecord;
     28 	}
     29
     30 	function restoreFormStyles( formElement, hijackRecord )
     31 	{
     32 		if ( !formElement || formElement.type != CKEDITOR.NODE_ELEMENT || formElement.getName() != 'form' )
     33 			return;
     34
     35 		if ( hijackRecord.length > 0 )
     36 		{
     37 			for ( var i = hijackRecord.length - 1 ; i >= 0 ; i-- )
     38 			{
     39 				var node = hijackRecord[i][0];
     40 				var sibling = hijackRecord[i][1];
     41 				if ( sibling )
     42 					node.insertBefore( sibling );
     43 				else
     44 					node.appendTo( formElement );
     45 			}
     46 		}
     47 	}
     48
     49 	function saveStyles( element, isInsideEditor )
     50 	{
     51 		var data = protectFormStyles( element );
     52 		var retval = {};
     53
     54 		var $element = element.$;
     55
     56 		if ( !isInsideEditor )
     57 		{
     58 			retval[ 'class' ] = $element.className || '';
     59 			$element.className = '';
     60 		}
     61
     62 		retval.inline = $element.style.cssText || '';
     63 		if ( !isInsideEditor )		// Reset any external styles that might interfere. (#2474)
     64 			$element.style.cssText = 'position: static; overflow: visible';
     65
     66 		restoreFormStyles( data );
     67 		return retval;
     68 	}
     69
     70 	function restoreStyles( element, savedStyles )
     71 	{
     72 		var data = protectFormStyles( element );
     73 		var $element = element.$;
     74 		if ( 'class' in savedStyles )
     75 			$element.className = savedStyles[ 'class' ];
     76 		if ( 'inline' in savedStyles )
     77 			$element.style.cssText = savedStyles.inline;
     78 		restoreFormStyles( data );
     79 	}
     80
     81 	function getResizeHandler( mainWindow, editor )
     82 	{
     83 		return function()
     84 		{
     85 			var viewPaneSize = mainWindow.getViewPaneSize();
     86 			editor.resize( viewPaneSize.width, viewPaneSize.height, null, true );
     87 		};
     88 	}
     89
     90 	CKEDITOR.plugins.add( 'maximize',
     91 	{
     92 		init : function( editor )
     93 		{
     94 			var lang = editor.lang;
     95 			var mainDocument = CKEDITOR.document;
     96 			var mainWindow = mainDocument.getWindow();
     97
     98 			// Saved selection and scroll position for the editing area.
     99 			var savedSelection;
    100 			var savedScroll;
    101
    102 			// Saved scroll position for the outer window.
    103 			var outerScroll;
    104
    105 			// Saved resize handler function.
    106 			var resizeHandler = getResizeHandler( mainWindow, editor );
    107
    108 			// Retain state after mode switches.
    109 			var savedState = CKEDITOR.TRISTATE_OFF;
    110
    111 			editor.addCommand( 'maximize',
    112 				{
    113 					modes : { wysiwyg : 1, source : 1 },
    114
    115 					exec : function()
    116 					{
    117 						var container = editor.container.getChild( [ 0, 0 ] );
    118 						var contents = editor.getThemeSpace( 'contents' );
    119
    120 						// Save current selection and scroll position in editing area.
    121 						if ( editor.mode == 'wysiwyg' )
    122 						{
    123 							savedSelection = editor.getSelection().getRanges();
    124 							savedScroll = mainWindow.getScrollPosition();
    125 						}
    126 						else
    127 						{
    128 							var $textarea = editor.textarea.$;
    129 							savedSelection = !CKEDITOR.env.ie && [ $textarea.selectionStart, $textarea.selectionEnd ];
    130 							savedScroll = [ $textarea.scrollLeft, $textarea.scrollTop ];
    131 						}
    132
    133 						if ( this.state == CKEDITOR.TRISTATE_OFF )		// Go fullscreen if the state is off.
    134 						{
    135 							// Add event handler for resizing.
    136 							mainWindow.on( 'resize', resizeHandler );
    137
    138 							// Save the scroll bar position.
    139 							outerScroll = mainWindow.getScrollPosition();
    140
    141 							// Save and reset the styles for the entire node tree.
    142 							var currentNode = editor.container;
    143 							while ( ( currentNode = currentNode.getParent() ) )
    144 							{
    145 								currentNode.setCustomData( 'maximize_saved_styles', saveStyles( currentNode ) );
    146 								currentNode.setStyle( 'z-index', editor.config.baseFloatZIndex - 1 );
    147 							}
    148 							contents.setCustomData( 'maximize_saved_styles', saveStyles( contents, true ) );
    149 							container.setCustomData( 'maximize_saved_styles', saveStyles( container, true ) );
    150
    151 							// Hide scroll bars.
    152 							if ( CKEDITOR.env.ie )
    153 							{
    154 								mainDocument.$.documentElement.style.overflow =
    155 									mainDocument.getBody().$.style.overflow = 'hidden';
    156 							}
    157 							else
    158 							{
    159 								mainDocument.getBody().setStyles(
    160 									{
    161 										overflow : 'hidden',
    162 										width : '0px',
    163 										height : '0px'
    164 									} );
    165 							}
    166
    167 							// Scroll to the top left.
    168 							mainWindow.$.scrollTo( 0, 0 );
    169
    170 							// Resize and move to top left.
    171 							var viewPaneSize = mainWindow.getViewPaneSize();
    172 							container.setStyle( 'position', 'absolute' );
    173 							container.$.offsetLeft;			// SAFARI BUG: See #2066.
    174 							container.setStyles(
    175 								{
    176 									'z-index' : editor.config.baseFloatZIndex - 1,
    177 									left : '0px',
    178 									top : '0px'
    179 								} );
    180 							editor.resize( viewPaneSize.width, viewPaneSize.height, null, true );
    181
    182 							// Still not top left? Fix it. (Bug #174)
    183 							var offset = container.getDocumentPosition();
    184 							container.setStyles(
    185 								{
    186 									left : ( -1 * offset.x ) + 'px',
    187 									top : ( -1 * offset.y ) + 'px'
    188 								} );
    189
    190 							// Add cke_maximized class.
    191 							container.addClass( 'cke_maximized' );
    192 						}
    193 						else if ( this.state == CKEDITOR.TRISTATE_ON )	// Restore from fullscreen if the state is on.
    194 						{
    195 							// Remove event handler for resizing.
    196 							mainWindow.removeListener( 'resize', resizeHandler );
    197
    198 							// Restore CSS styles for the entire node tree.
    199 							var editorElements = [ contents, container ];
    200 							for ( var i = 0 ; i < editorElements.length ; i++ )
    201 							{
    202 								restoreStyles( editorElements[i], editorElements[i].getCustomData( 'maximize_saved_styles' ) );
    203 								editorElements[i].removeCustomData( 'maximize_saved_styles' );
    204 							}
    205
    206 							currentNode = editor.container;
    207 							while ( ( currentNode = currentNode.getParent() ) )
    208 							{
    209 								restoreStyles( currentNode, currentNode.getCustomData( 'maximize_saved_styles' ) );
    210 								currentNode.removeCustomData( 'maximize_saved_styles' );
    211 							}
    212
    213 							// Restore the window scroll position.
    214 							mainWindow.$.scrollTo( outerScroll.x, outerScroll.y );
    215
    216 							// Remove cke_maximized class.
    217 							container.removeClass( 'cke_maximized' );
    218
    219 							// Emit a resize event, because this time the size is modified in
    220 							// restoreStyles.
    221 							editor.fire( 'resize' );
    222 						}
    223
    224 						this.toggleState();
    225
    226 						// Restore selection and scroll position in editing area.
    227 						if ( editor.mode == 'wysiwyg' )
    228 						{
    229 							editor.getSelection().selectRanges( savedSelection );
    230
    231 							var element = editor.getSelection().getStartElement();
    232 							if ( element )
    233 								element.scrollIntoView( true );
    234 							else
    235 								mainWindow.$.scrollTo( savedScroll.x, savedScroll.y );
    236 						}
    237 						else
    238 						{
    239 							if ( savedSelection )
    240 							{
    241 								$textarea.selectionStart = savedSelection[0];
    242 								$textarea.selectionEnd = savedSelection[1];
    243 							}
    244 							$textarea.scrollLeft = savedScroll[0];
    245 							$textarea.scrollTop = savedScroll[1];
    246 						}
    247
    248 						savedSelection = savedScroll = null;
    249 						savedState = this.state;
    250 					},
    251 					canUndo : false
    252 				} );
    253
    254 			editor.ui.addButton( 'Maximize',
    255 				{
    256 					label : lang.maximize,
    257 					command : 'maximize'
    258 				} );
    259
    260 			// Restore the command state after mode change.
    261 			editor.on( 'mode', function()
    262 				{
    263 					editor.getCommand( 'maximize' ).setState( savedState );
    264 				}, null, null, 100 );
    265 		}
    266 	} );
    267 })();
    268