Nation Notes module contributed by Z&H Healthcare.
[openemr.git] / library / custom_template / ckeditor / _source / plugins / floatpanel / plugin.js
blob444e9d11e40d23a7fa3872fa13f8115a72bed4b0
1 /*
2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
4 */
6 CKEDITOR.plugins.add( 'floatpanel',
8         requires : [ 'panel' ]
9 });
11 (function()
13         var panels = {};
14         var isShowing = false;
16         function getPanel( editor, doc, parentElement, definition, level )
17         {
18                 // Generates the panel key: docId-eleId-skinName-langDir[-uiColor][-CSSs][-level]
19                 var key = CKEDITOR.tools.genKey( doc.getUniqueId(), parentElement.getUniqueId(), editor.skinName, editor.lang.dir,
20                         editor.uiColor || '', definition.css || '', level || '' );
22                 var panel = panels[ key ];
24                 if ( !panel )
25                 {
26                         panel = panels[ key ] = new CKEDITOR.ui.panel( doc, definition );
27                         panel.element = parentElement.append( CKEDITOR.dom.element.createFromHtml( panel.renderHtml( editor ), doc ) );
29                         panel.element.setStyles(
30                                 {
31                                         display : 'none',
32                                         position : 'absolute'
33                                 });
34                 }
36                 return panel;
37         }
39         CKEDITOR.ui.floatPanel = CKEDITOR.tools.createClass(
40         {
41                 $ : function( editor, parentElement, definition, level )
42                 {
43                         definition.forceIFrame = 1;
45                         var doc = parentElement.getDocument(),
46                                 panel = getPanel( editor, doc, parentElement, definition, level || 0 ),
47                                 element = panel.element,
48                                 iframe = element.getFirst().getFirst();
50                         this.element = element;
52                         this._ =
53                         {
54                                 // The panel that will be floating.
55                                 panel : panel,
56                                 parentElement : parentElement,
57                                 definition : definition,
58                                 document : doc,
59                                 iframe : iframe,
60                                 children : [],
61                                 dir : editor.lang.dir
62                         };
64                         editor.on( 'mode', function(){ this.hide(); }, this );
65                 },
67                 proto :
68                 {
69                         addBlock : function( name, block )
70                         {
71                                 return this._.panel.addBlock( name, block );
72                         },
74                         addListBlock : function( name, multiSelect )
75                         {
76                                 return this._.panel.addListBlock( name, multiSelect );
77                         },
79                         getBlock : function( name )
80                         {
81                                 return this._.panel.getBlock( name );
82                         },
84                         /*
85                                 corner (LTR):
86                                         1 = top-left
87                                         2 = top-right
88                                         3 = bottom-right
89                                         4 = bottom-left
91                                 corner (RTL):
92                                         1 = top-right
93                                         2 = top-left
94                                         3 = bottom-left
95                                         4 = bottom-right
96                          */
97                         showBlock : function( name, offsetParent, corner, offsetX, offsetY )
98                         {
99                                 var panel = this._.panel,
100                                         block = panel.showBlock( name );
102                                 this.allowBlur( false );
103                                 isShowing = 1;
105                                 var element = this.element,
106                                         iframe = this._.iframe,
107                                         definition = this._.definition,
108                                         position = offsetParent.getDocumentPosition( element.getDocument() ),
109                                         rtl = this._.dir == 'rtl';
111                                 var left        = position.x + ( offsetX || 0 ),
112                                         top             = position.y + ( offsetY || 0 );
114                                 // Floating panels are off by (-1px, 0px) in RTL mode. (#3438)
115                                 if ( rtl && ( corner == 1 || corner == 4 ) )
116                                         left += offsetParent.$.offsetWidth;
117                                 else if ( !rtl && ( corner == 2 || corner == 3 ) )
118                                         left += offsetParent.$.offsetWidth - 1;
120                                 if ( corner == 3 || corner == 4 )
121                                         top += offsetParent.$.offsetHeight - 1;
123                                 // Memorize offsetParent by it's ID.
124                                 this._.panel._.offsetParentId = offsetParent.getId();
126                                 element.setStyles(
127                                         {
128                                                 top : top + 'px',
129                                                 left: 0,
130                                                 display : ''
131                                         });
133                                 // Don't use display or visibility style because we need to
134                                 // calculate the rendering layout later and focus the element.
135                                 element.setOpacity( 0 );
137                                 // To allow the context menu to decrease back their width
138                                 element.getFirst().removeStyle( 'width' );
140                                 // Configure the IFrame blur event. Do that only once.
141                                 if ( !this._.blurSet )
142                                 {
143                                         // Non IE prefer the event into a window object.
144                                         var focused = CKEDITOR.env.ie ? iframe : new CKEDITOR.dom.window( iframe.$.contentWindow );
146                                         // With addEventListener compatible browsers, we must
147                                         // useCapture when registering the focus/blur events to
148                                         // guarantee they will be firing in all situations. (#3068, #3222 )
149                                         CKEDITOR.event.useCapture = true;
151                                         focused.on( 'blur', function( ev )
152                                                 {
153                                                         if ( !this.allowBlur() )
154                                                                 return;
156                                                         // As we are using capture to register the listener,
157                                                         // the blur event may get fired even when focusing
158                                                         // inside the window itself, so we must ensure the
159                                                         // target is out of it.
160                                                         var target;
161                                                         if ( CKEDITOR.env.ie && !this.allowBlur()
162                                                                  || ( target = ev.data.getTarget() )
163                                                                       && target.getName && target.getName() != 'iframe' )
164                                                                 return;
166                                                         if ( this.visible && !this._.activeChild && !isShowing )
167                                                                 this.hide();
168                                                 },
169                                                 this );
171                                         focused.on( 'focus', function()
172                                                 {
173                                                         this._.focused = true;
174                                                         this.hideChild();
175                                                         this.allowBlur( true );
176                                                 },
177                                                 this );
179                                         CKEDITOR.event.useCapture = false;
181                                         this._.blurSet = 1;
182                                 }
184                                 panel.onEscape = CKEDITOR.tools.bind( function( keystroke )
185                                         {
186                                                 if ( this.onEscape && this.onEscape( keystroke ) === false )
187                                                         return false;
188                                         },
189                                         this );
191                                 CKEDITOR.tools.setTimeout( function()
192                                         {
193                                                 if ( rtl )
194                                                         left -= element.$.offsetWidth;
196                                                 var panelLoad = CKEDITOR.tools.bind( function ()
197                                                 {
198                                                         var target = element.getFirst();
200                                                         if ( block.autoSize )
201                                                         {
202                                                                 // We must adjust first the width or IE6 could include extra lines in the height computation
203                                                                 var widthNode = block.element.$;
205                                                                 if ( CKEDITOR.env.gecko || CKEDITOR.env.opera )
206                                                                         widthNode = widthNode.parentNode;
208                                                                 if ( CKEDITOR.env.ie )
209                                                                         widthNode = widthNode.document.body;
211                                                                 var width = widthNode.scrollWidth;
212                                                                 // Account for extra height needed due to IE quirks box model bug:
213                                                                 // http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug
214                                                                 // (#3426)
215                                                                 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && width > 0 )
216                                                                         width += ( target.$.offsetWidth || 0 ) - ( target.$.clientWidth || 0 );
217                                                                 // A little extra at the end.
218                                                                 // If not present, IE6 might break into the next line, but also it looks better this way
219                                                                 width += 4 ;
221                                                                 target.setStyle( 'width', width + 'px' );
223                                                                 // IE doesn't compute the scrollWidth if a filter is applied previously
224                                                                 block.element.addClass( 'cke_frameLoaded' );
226                                                                 var height = block.element.$.scrollHeight;
228                                                                 // Account for extra height needed due to IE quirks box model bug:
229                                                                 // http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug
230                                                                 // (#3426)
231                                                                 if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && height > 0 )
232                                                                         height += ( target.$.offsetHeight || 0 ) - ( target.$.clientHeight || 0 );
234                                                                 target.setStyle( 'height', height + 'px' );
236                                                                 // Fix IE < 8 visibility.
237                                                                 panel._.currentBlock.element.setStyle( 'display', 'none' ).removeStyle( 'display' );
238                                                         }
239                                                         else
240                                                                 target.removeStyle( 'height' );
242                                                         var panelElement = panel.element,
243                                                                 panelWindow = panelElement.getWindow(),
244                                                                 windowScroll = panelWindow.getScrollPosition(),
245                                                                 viewportSize = panelWindow.getViewPaneSize(),
246                                                                 panelSize =
247                                                                 {
248                                                                         'height' : panelElement.$.offsetHeight,
249                                                                         'width' : panelElement.$.offsetWidth
250                                                                 };
252                                                         // If the menu is horizontal off, shift it toward
253                                                         // the opposite language direction.
254                                                         if ( rtl ? left < 0 : left + panelSize.width > viewportSize.width + windowScroll.x )
255                                                                 left += ( panelSize.width * ( rtl ? 1 : -1 ) );
257                                                         // Vertical off screen is simpler.
258                                                         if ( top + panelSize.height > viewportSize.height + windowScroll.y )
259                                                                 top -= panelSize.height;
261                                                         // If IE is in RTL, we have troubles with absolute
262                                                         // position and horizontal scrolls. Here we have a
263                                                         // series of hacks to workaround it. (#6146)
264                                                         if ( CKEDITOR.env.ie )
265                                                         {
266                                                                 var offsetParent = new CKEDITOR.dom.element( element.$.offsetParent ),
267                                                                         scrollParent = offsetParent;
269                                                                 // Quirks returns <body>, but standards returns <html>.
270                                                                 if ( scrollParent.getName() == 'html' )
271                                                                         scrollParent = scrollParent.getDocument().getBody();
273                                                                 if ( scrollParent.getComputedStyle( 'direction' ) == 'rtl' )
274                                                                 {
275                                                                         // For IE8, there is not much logic on this, but it works.
276                                                                         if ( CKEDITOR.env.ie8Compat )
277                                                                                 left -= element.getDocument().getDocumentElement().$.scrollLeft * 2;
278                                                                         else
279                                                                                 left -= ( offsetParent.$.scrollWidth - offsetParent.$.clientWidth );
280                                                                 }
281                                                         }
283                                                         // Trigger the onHide event of the previously active panel to prevent
284                                                         // incorrect styles from being applied (#6170)
285                                                         var innerElement = element.getFirst(),
286                                                                 activePanel;
287                                                         if ( ( activePanel = innerElement.getCustomData( 'activePanel' ) ) )
288                                                                 activePanel.onHide && activePanel.onHide.call( this, 1 );
289                                                         innerElement.setCustomData( 'activePanel', this );
291                                                         element.setStyles(
292                                                                 {
293                                                                         top : top + 'px',
294                                                                         left : left + 'px'
295                                                                 } );
296                                                         element.setOpacity( 1 );
297                                                 } , this );
299                                                 panel.isLoaded ? panelLoad() : panel.onLoad = panelLoad;
301                                                 // Set the panel frame focus, so the blur event gets fired.
302                                                 CKEDITOR.tools.setTimeout( function()
303                                                 {
304                                                         iframe.$.contentWindow.focus();
305                                                         // We need this get fired manually because of unfired focus() function.
306                                                         this.allowBlur( true );
307                                                 }, 0, this);
308                                         },  CKEDITOR.env.air ? 200 : 0, this);
309                                 this.visible = 1;
311                                 if ( this.onShow )
312                                         this.onShow.call( this );
314                                 isShowing = 0;
315                         },
317                         hide : function()
318                         {
319                                 if ( this.visible && ( !this.onHide || this.onHide.call( this ) !== true ) )
320                                 {
321                                         this.hideChild();
322                                         this.element.setStyle( 'display', 'none' );
323                                         this.visible = 0;
324                                         this.element.getFirst().removeCustomData( 'activePanel' );
325                                 }
326                         },
328                         allowBlur : function( allow )   // Prevent editor from hiding the panel. #3222.
329                         {
330                                 var panel = this._.panel;
331                                 if ( allow != undefined )
332                                         panel.allowBlur = allow;
334                                 return panel.allowBlur;
335                         },
337                         showAsChild : function( panel, blockName, offsetParent, corner, offsetX, offsetY )
338                         {
339                                 // Skip reshowing of child which is already visible.
340                                 if ( this._.activeChild == panel && panel._.panel._.offsetParentId == offsetParent.getId() )
341                                         return;
343                                 this.hideChild();
345                                 panel.onHide = CKEDITOR.tools.bind( function()
346                                         {
347                                                 // Use a timeout, so we give time for this menu to get
348                                                 // potentially focused.
349                                                 CKEDITOR.tools.setTimeout( function()
350                                                         {
351                                                                 if ( !this._.focused )
352                                                                         this.hide();
353                                                         },
354                                                         0, this );
355                                         },
356                                         this );
358                                 this._.activeChild = panel;
359                                 this._.focused = false;
361                                 panel.showBlock( blockName, offsetParent, corner, offsetX, offsetY );
363                                 /* #3767 IE: Second level menu may not have borders */
364                                 if ( CKEDITOR.env.ie7Compat || ( CKEDITOR.env.ie8 && CKEDITOR.env.ie6Compat ) )
365                                 {
366                                         setTimeout(function()
367                                                 {
368                                                         panel.element.getChild( 0 ).$.style.cssText += '';
369                                                 }, 100);
370                                 }
371                         },
373                         hideChild : function()
374                         {
375                                 var activeChild = this._.activeChild;
377                                 if ( activeChild )
378                                 {
379                                         delete activeChild.onHide;
380                                         delete this._.activeChild;
381                                         activeChild.hide();
382                                 }
383                         }
384                 }
385         });
387         CKEDITOR.on( 'instanceDestroyed', function()
388         {
389                 var isLastInstance = CKEDITOR.tools.isEmpty( CKEDITOR.instances );
391                 for ( var i in panels )
392                 {
393                         var panel = panels[ i ];
394                         // Safe to destroy it since there're no more instances.(#4241)
395                         if ( isLastInstance )
396                                 panel.destroy();
397                         // Panel might be used by other instances, just hide them.(#4552)
398                         else
399                                 panel.element.hide();
400                 }
401                 // Remove the registration.
402                 isLastInstance && ( panels = {} );
404         } );
405 })();