diff options
Diffstat (limited to 'sources/plugins/maximize/plugin.js')
-rw-r--r-- | sources/plugins/maximize/plugin.js | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/sources/plugins/maximize/plugin.js b/sources/plugins/maximize/plugin.js new file mode 100644 index 0000000..ae621f1 --- /dev/null +++ b/sources/plugins/maximize/plugin.js | |||
@@ -0,0 +1,314 @@ | |||
1 | /** | ||
2 | * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. | ||
3 | * For licensing, see LICENSE.md or http://ckeditor.com/license | ||
4 | */ | ||
5 | |||
6 | ( function() { | ||
7 | function protectFormStyles( formElement ) { | ||
8 | if ( !formElement || formElement.type != CKEDITOR.NODE_ELEMENT || formElement.getName() != 'form' ) | ||
9 | return []; | ||
10 | |||
11 | var hijackRecord = [], | ||
12 | hijackNames = [ 'style', 'className' ]; | ||
13 | for ( var i = 0; i < hijackNames.length; i++ ) { | ||
14 | var name = hijackNames[ i ]; | ||
15 | var $node = formElement.$.elements.namedItem( name ); | ||
16 | if ( $node ) { | ||
17 | var hijackNode = new CKEDITOR.dom.element( $node ); | ||
18 | hijackRecord.push( [ hijackNode, hijackNode.nextSibling ] ); | ||
19 | hijackNode.remove(); | ||
20 | } | ||
21 | } | ||
22 | |||
23 | return hijackRecord; | ||
24 | } | ||
25 | |||
26 | function restoreFormStyles( formElement, hijackRecord ) { | ||
27 | if ( !formElement || formElement.type != CKEDITOR.NODE_ELEMENT || formElement.getName() != 'form' ) | ||
28 | return; | ||
29 | |||
30 | if ( hijackRecord.length > 0 ) { | ||
31 | for ( var i = hijackRecord.length - 1; i >= 0; i-- ) { | ||
32 | var node = hijackRecord[ i ][ 0 ]; | ||
33 | var sibling = hijackRecord[ i ][ 1 ]; | ||
34 | if ( sibling ) | ||
35 | node.insertBefore( sibling ); | ||
36 | else | ||
37 | node.appendTo( formElement ); | ||
38 | } | ||
39 | } | ||
40 | } | ||
41 | |||
42 | function saveStyles( element, isInsideEditor ) { | ||
43 | var data = protectFormStyles( element ); | ||
44 | var retval = {}; | ||
45 | |||
46 | var $element = element.$; | ||
47 | |||
48 | if ( !isInsideEditor ) { | ||
49 | retval[ 'class' ] = $element.className || ''; | ||
50 | $element.className = ''; | ||
51 | } | ||
52 | |||
53 | retval.inline = $element.style.cssText || ''; | ||
54 | if ( !isInsideEditor ) // Reset any external styles that might interfere. (#2474) | ||
55 | $element.style.cssText = 'position: static; overflow: visible'; | ||
56 | |||
57 | restoreFormStyles( data ); | ||
58 | return retval; | ||
59 | } | ||
60 | |||
61 | function restoreStyles( element, savedStyles ) { | ||
62 | var data = protectFormStyles( element ); | ||
63 | var $element = element.$; | ||
64 | if ( 'class' in savedStyles ) | ||
65 | $element.className = savedStyles[ 'class' ]; | ||
66 | if ( 'inline' in savedStyles ) | ||
67 | $element.style.cssText = savedStyles.inline; | ||
68 | restoreFormStyles( data ); | ||
69 | } | ||
70 | |||
71 | function refreshCursor( editor ) { | ||
72 | if ( editor.editable().isInline() ) | ||
73 | return; | ||
74 | |||
75 | // Refresh all editor instances on the page (#5724). | ||
76 | var all = CKEDITOR.instances; | ||
77 | for ( var i in all ) { | ||
78 | var one = all[ i ]; | ||
79 | if ( one.mode == 'wysiwyg' && !one.readOnly ) { | ||
80 | var body = one.document.getBody(); | ||
81 | // Refresh 'contentEditable' otherwise | ||
82 | // DOM lifting breaks design mode. (#5560) | ||
83 | body.setAttribute( 'contentEditable', false ); | ||
84 | body.setAttribute( 'contentEditable', true ); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | if ( editor.editable().hasFocus ) { | ||
89 | editor.toolbox.focus(); | ||
90 | editor.focus(); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | CKEDITOR.plugins.add( 'maximize', { | ||
95 | // jscs:disable maximumLineLength | ||
96 | lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE% | ||
97 | // jscs:enable maximumLineLength | ||
98 | icons: 'maximize', // %REMOVE_LINE_CORE% | ||
99 | hidpi: true, // %REMOVE_LINE_CORE% | ||
100 | init: function( editor ) { | ||
101 | // Maximize plugin isn't available in inline mode yet. | ||
102 | if ( editor.elementMode == CKEDITOR.ELEMENT_MODE_INLINE ) | ||
103 | return; | ||
104 | |||
105 | var lang = editor.lang; | ||
106 | var mainDocument = CKEDITOR.document, | ||
107 | mainWindow = mainDocument.getWindow(); | ||
108 | |||
109 | // Saved selection and scroll position for the editing area. | ||
110 | var savedSelection, savedScroll; | ||
111 | |||
112 | // Saved scroll position for the outer window. | ||
113 | var outerScroll; | ||
114 | |||
115 | // Saved resize handler function. | ||
116 | function resizeHandler() { | ||
117 | var viewPaneSize = mainWindow.getViewPaneSize(); | ||
118 | editor.resize( viewPaneSize.width, viewPaneSize.height, null, true ); | ||
119 | } | ||
120 | |||
121 | // Retain state after mode switches. | ||
122 | var savedState = CKEDITOR.TRISTATE_OFF; | ||
123 | |||
124 | editor.addCommand( 'maximize', { | ||
125 | // Disabled on iOS (#8307). | ||
126 | modes: { wysiwyg: !CKEDITOR.env.iOS, source: !CKEDITOR.env.iOS }, | ||
127 | readOnly: 1, | ||
128 | editorFocus: false, | ||
129 | exec: function() { | ||
130 | var container = editor.container.getFirst( function( node ) { | ||
131 | return node.type == CKEDITOR.NODE_ELEMENT && node.hasClass( 'cke_inner' ); | ||
132 | } ); | ||
133 | var contents = editor.ui.space( 'contents' ); | ||
134 | |||
135 | // Save current selection and scroll position in editing area. | ||
136 | if ( editor.mode == 'wysiwyg' ) { | ||
137 | var selection = editor.getSelection(); | ||
138 | savedSelection = selection && selection.getRanges(); | ||
139 | savedScroll = mainWindow.getScrollPosition(); | ||
140 | } else { | ||
141 | var $textarea = editor.editable().$; | ||
142 | savedSelection = !CKEDITOR.env.ie && [ $textarea.selectionStart, $textarea.selectionEnd ]; | ||
143 | savedScroll = [ $textarea.scrollLeft, $textarea.scrollTop ]; | ||
144 | } | ||
145 | |||
146 | // Go fullscreen if the state is off. | ||
147 | if ( this.state == CKEDITOR.TRISTATE_OFF ) { | ||
148 | // Add event handler for resizing. | ||
149 | mainWindow.on( 'resize', resizeHandler ); | ||
150 | |||
151 | // Save the scroll bar position. | ||
152 | outerScroll = mainWindow.getScrollPosition(); | ||
153 | |||
154 | // Save and reset the styles for the entire node tree. | ||
155 | var currentNode = editor.container; | ||
156 | while ( ( currentNode = currentNode.getParent() ) ) { | ||
157 | currentNode.setCustomData( 'maximize_saved_styles', saveStyles( currentNode ) ); | ||
158 | // Show under floatpanels (-1) and context menu (-2). | ||
159 | currentNode.setStyle( 'z-index', editor.config.baseFloatZIndex - 5 ); | ||
160 | } | ||
161 | contents.setCustomData( 'maximize_saved_styles', saveStyles( contents, true ) ); | ||
162 | container.setCustomData( 'maximize_saved_styles', saveStyles( container, true ) ); | ||
163 | |||
164 | // Hide scroll bars. | ||
165 | var styles = { | ||
166 | overflow: CKEDITOR.env.webkit ? '' : 'hidden', // #6896 | ||
167 | width: 0, | ||
168 | height: 0 | ||
169 | }; | ||
170 | |||
171 | mainDocument.getDocumentElement().setStyles( styles ); | ||
172 | !CKEDITOR.env.gecko && mainDocument.getDocumentElement().setStyle( 'position', 'fixed' ); | ||
173 | !( CKEDITOR.env.gecko && CKEDITOR.env.quirks ) && mainDocument.getBody().setStyles( styles ); | ||
174 | |||
175 | // Scroll to the top left (IE needs some time for it - #4923). | ||
176 | CKEDITOR.env.ie ? setTimeout( function() { | ||
177 | mainWindow.$.scrollTo( 0, 0 ); | ||
178 | }, 0 ) : mainWindow.$.scrollTo( 0, 0 ); | ||
179 | |||
180 | // Resize and move to top left. | ||
181 | // Special treatment for FF Quirks (#7284) | ||
182 | container.setStyle( 'position', CKEDITOR.env.gecko && CKEDITOR.env.quirks ? 'fixed' : 'absolute' ); | ||
183 | container.$.offsetLeft; // SAFARI BUG: See #2066. | ||
184 | container.setStyles( { | ||
185 | // Show under floatpanels (-1) and context menu (-2). | ||
186 | 'z-index': editor.config.baseFloatZIndex - 5, | ||
187 | left: '0px', | ||
188 | top: '0px' | ||
189 | } ); | ||
190 | |||
191 | // Add cke_maximized class before resize handle since that will change things sizes (#5580) | ||
192 | container.addClass( 'cke_maximized' ); | ||
193 | |||
194 | resizeHandler(); | ||
195 | |||
196 | // Still not top left? Fix it. (Bug #174) | ||
197 | var offset = container.getDocumentPosition(); | ||
198 | container.setStyles( { | ||
199 | left: ( -1 * offset.x ) + 'px', | ||
200 | top: ( -1 * offset.y ) + 'px' | ||
201 | } ); | ||
202 | |||
203 | // Fixing positioning editor chrome in Firefox break design mode. (#5149) | ||
204 | CKEDITOR.env.gecko && refreshCursor( editor ); | ||
205 | } | ||
206 | // Restore from fullscreen if the state is on. | ||
207 | else if ( this.state == CKEDITOR.TRISTATE_ON ) { | ||
208 | // Remove event handler for resizing. | ||
209 | mainWindow.removeListener( 'resize', resizeHandler ); | ||
210 | |||
211 | // Restore CSS styles for the entire node tree. | ||
212 | var editorElements = [ contents, container ]; | ||
213 | for ( var i = 0; i < editorElements.length; i++ ) { | ||
214 | restoreStyles( editorElements[ i ], editorElements[ i ].getCustomData( 'maximize_saved_styles' ) ); | ||
215 | editorElements[ i ].removeCustomData( 'maximize_saved_styles' ); | ||
216 | } | ||
217 | |||
218 | currentNode = editor.container; | ||
219 | while ( ( currentNode = currentNode.getParent() ) ) { | ||
220 | restoreStyles( currentNode, currentNode.getCustomData( 'maximize_saved_styles' ) ); | ||
221 | currentNode.removeCustomData( 'maximize_saved_styles' ); | ||
222 | } | ||
223 | |||
224 | // Restore the window scroll position. | ||
225 | CKEDITOR.env.ie ? setTimeout( function() { | ||
226 | mainWindow.$.scrollTo( outerScroll.x, outerScroll.y ); | ||
227 | }, 0 ) : mainWindow.$.scrollTo( outerScroll.x, outerScroll.y ); | ||
228 | |||
229 | // Remove cke_maximized class. | ||
230 | container.removeClass( 'cke_maximized' ); | ||
231 | |||
232 | // Webkit requires a re-layout on editor chrome. (#6695) | ||
233 | if ( CKEDITOR.env.webkit ) { | ||
234 | container.setStyle( 'display', 'inline' ); | ||
235 | setTimeout( function() { | ||
236 | container.setStyle( 'display', 'block' ); | ||
237 | }, 0 ); | ||
238 | } | ||
239 | |||
240 | // Emit a resize event, because this time the size is modified in | ||
241 | // restoreStyles. | ||
242 | editor.fire( 'resize', { | ||
243 | outerHeight: editor.container.$.offsetHeight, | ||
244 | contentsHeight: contents.$.offsetHeight, | ||
245 | outerWidth: editor.container.$.offsetWidth | ||
246 | } ); | ||
247 | } | ||
248 | |||
249 | this.toggleState(); | ||
250 | |||
251 | // Toggle button label. | ||
252 | var button = this.uiItems[ 0 ]; | ||
253 | // Only try to change the button if it exists (#6166) | ||
254 | if ( button ) { | ||
255 | var label = ( this.state == CKEDITOR.TRISTATE_OFF ) ? lang.maximize.maximize : lang.maximize.minimize; | ||
256 | var buttonNode = CKEDITOR.document.getById( button._.id ); | ||
257 | buttonNode.getChild( 1 ).setHtml( label ); | ||
258 | buttonNode.setAttribute( 'title', label ); | ||
259 | buttonNode.setAttribute( 'href', 'javascript:void("' + label + '");' ); // jshint ignore:line | ||
260 | } | ||
261 | |||
262 | // Restore selection and scroll position in editing area. | ||
263 | if ( editor.mode == 'wysiwyg' ) { | ||
264 | if ( savedSelection ) { | ||
265 | // Fixing positioning editor chrome in Firefox break design mode. (#5149) | ||
266 | CKEDITOR.env.gecko && refreshCursor( editor ); | ||
267 | |||
268 | editor.getSelection().selectRanges( savedSelection ); | ||
269 | var element = editor.getSelection().getStartElement(); | ||
270 | element && element.scrollIntoView( true ); | ||
271 | } else { | ||
272 | mainWindow.$.scrollTo( savedScroll.x, savedScroll.y ); | ||
273 | } | ||
274 | } else { | ||
275 | if ( savedSelection ) { | ||
276 | $textarea.selectionStart = savedSelection[ 0 ]; | ||
277 | $textarea.selectionEnd = savedSelection[ 1 ]; | ||
278 | } | ||
279 | $textarea.scrollLeft = savedScroll[ 0 ]; | ||
280 | $textarea.scrollTop = savedScroll[ 1 ]; | ||
281 | } | ||
282 | |||
283 | savedSelection = savedScroll = null; | ||
284 | savedState = this.state; | ||
285 | |||
286 | editor.fire( 'maximize', this.state ); | ||
287 | }, | ||
288 | canUndo: false | ||
289 | } ); | ||
290 | |||
291 | editor.ui.addButton && editor.ui.addButton( 'Maximize', { | ||
292 | label: lang.maximize.maximize, | ||
293 | command: 'maximize', | ||
294 | toolbar: 'tools,10' | ||
295 | } ); | ||
296 | |||
297 | // Restore the command state after mode change, unless it has been changed to disabled (#6467) | ||
298 | editor.on( 'mode', function() { | ||
299 | var command = editor.getCommand( 'maximize' ); | ||
300 | command.setState( command.state == CKEDITOR.TRISTATE_DISABLED ? CKEDITOR.TRISTATE_DISABLED : savedState ); | ||
301 | }, null, null, 100 ); | ||
302 | } | ||
303 | } ); | ||
304 | } )(); | ||
305 | |||
306 | /** | ||
307 | * Event fired when the maximize command is called. | ||
308 | * It also indicates whether an editor is maximized or not. | ||
309 | * | ||
310 | * @event maximize | ||
311 | * @member CKEDITOR.editor | ||
312 | * @param {CKEDITOR.editor} editor This editor instance. | ||
313 | * @param {Number} data Current state of the command. See {@link CKEDITOR#TRISTATE_ON} and {@link CKEDITOR#TRISTATE_OFF}. | ||
314 | */ | ||