Nation Notes module contributed by Z&H Healthcare.
[openemr.git] / library / custom_template / ckeditor / _source / plugins / blockquote / plugin.js
blob7566bfe7fe26d54700736c16be123a8eaf555dde
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 /**
7  * @file Blockquote.
8  */
10 (function()
12         function getState( editor, path )
13         {
14                 var firstBlock = path.block || path.blockLimit;
16                 if ( !firstBlock || firstBlock.getName() == 'body' )
17                         return CKEDITOR.TRISTATE_OFF;
19                 // See if the first block has a blockquote parent.
20                 if ( firstBlock.getAscendant( 'blockquote', true ) )
21                         return CKEDITOR.TRISTATE_ON;
23                 return CKEDITOR.TRISTATE_OFF;
24         }
26         function onSelectionChange( evt )
27         {
28                 var editor = evt.editor,
29                         command = editor.getCommand( 'blockquote' );
30                 command.state = getState( editor, evt.data.path );
31                 command.fire( 'state' );
32         }
34         function noBlockLeft( bqBlock )
35         {
36                 for ( var i = 0, length = bqBlock.getChildCount(), child ; i < length && ( child = bqBlock.getChild( i ) ) ; i++ )
37                 {
38                         if ( child.type == CKEDITOR.NODE_ELEMENT && child.isBlockBoundary() )
39                                 return false;
40                 }
41                 return true;
42         }
44         var commandObject =
45         {
46                 exec : function( editor )
47                 {
48                         var state = editor.getCommand( 'blockquote' ).state,
49                                 selection = editor.getSelection(),
50                                 range = selection && selection.getRanges( true )[0];
52                         if ( !range )
53                                 return;
55                         var bookmarks = selection.createBookmarks();
57                         // Kludge for #1592: if the bookmark nodes are in the beginning of
58                         // blockquote, then move them to the nearest block element in the
59                         // blockquote.
60                         if ( CKEDITOR.env.ie )
61                         {
62                                 var bookmarkStart = bookmarks[0].startNode,
63                                         bookmarkEnd = bookmarks[0].endNode,
64                                         cursor;
66                                 if ( bookmarkStart && bookmarkStart.getParent().getName() == 'blockquote' )
67                                 {
68                                         cursor = bookmarkStart;
69                                         while ( ( cursor = cursor.getNext() ) )
70                                         {
71                                                 if ( cursor.type == CKEDITOR.NODE_ELEMENT &&
72                                                                 cursor.isBlockBoundary() )
73                                                 {
74                                                         bookmarkStart.move( cursor, true );
75                                                         break;
76                                                 }
77                                         }
78                                 }
80                                 if ( bookmarkEnd
81                                                 && bookmarkEnd.getParent().getName() == 'blockquote' )
82                                 {
83                                         cursor = bookmarkEnd;
84                                         while ( ( cursor = cursor.getPrevious() ) )
85                                         {
86                                                 if ( cursor.type == CKEDITOR.NODE_ELEMENT &&
87                                                                 cursor.isBlockBoundary() )
88                                                 {
89                                                         bookmarkEnd.move( cursor );
90                                                         break;
91                                                 }
92                                         }
93                                 }
94                         }
96                         var iterator = range.createIterator(),
97                                 block;
98                         iterator.enlargeBr = editor.config.enterMode != CKEDITOR.ENTER_BR;
100                         if ( state == CKEDITOR.TRISTATE_OFF )
101                         {
102                                 var paragraphs = [];
103                                 while ( ( block = iterator.getNextParagraph() ) )
104                                         paragraphs.push( block );
106                                 // If no paragraphs, create one from the current selection position.
107                                 if ( paragraphs.length < 1 )
108                                 {
109                                         var para = editor.document.createElement( editor.config.enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ),
110                                                 firstBookmark = bookmarks.shift();
111                                         range.insertNode( para );
112                                         para.append( new CKEDITOR.dom.text( '\ufeff', editor.document ) );
113                                         range.moveToBookmark( firstBookmark );
114                                         range.selectNodeContents( para );
115                                         range.collapse( true );
116                                         firstBookmark = range.createBookmark();
117                                         paragraphs.push( para );
118                                         bookmarks.unshift( firstBookmark );
119                                 }
121                                 // Make sure all paragraphs have the same parent.
122                                 var commonParent = paragraphs[0].getParent(),
123                                         tmp = [];
124                                 for ( var i = 0 ; i < paragraphs.length ; i++ )
125                                 {
126                                         block = paragraphs[i];
127                                         commonParent = commonParent.getCommonAncestor( block.getParent() );
128                                 }
130                                 // The common parent must not be the following tags: table, tbody, tr, ol, ul.
131                                 var denyTags = { table : 1, tbody : 1, tr : 1, ol : 1, ul : 1 };
132                                 while ( denyTags[ commonParent.getName() ] )
133                                         commonParent = commonParent.getParent();
135                                 // Reconstruct the block list to be processed such that all resulting blocks
136                                 // satisfy parentNode.equals( commonParent ).
137                                 var lastBlock = null;
138                                 while ( paragraphs.length > 0 )
139                                 {
140                                         block = paragraphs.shift();
141                                         while ( !block.getParent().equals( commonParent ) )
142                                                 block = block.getParent();
143                                         if ( !block.equals( lastBlock ) )
144                                                 tmp.push( block );
145                                         lastBlock = block;
146                                 }
148                                 // If any of the selected blocks is a blockquote, remove it to prevent
149                                 // nested blockquotes.
150                                 while ( tmp.length > 0 )
151                                 {
152                                         block = tmp.shift();
153                                         if ( block.getName() == 'blockquote' )
154                                         {
155                                                 var docFrag = new CKEDITOR.dom.documentFragment( editor.document );
156                                                 while ( block.getFirst() )
157                                                 {
158                                                         docFrag.append( block.getFirst().remove() );
159                                                         paragraphs.push( docFrag.getLast() );
160                                                 }
162                                                 docFrag.replace( block );
163                                         }
164                                         else
165                                                 paragraphs.push( block );
166                                 }
168                                 // Now we have all the blocks to be included in a new blockquote node.
169                                 var bqBlock = editor.document.createElement( 'blockquote' );
170                                 bqBlock.insertBefore( paragraphs[0] );
171                                 while ( paragraphs.length > 0 )
172                                 {
173                                         block = paragraphs.shift();
174                                         bqBlock.append( block );
175                                 }
176                         }
177                         else if ( state == CKEDITOR.TRISTATE_ON )
178                         {
179                                 var moveOutNodes = [],
180                                         database = {};
182                                 while ( ( block = iterator.getNextParagraph() ) )
183                                 {
184                                         var bqParent = null,
185                                                 bqChild = null;
186                                         while ( block.getParent() )
187                                         {
188                                                 if ( block.getParent().getName() == 'blockquote' )
189                                                 {
190                                                         bqParent = block.getParent();
191                                                         bqChild = block;
192                                                         break;
193                                                 }
194                                                 block = block.getParent();
195                                         }
197                                         // Remember the blocks that were recorded down in the moveOutNodes array
198                                         // to prevent duplicates.
199                                         if ( bqParent && bqChild && !bqChild.getCustomData( 'blockquote_moveout' ) )
200                                         {
201                                                 moveOutNodes.push( bqChild );
202                                                 CKEDITOR.dom.element.setMarker( database, bqChild, 'blockquote_moveout', true );
203                                         }
204                                 }
206                                 CKEDITOR.dom.element.clearAllMarkers( database );
208                                 var movedNodes = [],
209                                         processedBlockquoteBlocks = [];
211                                 database = {};
212                                 while ( moveOutNodes.length > 0 )
213                                 {
214                                         var node = moveOutNodes.shift();
215                                         bqBlock = node.getParent();
217                                         // If the node is located at the beginning or the end, just take it out
218                                         // without splitting. Otherwise, split the blockquote node and move the
219                                         // paragraph in between the two blockquote nodes.
220                                         if ( !node.getPrevious() )
221                                                 node.remove().insertBefore( bqBlock );
222                                         else if ( !node.getNext() )
223                                                 node.remove().insertAfter( bqBlock );
224                                         else
225                                         {
226                                                 node.breakParent( node.getParent() );
227                                                 processedBlockquoteBlocks.push( node.getNext() );
228                                         }
230                                         // Remember the blockquote node so we can clear it later (if it becomes empty).
231                                         if ( !bqBlock.getCustomData( 'blockquote_processed' ) )
232                                         {
233                                                 processedBlockquoteBlocks.push( bqBlock );
234                                                 CKEDITOR.dom.element.setMarker( database, bqBlock, 'blockquote_processed', true );
235                                         }
237                                         movedNodes.push( node );
238                                 }
240                                 CKEDITOR.dom.element.clearAllMarkers( database );
242                                 // Clear blockquote nodes that have become empty.
243                                 for ( i = processedBlockquoteBlocks.length - 1 ; i >= 0 ; i-- )
244                                 {
245                                         bqBlock = processedBlockquoteBlocks[i];
246                                         if ( noBlockLeft( bqBlock ) )
247                                                 bqBlock.remove();
248                                 }
250                                 if ( editor.config.enterMode == CKEDITOR.ENTER_BR )
251                                 {
252                                         var firstTime = true;
253                                         while ( movedNodes.length )
254                                         {
255                                                 node = movedNodes.shift();
257                                                 if ( node.getName() == 'div' )
258                                                 {
259                                                         docFrag = new CKEDITOR.dom.documentFragment( editor.document );
260                                                         var needBeginBr = firstTime && node.getPrevious() &&
261                                                                         !( node.getPrevious().type == CKEDITOR.NODE_ELEMENT && node.getPrevious().isBlockBoundary() );
262                                                         if ( needBeginBr )
263                                                                 docFrag.append( editor.document.createElement( 'br' ) );
265                                                         var needEndBr = node.getNext() &&
266                                                                 !( node.getNext().type == CKEDITOR.NODE_ELEMENT && node.getNext().isBlockBoundary() );
267                                                         while ( node.getFirst() )
268                                                                 node.getFirst().remove().appendTo( docFrag );
270                                                         if ( needEndBr )
271                                                                 docFrag.append( editor.document.createElement( 'br' ) );
273                                                         docFrag.replace( node );
274                                                         firstTime = false;
275                                                 }
276                                         }
277                                 }
278                         }
280                         selection.selectBookmarks( bookmarks );
281                         editor.focus();
282                 }
283         };
285         CKEDITOR.plugins.add( 'blockquote',
286         {
287                 init : function( editor )
288                 {
289                         editor.addCommand( 'blockquote', commandObject );
291                         editor.ui.addButton( 'Blockquote',
292                                 {
293                                         label : editor.lang.blockquote,
294                                         command : 'blockquote'
295                                 } );
297                         editor.on( 'selectionChange', onSelectionChange );
298                 },
300                 requires : [ 'domiterator' ]
301         } );
302 })();