]>
Commit | Line | Data |
---|---|---|
7adcb81e | 1 | /**\r |
3b35bd27 | 2 | * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.\r |
7adcb81e IB |
3 | * For licensing, see LICENSE.md or http://ckeditor.com/license\r |
4 | */\r | |
5 | \r | |
6 | ( function() {\r | |
7 | function noBlockLeft( bqBlock ) {\r | |
8 | for ( var i = 0, length = bqBlock.getChildCount(), child; i < length && ( child = bqBlock.getChild( i ) ); i++ ) {\r | |
9 | if ( child.type == CKEDITOR.NODE_ELEMENT && child.isBlockBoundary() )\r | |
10 | return false;\r | |
11 | }\r | |
12 | return true;\r | |
13 | }\r | |
14 | \r | |
15 | var commandObject = {\r | |
16 | exec: function( editor ) {\r | |
17 | var state = editor.getCommand( 'blockquote' ).state,\r | |
18 | selection = editor.getSelection(),\r | |
19 | range = selection && selection.getRanges()[ 0 ];\r | |
20 | \r | |
21 | if ( !range )\r | |
22 | return;\r | |
23 | \r | |
24 | var bookmarks = selection.createBookmarks();\r | |
25 | \r | |
26 | // Kludge for #1592: if the bookmark nodes are in the beginning of\r | |
27 | // blockquote, then move them to the nearest block element in the\r | |
28 | // blockquote.\r | |
29 | if ( CKEDITOR.env.ie ) {\r | |
30 | var bookmarkStart = bookmarks[ 0 ].startNode,\r | |
31 | bookmarkEnd = bookmarks[ 0 ].endNode,\r | |
32 | cursor;\r | |
33 | \r | |
34 | if ( bookmarkStart && bookmarkStart.getParent().getName() == 'blockquote' ) {\r | |
35 | cursor = bookmarkStart;\r | |
36 | while ( ( cursor = cursor.getNext() ) ) {\r | |
37 | if ( cursor.type == CKEDITOR.NODE_ELEMENT && cursor.isBlockBoundary() ) {\r | |
38 | bookmarkStart.move( cursor, true );\r | |
39 | break;\r | |
40 | }\r | |
41 | }\r | |
42 | }\r | |
43 | \r | |
44 | if ( bookmarkEnd && bookmarkEnd.getParent().getName() == 'blockquote' ) {\r | |
45 | cursor = bookmarkEnd;\r | |
46 | while ( ( cursor = cursor.getPrevious() ) ) {\r | |
47 | if ( cursor.type == CKEDITOR.NODE_ELEMENT && cursor.isBlockBoundary() ) {\r | |
48 | bookmarkEnd.move( cursor );\r | |
49 | break;\r | |
50 | }\r | |
51 | }\r | |
52 | }\r | |
53 | }\r | |
54 | \r | |
55 | var iterator = range.createIterator(),\r | |
56 | block;\r | |
57 | iterator.enlargeBr = editor.config.enterMode != CKEDITOR.ENTER_BR;\r | |
58 | \r | |
59 | if ( state == CKEDITOR.TRISTATE_OFF ) {\r | |
60 | var paragraphs = [];\r | |
61 | while ( ( block = iterator.getNextParagraph() ) )\r | |
62 | paragraphs.push( block );\r | |
63 | \r | |
64 | // If no paragraphs, create one from the current selection position.\r | |
65 | if ( paragraphs.length < 1 ) {\r | |
66 | var para = editor.document.createElement( editor.config.enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ),\r | |
67 | firstBookmark = bookmarks.shift();\r | |
68 | range.insertNode( para );\r | |
69 | para.append( new CKEDITOR.dom.text( '\ufeff', editor.document ) );\r | |
70 | range.moveToBookmark( firstBookmark );\r | |
71 | range.selectNodeContents( para );\r | |
72 | range.collapse( true );\r | |
73 | firstBookmark = range.createBookmark();\r | |
74 | paragraphs.push( para );\r | |
75 | bookmarks.unshift( firstBookmark );\r | |
76 | }\r | |
77 | \r | |
78 | // Make sure all paragraphs have the same parent.\r | |
79 | var commonParent = paragraphs[ 0 ].getParent(),\r | |
80 | tmp = [];\r | |
81 | for ( var i = 0; i < paragraphs.length; i++ ) {\r | |
82 | block = paragraphs[ i ];\r | |
83 | commonParent = commonParent.getCommonAncestor( block.getParent() );\r | |
84 | }\r | |
85 | \r | |
86 | // The common parent must not be the following tags: table, tbody, tr, ol, ul.\r | |
87 | var denyTags = { table: 1, tbody: 1, tr: 1, ol: 1, ul: 1 };\r | |
88 | while ( denyTags[ commonParent.getName() ] )\r | |
89 | commonParent = commonParent.getParent();\r | |
90 | \r | |
91 | // Reconstruct the block list to be processed such that all resulting blocks\r | |
92 | // satisfy parentNode.equals( commonParent ).\r | |
93 | var lastBlock = null;\r | |
94 | while ( paragraphs.length > 0 ) {\r | |
95 | block = paragraphs.shift();\r | |
96 | while ( !block.getParent().equals( commonParent ) )\r | |
97 | block = block.getParent();\r | |
98 | if ( !block.equals( lastBlock ) )\r | |
99 | tmp.push( block );\r | |
100 | lastBlock = block;\r | |
101 | }\r | |
102 | \r | |
103 | // If any of the selected blocks is a blockquote, remove it to prevent\r | |
104 | // nested blockquotes.\r | |
105 | while ( tmp.length > 0 ) {\r | |
106 | block = tmp.shift();\r | |
107 | if ( block.getName() == 'blockquote' ) {\r | |
108 | var docFrag = new CKEDITOR.dom.documentFragment( editor.document );\r | |
109 | while ( block.getFirst() ) {\r | |
110 | docFrag.append( block.getFirst().remove() );\r | |
111 | paragraphs.push( docFrag.getLast() );\r | |
112 | }\r | |
113 | \r | |
114 | docFrag.replace( block );\r | |
115 | } else {\r | |
116 | paragraphs.push( block );\r | |
117 | }\r | |
118 | }\r | |
119 | \r | |
120 | // Now we have all the blocks to be included in a new blockquote node.\r | |
121 | var bqBlock = editor.document.createElement( 'blockquote' );\r | |
122 | bqBlock.insertBefore( paragraphs[ 0 ] );\r | |
123 | while ( paragraphs.length > 0 ) {\r | |
124 | block = paragraphs.shift();\r | |
125 | bqBlock.append( block );\r | |
126 | }\r | |
127 | } else if ( state == CKEDITOR.TRISTATE_ON ) {\r | |
128 | var moveOutNodes = [],\r | |
129 | database = {};\r | |
130 | \r | |
131 | while ( ( block = iterator.getNextParagraph() ) ) {\r | |
132 | var bqParent = null,\r | |
133 | bqChild = null;\r | |
134 | while ( block.getParent() ) {\r | |
135 | if ( block.getParent().getName() == 'blockquote' ) {\r | |
136 | bqParent = block.getParent();\r | |
137 | bqChild = block;\r | |
138 | break;\r | |
139 | }\r | |
140 | block = block.getParent();\r | |
141 | }\r | |
142 | \r | |
143 | // Remember the blocks that were recorded down in the moveOutNodes array\r | |
144 | // to prevent duplicates.\r | |
145 | if ( bqParent && bqChild && !bqChild.getCustomData( 'blockquote_moveout' ) ) {\r | |
146 | moveOutNodes.push( bqChild );\r | |
147 | CKEDITOR.dom.element.setMarker( database, bqChild, 'blockquote_moveout', true );\r | |
148 | }\r | |
149 | }\r | |
150 | \r | |
151 | CKEDITOR.dom.element.clearAllMarkers( database );\r | |
152 | \r | |
153 | var movedNodes = [],\r | |
154 | processedBlockquoteBlocks = [];\r | |
155 | \r | |
156 | database = {};\r | |
157 | while ( moveOutNodes.length > 0 ) {\r | |
158 | var node = moveOutNodes.shift();\r | |
159 | bqBlock = node.getParent();\r | |
160 | \r | |
161 | // If the node is located at the beginning or the end, just take it out\r | |
162 | // without splitting. Otherwise, split the blockquote node and move the\r | |
163 | // paragraph in between the two blockquote nodes.\r | |
164 | if ( !node.getPrevious() )\r | |
165 | node.remove().insertBefore( bqBlock );\r | |
166 | else if ( !node.getNext() )\r | |
167 | node.remove().insertAfter( bqBlock );\r | |
168 | else {\r | |
169 | node.breakParent( node.getParent() );\r | |
170 | processedBlockquoteBlocks.push( node.getNext() );\r | |
171 | }\r | |
172 | \r | |
173 | // Remember the blockquote node so we can clear it later (if it becomes empty).\r | |
174 | if ( !bqBlock.getCustomData( 'blockquote_processed' ) ) {\r | |
175 | processedBlockquoteBlocks.push( bqBlock );\r | |
176 | CKEDITOR.dom.element.setMarker( database, bqBlock, 'blockquote_processed', true );\r | |
177 | }\r | |
178 | \r | |
179 | movedNodes.push( node );\r | |
180 | }\r | |
181 | \r | |
182 | CKEDITOR.dom.element.clearAllMarkers( database );\r | |
183 | \r | |
184 | // Clear blockquote nodes that have become empty.\r | |
185 | for ( i = processedBlockquoteBlocks.length - 1; i >= 0; i-- ) {\r | |
186 | bqBlock = processedBlockquoteBlocks[ i ];\r | |
187 | if ( noBlockLeft( bqBlock ) )\r | |
188 | bqBlock.remove();\r | |
189 | }\r | |
190 | \r | |
191 | if ( editor.config.enterMode == CKEDITOR.ENTER_BR ) {\r | |
192 | var firstTime = true;\r | |
193 | while ( movedNodes.length ) {\r | |
194 | node = movedNodes.shift();\r | |
195 | \r | |
196 | if ( node.getName() == 'div' ) {\r | |
197 | docFrag = new CKEDITOR.dom.documentFragment( editor.document );\r | |
198 | var needBeginBr = firstTime && node.getPrevious() && !( node.getPrevious().type == CKEDITOR.NODE_ELEMENT && node.getPrevious().isBlockBoundary() );\r | |
199 | if ( needBeginBr )\r | |
200 | docFrag.append( editor.document.createElement( 'br' ) );\r | |
201 | \r | |
202 | var needEndBr = node.getNext() && !( node.getNext().type == CKEDITOR.NODE_ELEMENT && node.getNext().isBlockBoundary() );\r | |
203 | while ( node.getFirst() )\r | |
204 | node.getFirst().remove().appendTo( docFrag );\r | |
205 | \r | |
206 | if ( needEndBr )\r | |
207 | docFrag.append( editor.document.createElement( 'br' ) );\r | |
208 | \r | |
209 | docFrag.replace( node );\r | |
210 | firstTime = false;\r | |
211 | }\r | |
212 | }\r | |
213 | }\r | |
214 | }\r | |
215 | \r | |
216 | selection.selectBookmarks( bookmarks );\r | |
217 | editor.focus();\r | |
218 | },\r | |
219 | \r | |
220 | refresh: function( editor, path ) {\r | |
221 | // Check if inside of blockquote.\r | |
222 | var firstBlock = path.block || path.blockLimit;\r | |
223 | this.setState( editor.elementPath( firstBlock ).contains( 'blockquote', 1 ) ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );\r | |
224 | },\r | |
225 | \r | |
226 | context: 'blockquote',\r | |
227 | \r | |
228 | allowedContent: 'blockquote',\r | |
229 | requiredContent: 'blockquote'\r | |
230 | };\r | |
231 | \r | |
232 | CKEDITOR.plugins.add( 'blockquote', {\r | |
233 | // jscs:disable maximumLineLength\r | |
3b35bd27 | 234 | 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%\r |
7adcb81e IB |
235 | // jscs:enable maximumLineLength\r |
236 | icons: 'blockquote', // %REMOVE_LINE_CORE%\r | |
237 | hidpi: true, // %REMOVE_LINE_CORE%\r | |
238 | init: function( editor ) {\r | |
239 | if ( editor.blockless )\r | |
240 | return;\r | |
241 | \r | |
242 | editor.addCommand( 'blockquote', commandObject );\r | |
243 | \r | |
244 | editor.ui.addButton && editor.ui.addButton( 'Blockquote', {\r | |
245 | label: editor.lang.blockquote.toolbar,\r | |
246 | command: 'blockquote',\r | |
247 | toolbar: 'blocks,10'\r | |
248 | } );\r | |
249 | }\r | |
250 | } );\r | |
251 | } )();\r |