diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2017-01-20 00:55:51 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2017-01-20 00:55:51 +0100 |
commit | c63493c899de714b05b0521bb38aab60d19030ef (patch) | |
tree | fcb2b261afa0f3c2bd6b48929b64724c71192bae /sources/plugins/enterkey | |
download | ludivine-ckeditor-component-c63493c899de714b05b0521bb38aab60d19030ef.tar.gz ludivine-ckeditor-component-c63493c899de714b05b0521bb38aab60d19030ef.tar.zst ludivine-ckeditor-component-c63493c899de714b05b0521bb38aab60d19030ef.zip |
Validation initiale4.6.2.1
Diffstat (limited to 'sources/plugins/enterkey')
-rw-r--r-- | sources/plugins/enterkey/plugin.js | 566 | ||||
-rw-r--r-- | sources/plugins/enterkey/samples/enterkey.html | 106 |
2 files changed, 672 insertions, 0 deletions
diff --git a/sources/plugins/enterkey/plugin.js b/sources/plugins/enterkey/plugin.js new file mode 100644 index 0000000..9410bbd --- /dev/null +++ b/sources/plugins/enterkey/plugin.js | |||
@@ -0,0 +1,566 @@ | |||
1 | /** | ||
2 | * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. | ||
3 | * For licensing, see LICENSE.md or http://ckeditor.com/license | ||
4 | */ | ||
5 | |||
6 | ( function() { | ||
7 | CKEDITOR.plugins.add( 'enterkey', { | ||
8 | init: function( editor ) { | ||
9 | editor.addCommand( 'enter', { | ||
10 | modes: { wysiwyg: 1 }, | ||
11 | editorFocus: false, | ||
12 | exec: function( editor ) { | ||
13 | enter( editor ); | ||
14 | } | ||
15 | } ); | ||
16 | |||
17 | editor.addCommand( 'shiftEnter', { | ||
18 | modes: { wysiwyg: 1 }, | ||
19 | editorFocus: false, | ||
20 | exec: function( editor ) { | ||
21 | shiftEnter( editor ); | ||
22 | } | ||
23 | } ); | ||
24 | |||
25 | editor.setKeystroke( [ | ||
26 | [ 13, 'enter' ], | ||
27 | [ CKEDITOR.SHIFT + 13, 'shiftEnter' ] | ||
28 | ] ); | ||
29 | } | ||
30 | } ); | ||
31 | |||
32 | var whitespaces = CKEDITOR.dom.walker.whitespaces(), | ||
33 | bookmark = CKEDITOR.dom.walker.bookmark(); | ||
34 | |||
35 | CKEDITOR.plugins.enterkey = { | ||
36 | enterBlock: function( editor, mode, range, forceMode ) { | ||
37 | // Get the range for the current selection. | ||
38 | range = range || getRange( editor ); | ||
39 | |||
40 | // We may not have valid ranges to work on, like when inside a | ||
41 | // contenteditable=false element. | ||
42 | if ( !range ) | ||
43 | return; | ||
44 | |||
45 | // When range is in nested editable, we have to replace range with this one, | ||
46 | // which have root property set to closest editable, to make auto paragraphing work. (#12162) | ||
47 | range = replaceRangeWithClosestEditableRoot( range ); | ||
48 | |||
49 | var doc = range.document; | ||
50 | |||
51 | var atBlockStart = range.checkStartOfBlock(), | ||
52 | atBlockEnd = range.checkEndOfBlock(), | ||
53 | path = editor.elementPath( range.startContainer ), | ||
54 | block = path.block, | ||
55 | |||
56 | // Determine the block element to be used. | ||
57 | blockTag = ( mode == CKEDITOR.ENTER_DIV ? 'div' : 'p' ), | ||
58 | |||
59 | newBlock; | ||
60 | |||
61 | // Exit the list when we're inside an empty list item block. (#5376) | ||
62 | if ( atBlockStart && atBlockEnd ) { | ||
63 | // Exit the list when we're inside an empty list item block. (#5376) | ||
64 | if ( block && ( block.is( 'li' ) || block.getParent().is( 'li' ) ) ) { | ||
65 | // Make sure to point to the li when dealing with empty list item. | ||
66 | if ( !block.is( 'li' ) ) | ||
67 | block = block.getParent(); | ||
68 | |||
69 | var blockParent = block.getParent(), | ||
70 | blockGrandParent = blockParent.getParent(), | ||
71 | |||
72 | firstChild = !block.hasPrevious(), | ||
73 | lastChild = !block.hasNext(), | ||
74 | |||
75 | selection = editor.getSelection(), | ||
76 | bookmarks = selection.createBookmarks(), | ||
77 | |||
78 | orgDir = block.getDirection( 1 ), | ||
79 | className = block.getAttribute( 'class' ), | ||
80 | style = block.getAttribute( 'style' ), | ||
81 | dirLoose = blockGrandParent.getDirection( 1 ) != orgDir, | ||
82 | |||
83 | enterMode = editor.enterMode, | ||
84 | needsBlock = enterMode != CKEDITOR.ENTER_BR || dirLoose || style || className, | ||
85 | |||
86 | child; | ||
87 | |||
88 | if ( blockGrandParent.is( 'li' ) ) { | ||
89 | |||
90 | // If block is the first or the last child of the parent | ||
91 | // list, degrade it and move to the outer list: | ||
92 | // before the parent list if block is first child and after | ||
93 | // the parent list if block is the last child, respectively. | ||
94 | // | ||
95 | // <ul> => <ul> | ||
96 | // <li> => <li> | ||
97 | // <ul> => <ul> | ||
98 | // <li>x</li> => <li>x</li> | ||
99 | // <li>^</li> => </ul> | ||
100 | // </ul> => </li> | ||
101 | // </li> => <li>^</li> | ||
102 | // </ul> => </ul> | ||
103 | // | ||
104 | // AND | ||
105 | // | ||
106 | // <ul> => <ul> | ||
107 | // <li> => <li>^</li> | ||
108 | // <ul> => <li> | ||
109 | // <li>^</li> => <ul> | ||
110 | // <li>x</li> => <li>x</li> | ||
111 | // </ul> => </ul> | ||
112 | // </li> => </li> | ||
113 | // </ul> => </ul> | ||
114 | |||
115 | if ( firstChild || lastChild ) { | ||
116 | |||
117 | // If it's only child, we don't want to keep perent ul anymore. | ||
118 | if ( firstChild && lastChild ) { | ||
119 | blockParent.remove(); | ||
120 | } | ||
121 | |||
122 | block[lastChild ? 'insertAfter' : 'insertBefore']( blockGrandParent ); | ||
123 | |||
124 | // If the empty block is neither first nor last child | ||
125 | // then split the list and the block as an element | ||
126 | // of outer list. | ||
127 | // | ||
128 | // => <ul> | ||
129 | // => <li> | ||
130 | // <ul> => <ul> | ||
131 | // <li> => <li>x</li> | ||
132 | // <ul> => </ul> | ||
133 | // <li>x</li> => </li> | ||
134 | // <li>^</li> => <li>^</li> | ||
135 | // <li>y</li> => <li> | ||
136 | // </ul> => <ul> | ||
137 | // </li> => <li>y</li> | ||
138 | // </ul> => </ul> | ||
139 | // => </li> | ||
140 | // => </ul> | ||
141 | |||
142 | } else { | ||
143 | block.breakParent( blockGrandParent ); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | else if ( !needsBlock ) { | ||
148 | block.appendBogus( true ); | ||
149 | |||
150 | // If block is the first or last child of the parent | ||
151 | // list, move all block's children out of the list: | ||
152 | // before the list if block is first child and after the list | ||
153 | // if block is the last child, respectively. | ||
154 | // | ||
155 | // <ul> => <ul> | ||
156 | // <li>x</li> => <li>x</li> | ||
157 | // <li>^</li> => </ul> | ||
158 | // </ul> => ^ | ||
159 | // | ||
160 | // AND | ||
161 | // | ||
162 | // <ul> => ^ | ||
163 | // <li>^</li> => <ul> | ||
164 | // <li>x</li> => <li>x</li> | ||
165 | // </ul> => </ul> | ||
166 | |||
167 | if ( firstChild || lastChild ) { | ||
168 | while ( ( child = block[ firstChild ? 'getFirst' : 'getLast' ]() ) ) | ||
169 | child[ firstChild ? 'insertBefore' : 'insertAfter' ]( blockParent ); | ||
170 | } | ||
171 | |||
172 | // If the empty block is neither first nor last child | ||
173 | // then split the list and put all the block contents | ||
174 | // between two lists. | ||
175 | // | ||
176 | // <ul> => <ul> | ||
177 | // <li>x</li> => <li>x</li> | ||
178 | // <li>^</li> => </ul> | ||
179 | // <li>y</li> => ^ | ||
180 | // </ul> => <ul> | ||
181 | // => <li>y</li> | ||
182 | // => </ul> | ||
183 | |||
184 | else { | ||
185 | block.breakParent( blockParent ); | ||
186 | |||
187 | while ( ( child = block.getLast() ) ) | ||
188 | child.insertAfter( blockParent ); | ||
189 | } | ||
190 | |||
191 | block.remove(); | ||
192 | } else { | ||
193 | // Original path block is the list item, create new block for the list item content. | ||
194 | if ( path.block.is( 'li' ) ) { | ||
195 | // Use <div> block for ENTER_BR and ENTER_DIV. | ||
196 | newBlock = doc.createElement( mode == CKEDITOR.ENTER_P ? 'p' : 'div' ); | ||
197 | |||
198 | if ( dirLoose ) | ||
199 | newBlock.setAttribute( 'dir', orgDir ); | ||
200 | |||
201 | style && newBlock.setAttribute( 'style', style ); | ||
202 | className && newBlock.setAttribute( 'class', className ); | ||
203 | |||
204 | // Move all the child nodes to the new block. | ||
205 | block.moveChildren( newBlock ); | ||
206 | } | ||
207 | // The original path block is not a list item, just copy the block to out side of the list. | ||
208 | else { | ||
209 | newBlock = path.block; | ||
210 | } | ||
211 | |||
212 | // If block is the first or last child of the parent | ||
213 | // list, move it out of the list: | ||
214 | // before the list if block is first child and after the list | ||
215 | // if block is the last child, respectively. | ||
216 | // | ||
217 | // <ul> => <ul> | ||
218 | // <li>x</li> => <li>x</li> | ||
219 | // <li>^</li> => </ul> | ||
220 | // </ul> => <p>^</p> | ||
221 | // | ||
222 | // AND | ||
223 | // | ||
224 | // <ul> => <p>^</p> | ||
225 | // <li>^</li> => <ul> | ||
226 | // <li>x</li> => <li>x</li> | ||
227 | // </ul> => </ul> | ||
228 | |||
229 | if ( firstChild || lastChild ) | ||
230 | newBlock[ firstChild ? 'insertBefore' : 'insertAfter' ]( blockParent ); | ||
231 | |||
232 | // If the empty block is neither first nor last child | ||
233 | // then split the list and put the new block between | ||
234 | // two lists. | ||
235 | // | ||
236 | // => <ul> | ||
237 | // <ul> => <li>x</li> | ||
238 | // <li>x</li> => </ul> | ||
239 | // <li>^</li> => <p>^</p> | ||
240 | // <li>y</li> => <ul> | ||
241 | // </ul> => <li>y</li> | ||
242 | // => </ul> | ||
243 | |||
244 | else { | ||
245 | block.breakParent( blockParent ); | ||
246 | newBlock.insertAfter( blockParent ); | ||
247 | } | ||
248 | |||
249 | block.remove(); | ||
250 | } | ||
251 | |||
252 | selection.selectBookmarks( bookmarks ); | ||
253 | |||
254 | return; | ||
255 | } | ||
256 | |||
257 | if ( block && block.getParent().is( 'blockquote' ) ) { | ||
258 | block.breakParent( block.getParent() ); | ||
259 | |||
260 | // If we were at the start of <blockquote>, there will be an empty element before it now. | ||
261 | if ( !block.getPrevious().getFirst( CKEDITOR.dom.walker.invisible( 1 ) ) ) | ||
262 | block.getPrevious().remove(); | ||
263 | |||
264 | // If we were at the end of <blockquote>, there will be an empty element after it now. | ||
265 | if ( !block.getNext().getFirst( CKEDITOR.dom.walker.invisible( 1 ) ) ) | ||
266 | block.getNext().remove(); | ||
267 | |||
268 | range.moveToElementEditStart( block ); | ||
269 | range.select(); | ||
270 | return; | ||
271 | } | ||
272 | } | ||
273 | // Don't split <pre> if we're in the middle of it, act as shift enter key. | ||
274 | else if ( block && block.is( 'pre' ) ) { | ||
275 | if ( !atBlockEnd ) { | ||
276 | enterBr( editor, mode, range, forceMode ); | ||
277 | return; | ||
278 | } | ||
279 | } | ||
280 | |||
281 | // Split the range. | ||
282 | var splitInfo = range.splitBlock( blockTag ); | ||
283 | |||
284 | if ( !splitInfo ) | ||
285 | return; | ||
286 | |||
287 | // Get the current blocks. | ||
288 | var previousBlock = splitInfo.previousBlock, | ||
289 | nextBlock = splitInfo.nextBlock; | ||
290 | |||
291 | var isStartOfBlock = splitInfo.wasStartOfBlock, | ||
292 | isEndOfBlock = splitInfo.wasEndOfBlock; | ||
293 | |||
294 | var node; | ||
295 | |||
296 | // If this is a block under a list item, split it as well. (#1647) | ||
297 | if ( nextBlock ) { | ||
298 | node = nextBlock.getParent(); | ||
299 | if ( node.is( 'li' ) ) { | ||
300 | nextBlock.breakParent( node ); | ||
301 | nextBlock.move( nextBlock.getNext(), 1 ); | ||
302 | } | ||
303 | } else if ( previousBlock && ( node = previousBlock.getParent() ) && node.is( 'li' ) ) { | ||
304 | previousBlock.breakParent( node ); | ||
305 | node = previousBlock.getNext(); | ||
306 | range.moveToElementEditStart( node ); | ||
307 | previousBlock.move( previousBlock.getPrevious() ); | ||
308 | } | ||
309 | |||
310 | // If we have both the previous and next blocks, it means that the | ||
311 | // boundaries were on separated blocks, or none of them where on the | ||
312 | // block limits (start/end). | ||
313 | if ( !isStartOfBlock && !isEndOfBlock ) { | ||
314 | // If the next block is an <li> with another list tree as the first | ||
315 | // child, we'll need to append a filler (<br>/NBSP) or the list item | ||
316 | // wouldn't be editable. (#1420) | ||
317 | if ( nextBlock.is( 'li' ) ) { | ||
318 | var walkerRange = range.clone(); | ||
319 | walkerRange.selectNodeContents( nextBlock ); | ||
320 | var walker = new CKEDITOR.dom.walker( walkerRange ); | ||
321 | walker.evaluator = function( node ) { | ||
322 | return !( bookmark( node ) || whitespaces( node ) || node.type == CKEDITOR.NODE_ELEMENT && node.getName() in CKEDITOR.dtd.$inline && !( node.getName() in CKEDITOR.dtd.$empty ) ); | ||
323 | }; | ||
324 | |||
325 | node = walker.next(); | ||
326 | if ( node && node.type == CKEDITOR.NODE_ELEMENT && node.is( 'ul', 'ol' ) ) | ||
327 | ( CKEDITOR.env.needsBrFiller ? doc.createElement( 'br' ) : doc.createText( '\xa0' ) ).insertBefore( node ); | ||
328 | } | ||
329 | |||
330 | // Move the selection to the end block. | ||
331 | if ( nextBlock ) | ||
332 | range.moveToElementEditStart( nextBlock ); | ||
333 | } else { | ||
334 | var newBlockDir; | ||
335 | |||
336 | if ( previousBlock ) { | ||
337 | // Do not enter this block if it's a header tag, or we are in | ||
338 | // a Shift+Enter (#77). Create a new block element instead | ||
339 | // (later in the code). | ||
340 | if ( previousBlock.is( 'li' ) || !( headerTagRegex.test( previousBlock.getName() ) || previousBlock.is( 'pre' ) ) ) { | ||
341 | // Otherwise, duplicate the previous block. | ||
342 | newBlock = previousBlock.clone(); | ||
343 | } | ||
344 | } else if ( nextBlock ) { | ||
345 | newBlock = nextBlock.clone(); | ||
346 | } | ||
347 | |||
348 | if ( !newBlock ) { | ||
349 | // We have already created a new list item. (#6849) | ||
350 | if ( node && node.is( 'li' ) ) | ||
351 | newBlock = node; | ||
352 | else { | ||
353 | newBlock = doc.createElement( blockTag ); | ||
354 | if ( previousBlock && ( newBlockDir = previousBlock.getDirection() ) ) | ||
355 | newBlock.setAttribute( 'dir', newBlockDir ); | ||
356 | } | ||
357 | } | ||
358 | // Force the enter block unless we're talking of a list item. | ||
359 | else if ( forceMode && !newBlock.is( 'li' ) ) { | ||
360 | newBlock.renameNode( blockTag ); | ||
361 | } | ||
362 | |||
363 | // Recreate the inline elements tree, which was available | ||
364 | // before hitting enter, so the same styles will be available in | ||
365 | // the new block. | ||
366 | var elementPath = splitInfo.elementPath; | ||
367 | if ( elementPath ) { | ||
368 | for ( var i = 0, len = elementPath.elements.length; i < len; i++ ) { | ||
369 | var element = elementPath.elements[ i ]; | ||
370 | |||
371 | if ( element.equals( elementPath.block ) || element.equals( elementPath.blockLimit ) ) | ||
372 | break; | ||
373 | |||
374 | if ( CKEDITOR.dtd.$removeEmpty[ element.getName() ] ) { | ||
375 | element = element.clone(); | ||
376 | newBlock.moveChildren( element ); | ||
377 | newBlock.append( element ); | ||
378 | } | ||
379 | } | ||
380 | } | ||
381 | |||
382 | newBlock.appendBogus(); | ||
383 | |||
384 | if ( !newBlock.getParent() ) | ||
385 | range.insertNode( newBlock ); | ||
386 | |||
387 | // list item start number should not be duplicated (#7330), but we need | ||
388 | // to remove the attribute after it's onto the DOM tree because of old IEs (#7581). | ||
389 | newBlock.is( 'li' ) && newBlock.removeAttribute( 'value' ); | ||
390 | |||
391 | // This is tricky, but to make the new block visible correctly | ||
392 | // we must select it. | ||
393 | // The previousBlock check has been included because it may be | ||
394 | // empty if we have fixed a block-less space (like ENTER into an | ||
395 | // empty table cell). | ||
396 | if ( CKEDITOR.env.ie && isStartOfBlock && ( !isEndOfBlock || !previousBlock.getChildCount() ) ) { | ||
397 | // Move the selection to the new block. | ||
398 | range.moveToElementEditStart( isEndOfBlock ? previousBlock : newBlock ); | ||
399 | range.select(); | ||
400 | } | ||
401 | |||
402 | // Move the selection to the new block. | ||
403 | range.moveToElementEditStart( isStartOfBlock && !isEndOfBlock ? nextBlock : newBlock ); | ||
404 | } | ||
405 | |||
406 | range.select(); | ||
407 | range.scrollIntoView(); | ||
408 | }, | ||
409 | |||
410 | enterBr: function( editor, mode, range, forceMode ) { | ||
411 | // Get the range for the current selection. | ||
412 | range = range || getRange( editor ); | ||
413 | |||
414 | // We may not have valid ranges to work on, like when inside a | ||
415 | // contenteditable=false element. | ||
416 | if ( !range ) | ||
417 | return; | ||
418 | |||
419 | var doc = range.document; | ||
420 | |||
421 | var isEndOfBlock = range.checkEndOfBlock(); | ||
422 | |||
423 | var elementPath = new CKEDITOR.dom.elementPath( editor.getSelection().getStartElement() ); | ||
424 | |||
425 | var startBlock = elementPath.block, | ||
426 | startBlockTag = startBlock && elementPath.block.getName(); | ||
427 | |||
428 | if ( !forceMode && startBlockTag == 'li' ) { | ||
429 | enterBlock( editor, mode, range, forceMode ); | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | // If we are at the end of a header block. | ||
434 | if ( !forceMode && isEndOfBlock && headerTagRegex.test( startBlockTag ) ) { | ||
435 | var newBlock, newBlockDir; | ||
436 | |||
437 | if ( ( newBlockDir = startBlock.getDirection() ) ) { | ||
438 | newBlock = doc.createElement( 'div' ); | ||
439 | newBlock.setAttribute( 'dir', newBlockDir ); | ||
440 | newBlock.insertAfter( startBlock ); | ||
441 | range.setStart( newBlock, 0 ); | ||
442 | } else { | ||
443 | // Insert a <br> after the current paragraph. | ||
444 | doc.createElement( 'br' ).insertAfter( startBlock ); | ||
445 | |||
446 | // A text node is required by Gecko only to make the cursor blink. | ||
447 | if ( CKEDITOR.env.gecko ) | ||
448 | doc.createText( '' ).insertAfter( startBlock ); | ||
449 | |||
450 | // IE has different behaviors regarding position. | ||
451 | range.setStartAt( startBlock.getNext(), CKEDITOR.env.ie ? CKEDITOR.POSITION_BEFORE_START : CKEDITOR.POSITION_AFTER_START ); | ||
452 | } | ||
453 | } else { | ||
454 | var lineBreak; | ||
455 | |||
456 | // IE<8 prefers text node as line-break inside of <pre> (#4711). | ||
457 | if ( startBlockTag == 'pre' && CKEDITOR.env.ie && CKEDITOR.env.version < 8 ) | ||
458 | lineBreak = doc.createText( '\r' ); | ||
459 | else | ||
460 | lineBreak = doc.createElement( 'br' ); | ||
461 | |||
462 | range.deleteContents(); | ||
463 | range.insertNode( lineBreak ); | ||
464 | |||
465 | // Old IEs have different behavior regarding position. | ||
466 | if ( !CKEDITOR.env.needsBrFiller ) | ||
467 | range.setStartAt( lineBreak, CKEDITOR.POSITION_AFTER_END ); | ||
468 | else { | ||
469 | // A text node is required by Gecko only to make the cursor blink. | ||
470 | // We need some text inside of it, so the bogus <br> is properly | ||
471 | // created. | ||
472 | doc.createText( '\ufeff' ).insertAfter( lineBreak ); | ||
473 | |||
474 | // If we are at the end of a block, we must be sure the bogus node is available in that block. | ||
475 | if ( isEndOfBlock ) { | ||
476 | // In most situations we've got an elementPath.block (e.g. <p>), but in a | ||
477 | // blockless editor or when autoP is false that needs to be a block limit. | ||
478 | ( startBlock || elementPath.blockLimit ).appendBogus(); | ||
479 | } | ||
480 | |||
481 | // Now we can remove the text node contents, so the caret doesn't | ||
482 | // stop on it. | ||
483 | lineBreak.getNext().$.nodeValue = ''; | ||
484 | |||
485 | range.setStartAt( lineBreak.getNext(), CKEDITOR.POSITION_AFTER_START ); | ||
486 | |||
487 | } | ||
488 | } | ||
489 | |||
490 | // This collapse guarantees the cursor will be blinking. | ||
491 | range.collapse( true ); | ||
492 | |||
493 | range.select(); | ||
494 | range.scrollIntoView(); | ||
495 | } | ||
496 | }; | ||
497 | |||
498 | var plugin = CKEDITOR.plugins.enterkey, | ||
499 | enterBr = plugin.enterBr, | ||
500 | enterBlock = plugin.enterBlock, | ||
501 | headerTagRegex = /^h[1-6]$/; | ||
502 | |||
503 | function shiftEnter( editor ) { | ||
504 | // On SHIFT+ENTER: | ||
505 | // 1. We want to enforce the mode to be respected, instead | ||
506 | // of cloning the current block. (#77) | ||
507 | return enter( editor, editor.activeShiftEnterMode, 1 ); | ||
508 | } | ||
509 | |||
510 | function enter( editor, mode, forceMode ) { | ||
511 | forceMode = editor.config.forceEnterMode || forceMode; | ||
512 | |||
513 | // Only effective within document. | ||
514 | if ( editor.mode != 'wysiwyg' ) | ||
515 | return; | ||
516 | |||
517 | if ( !mode ) | ||
518 | mode = editor.activeEnterMode; | ||
519 | |||
520 | // TODO this should be handled by setting editor.activeEnterMode on selection change. | ||
521 | // Check path block specialities: | ||
522 | // 1. Cannot be a un-splittable element, e.g. table caption; | ||
523 | var path = editor.elementPath(); | ||
524 | if ( !path.isContextFor( 'p' ) ) { | ||
525 | mode = CKEDITOR.ENTER_BR; | ||
526 | forceMode = 1; | ||
527 | } | ||
528 | |||
529 | editor.fire( 'saveSnapshot' ); // Save undo step. | ||
530 | |||
531 | if ( mode == CKEDITOR.ENTER_BR ) | ||
532 | enterBr( editor, mode, null, forceMode ); | ||
533 | else | ||
534 | enterBlock( editor, mode, null, forceMode ); | ||
535 | |||
536 | editor.fire( 'saveSnapshot' ); | ||
537 | } | ||
538 | |||
539 | function getRange( editor ) { | ||
540 | // Get the selection ranges. | ||
541 | var ranges = editor.getSelection().getRanges( true ); | ||
542 | |||
543 | // Delete the contents of all ranges except the first one. | ||
544 | for ( var i = ranges.length - 1; i > 0; i-- ) { | ||
545 | ranges[ i ].deleteContents(); | ||
546 | } | ||
547 | |||
548 | // Return the first range. | ||
549 | return ranges[ 0 ]; | ||
550 | } | ||
551 | |||
552 | function replaceRangeWithClosestEditableRoot( range ) { | ||
553 | var closestEditable = range.startContainer.getAscendant( function( node ) { | ||
554 | return node.type == CKEDITOR.NODE_ELEMENT && node.getAttribute( 'contenteditable' ) == 'true'; | ||
555 | }, true ); | ||
556 | |||
557 | if ( range.root.equals( closestEditable ) ) { | ||
558 | return range; | ||
559 | } else { | ||
560 | var newRange = new CKEDITOR.dom.range( closestEditable ); | ||
561 | |||
562 | newRange.moveToRange( range ); | ||
563 | return newRange; | ||
564 | } | ||
565 | } | ||
566 | } )(); | ||
diff --git a/sources/plugins/enterkey/samples/enterkey.html b/sources/plugins/enterkey/samples/enterkey.html new file mode 100644 index 0000000..79afee3 --- /dev/null +++ b/sources/plugins/enterkey/samples/enterkey.html | |||
@@ -0,0 +1,106 @@ | |||
1 | <!DOCTYPE html> | ||
2 | <!-- | ||
3 | Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. | ||
4 | For licensing, see LICENSE.md or http://ckeditor.com/license | ||
5 | --> | ||
6 | <html> | ||
7 | <head> | ||
8 | <meta charset="utf-8"> | ||
9 | <title>ENTER Key Configuration — CKEditor Sample</title> | ||
10 | <script src="../../../ckeditor.js"></script> | ||
11 | <link href="../../../samples/old/sample.css" rel="stylesheet"> | ||
12 | <meta name="ckeditor-sample-name" content="Using the "Enter" key in CKEditor"> | ||
13 | <meta name="ckeditor-sample-group" content="Advanced Samples"> | ||
14 | <meta name="ckeditor-sample-description" content="Configuring the behavior of <em>Enter</em> and <em>Shift+Enter</em> keys."> | ||
15 | <script> | ||
16 | |||
17 | var editor; | ||
18 | |||
19 | function changeEnter() { | ||
20 | // If we already have an editor, let's destroy it first. | ||
21 | if ( editor ) | ||
22 | editor.destroy( true ); | ||
23 | |||
24 | // Create the editor again, with the appropriate settings. | ||
25 | editor = CKEDITOR.replace( 'editor1', { | ||
26 | extraPlugins: 'enterkey', | ||
27 | enterMode: Number( document.getElementById( 'xEnter' ).value ), | ||
28 | shiftEnterMode: Number( document.getElementById( 'xShiftEnter' ).value ) | ||
29 | }); | ||
30 | } | ||
31 | |||
32 | window.onload = changeEnter; | ||
33 | |||
34 | </script> | ||
35 | </head> | ||
36 | <body> | ||
37 | <h1 class="samples"> | ||
38 | <a href="../../../samples/old/index.html">CKEditor Samples</a> » ENTER Key Configuration | ||
39 | </h1> | ||
40 | <div class="warning deprecated"> | ||
41 | This sample is not maintained anymore. Check out its <a href="http://sdk.ckeditor.com/samples/enterkey.html">brand new version in CKEditor SDK</a>. | ||
42 | </div> | ||
43 | <div class="description"> | ||
44 | <p> | ||
45 | This sample shows how to configure the <em>Enter</em> and <em>Shift+Enter</em> keys | ||
46 | to perform actions specified in the | ||
47 | <a class="samples" href="http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-enterMode"><code>enterMode</code></a> | ||
48 | and <a class="samples" href="http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-shiftEnterMode"><code>shiftEnterMode</code></a> | ||
49 | parameters, respectively. | ||
50 | You can choose from the following options: | ||
51 | </p> | ||
52 | <ul class="samples"> | ||
53 | <li><strong><code>ENTER_P</code></strong> – new <code><p></code> paragraphs are created;</li> | ||
54 | <li><strong><code>ENTER_BR</code></strong> – lines are broken with <code><br></code> elements;</li> | ||
55 | <li><strong><code>ENTER_DIV</code></strong> – new <code><div></code> blocks are created.</li> | ||
56 | </ul> | ||
57 | <p> | ||
58 | The sample code below shows how to configure CKEditor to create a <code><div></code> block when <em>Enter</em> key is pressed. | ||
59 | </p> | ||
60 | <pre class="samples"> | ||
61 | CKEDITOR.replace( '<em>textarea_id</em>', { | ||
62 | <strong>enterMode: CKEDITOR.ENTER_DIV</strong> | ||
63 | });</pre> | ||
64 | <p> | ||
65 | Note that <code><em>textarea_id</em></code> in the code above is the <code>id</code> attribute of | ||
66 | the <code><textarea></code> element to be replaced. | ||
67 | </p> | ||
68 | </div> | ||
69 | <div style="float: left; margin-right: 20px"> | ||
70 | When <em>Enter</em> is pressed:<br> | ||
71 | <select id="xEnter" onchange="changeEnter();"> | ||
72 | <option selected="selected" value="1">Create a new <P> (recommended)</option> | ||
73 | <option value="3">Create a new <DIV></option> | ||
74 | <option value="2">Break the line with a <BR></option> | ||
75 | </select> | ||
76 | </div> | ||
77 | <div style="float: left"> | ||
78 | When <em>Shift+Enter</em> is pressed:<br> | ||
79 | <select id="xShiftEnter" onchange="changeEnter();"> | ||
80 | <option value="1">Create a new <P></option> | ||
81 | <option value="3">Create a new <DIV></option> | ||
82 | <option selected="selected" value="2">Break the line with a <BR> (recommended)</option> | ||
83 | </select> | ||
84 | </div> | ||
85 | <br style="clear: both"> | ||
86 | <form action="../../../samples/sample_posteddata.php" method="post"> | ||
87 | <p> | ||
88 | <br> | ||
89 | <textarea cols="80" id="editor1" name="editor1" rows="10">This is some <strong>sample text</strong>. You are using <a href="http://ckeditor.com/">CKEditor</a>.</textarea> | ||
90 | </p> | ||
91 | <p> | ||
92 | <input type="submit" value="Submit"> | ||
93 | </p> | ||
94 | </form> | ||
95 | <div id="footer"> | ||
96 | <hr> | ||
97 | <p> | ||
98 | CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a> | ||
99 | </p> | ||
100 | <p id="copy"> | ||
101 | Copyright © 2003-2017, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico | ||
102 | Knabben. All rights reserved. | ||
103 | </p> | ||
104 | </div> | ||
105 | </body> | ||
106 | </html> | ||