aboutsummaryrefslogtreecommitdiff
path: root/sources/plugins/undo
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2016-01-25 17:45:33 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2016-01-25 18:00:33 +0100
commit7adcb81e4f83f98c468889aaa5a85558ba88c770 (patch)
tree0d6ede733777b29060b48df4afaa2c64bfbae276 /sources/plugins/undo
downloadconnexionswing-ckeditor-component-7adcb81e4f83f98c468889aaa5a85558ba88c770.tar.gz
connexionswing-ckeditor-component-7adcb81e4f83f98c468889aaa5a85558ba88c770.tar.zst
connexionswing-ckeditor-component-7adcb81e4f83f98c468889aaa5a85558ba88c770.zip
Initial commit4.5.6
Diffstat (limited to 'sources/plugins/undo')
-rw-r--r--sources/plugins/undo/dev/snapshot.html86
-rw-r--r--sources/plugins/undo/icons/hidpi/redo-rtl.pngbin0 -> 1869 bytes
-rw-r--r--sources/plugins/undo/icons/hidpi/redo.pngbin0 -> 1783 bytes
-rw-r--r--sources/plugins/undo/icons/hidpi/undo-rtl.pngbin0 -> 1783 bytes
-rw-r--r--sources/plugins/undo/icons/hidpi/undo.pngbin0 -> 1869 bytes
-rw-r--r--sources/plugins/undo/icons/redo-rtl.pngbin0 -> 849 bytes
-rw-r--r--sources/plugins/undo/icons/redo.pngbin0 -> 842 bytes
-rw-r--r--sources/plugins/undo/icons/undo-rtl.pngbin0 -> 842 bytes
-rw-r--r--sources/plugins/undo/icons/undo.pngbin0 -> 850 bytes
-rw-r--r--sources/plugins/undo/lang/af.js8
-rw-r--r--sources/plugins/undo/lang/ar.js8
-rw-r--r--sources/plugins/undo/lang/bg.js8
-rw-r--r--sources/plugins/undo/lang/bn.js8
-rw-r--r--sources/plugins/undo/lang/bs.js8
-rw-r--r--sources/plugins/undo/lang/ca.js8
-rw-r--r--sources/plugins/undo/lang/cs.js8
-rw-r--r--sources/plugins/undo/lang/cy.js8
-rw-r--r--sources/plugins/undo/lang/da.js8
-rw-r--r--sources/plugins/undo/lang/de.js8
-rw-r--r--sources/plugins/undo/lang/el.js8
-rw-r--r--sources/plugins/undo/lang/en-au.js8
-rw-r--r--sources/plugins/undo/lang/en-ca.js8
-rw-r--r--sources/plugins/undo/lang/en-gb.js8
-rw-r--r--sources/plugins/undo/lang/en.js8
-rw-r--r--sources/plugins/undo/lang/eo.js8
-rw-r--r--sources/plugins/undo/lang/es.js8
-rw-r--r--sources/plugins/undo/lang/et.js8
-rw-r--r--sources/plugins/undo/lang/eu.js8
-rw-r--r--sources/plugins/undo/lang/fa.js8
-rw-r--r--sources/plugins/undo/lang/fi.js8
-rw-r--r--sources/plugins/undo/lang/fo.js8
-rw-r--r--sources/plugins/undo/lang/fr-ca.js8
-rw-r--r--sources/plugins/undo/lang/fr.js8
-rw-r--r--sources/plugins/undo/lang/gl.js8
-rw-r--r--sources/plugins/undo/lang/gu.js8
-rw-r--r--sources/plugins/undo/lang/he.js8
-rw-r--r--sources/plugins/undo/lang/hi.js8
-rw-r--r--sources/plugins/undo/lang/hr.js8
-rw-r--r--sources/plugins/undo/lang/hu.js8
-rw-r--r--sources/plugins/undo/lang/id.js8
-rw-r--r--sources/plugins/undo/lang/is.js8
-rw-r--r--sources/plugins/undo/lang/it.js8
-rw-r--r--sources/plugins/undo/lang/ja.js8
-rw-r--r--sources/plugins/undo/lang/ka.js8
-rw-r--r--sources/plugins/undo/lang/km.js8
-rw-r--r--sources/plugins/undo/lang/ko.js8
-rw-r--r--sources/plugins/undo/lang/ku.js8
-rw-r--r--sources/plugins/undo/lang/lt.js8
-rw-r--r--sources/plugins/undo/lang/lv.js8
-rw-r--r--sources/plugins/undo/lang/mk.js8
-rw-r--r--sources/plugins/undo/lang/mn.js8
-rw-r--r--sources/plugins/undo/lang/ms.js8
-rw-r--r--sources/plugins/undo/lang/nb.js8
-rw-r--r--sources/plugins/undo/lang/nl.js8
-rw-r--r--sources/plugins/undo/lang/no.js8
-rw-r--r--sources/plugins/undo/lang/pl.js8
-rw-r--r--sources/plugins/undo/lang/pt-br.js8
-rw-r--r--sources/plugins/undo/lang/pt.js8
-rw-r--r--sources/plugins/undo/lang/ro.js8
-rw-r--r--sources/plugins/undo/lang/ru.js8
-rw-r--r--sources/plugins/undo/lang/si.js8
-rw-r--r--sources/plugins/undo/lang/sk.js8
-rw-r--r--sources/plugins/undo/lang/sl.js8
-rw-r--r--sources/plugins/undo/lang/sq.js8
-rw-r--r--sources/plugins/undo/lang/sr-latn.js8
-rw-r--r--sources/plugins/undo/lang/sr.js8
-rw-r--r--sources/plugins/undo/lang/sv.js8
-rw-r--r--sources/plugins/undo/lang/th.js8
-rw-r--r--sources/plugins/undo/lang/tr.js8
-rw-r--r--sources/plugins/undo/lang/tt.js8
-rw-r--r--sources/plugins/undo/lang/ug.js8
-rw-r--r--sources/plugins/undo/lang/uk.js8
-rw-r--r--sources/plugins/undo/lang/vi.js8
-rw-r--r--sources/plugins/undo/lang/zh-cn.js8
-rw-r--r--sources/plugins/undo/lang/zh.js8
-rw-r--r--sources/plugins/undo/plugin.js1328
76 files changed, 1942 insertions, 0 deletions
diff --git a/sources/plugins/undo/dev/snapshot.html b/sources/plugins/undo/dev/snapshot.html
new file mode 100644
index 00000000..c3a61c67
--- /dev/null
+++ b/sources/plugins/undo/dev/snapshot.html
@@ -0,0 +1,86 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Replace Textarea by Code &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <link href="../../../samples/old/sample.css" rel="stylesheet">
12</head>
13<body>
14 <h1 class="samples">
15 <a href="../../../samples/old/index.html">CKEditor Samples</a> &raquo; Replace Textarea Elements Using JavaScript Code
16 </h1>
17 <form action="sample_posteddata.php" method="post">
18 <div class="description">
19 <p>
20 This editor is using an <code>&lt;iframe&gt;</code> element-based editing area, provided by the <strong>Wysiwygarea</strong> plugin.
21 </p>
22<pre class="samples">
23CKEDITOR.replace( '<em>textarea_id</em>' )
24</pre>
25 </div>
26 <textarea cols="80" id="editor1" name="editor1" rows="10">
27 &lt;p&gt;Apollo 11&lt;/p&gt;
28 &lt;p&gt;111 222 333 444 555 666 777&lt;/p&gt;
29 </textarea>
30 <p>
31 <input type="submit" value="Submit">
32 </p>
33 </form>
34 <div id="footer">
35 <hr>
36 <p>
37 CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a>
38 </p>
39 <p id="copy">
40 Copyright &copy; 2003-2015, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico
41 Knabben. All rights reserved.
42 </p>
43 </div>
44 <div id="debugConsole">
45 <div>Snapshots: <strong id="debugSnapshotsCount">0</strong></div>
46 <div>Typing: <strong id="debugTypingVal">false</strong></div>
47 </div>
48 <div id="undoControls">
49 <a onclick="CKEDITOR.instances.editor1.execCommand('undo');" href="#">&lt; Undo</a>
50 <a onclick="CKEDITOR.instances.editor1.execCommand('redo');" href="#">Redo &gt;</a>
51 </div>
52 <script type="text/javascript">
53 var snapCount = document.getElementById( 'debugSnapshotsCount' ),
54 typingTracer = document.getElementById( 'debugTypingVal' ),
55 updateTypingTracer = function() {
56 typingTracer.innerHTML = String( CKEDITOR.instances.editor1.undoManager.typing );
57 },
58 updateSnapshotCounter = function() {
59 if ( !CKEDITOR && CKEDITOR.instances.editor1 )
60 return;
61
62 snapCount.innerHTML = CKEDITOR.instances.editor1.undoManager.snapshots.length;
63 updateTypingTracer();
64 };
65
66 CKEDITOR.replace( 'editor1', {
67 toolbar: [ [ 'Source', 'Bold', 'Italic' ] ,[ 'Undo' ], [ 'Redo' ] ],
68 on: {
69 instanceReady: function( evt ) {
70 CKEDITOR.instances.editor1.focus();
71 },
72 change: function( evt ) {
73 updateSnapshotCounter();
74 }
75 }
76 } );
77
78 window.setInterval( updateSnapshotCounter, 700 );
79 </script>
80 <style type="text/css">
81 #debugConsole { clear: both; }
82 #undoControls { clear: both; }
83 #undoControls a { padding: 25px 50px; font-size: 19px; margin-right: 15px; outline: 2px solid gray; display: block; float: left; text-decoration: none; }
84 </style>
85</body>
86</html>
diff --git a/sources/plugins/undo/icons/hidpi/redo-rtl.png b/sources/plugins/undo/icons/hidpi/redo-rtl.png
new file mode 100644
index 00000000..206d38ab
--- /dev/null
+++ b/sources/plugins/undo/icons/hidpi/redo-rtl.png
Binary files differ
diff --git a/sources/plugins/undo/icons/hidpi/redo.png b/sources/plugins/undo/icons/hidpi/redo.png
new file mode 100644
index 00000000..a7883643
--- /dev/null
+++ b/sources/plugins/undo/icons/hidpi/redo.png
Binary files differ
diff --git a/sources/plugins/undo/icons/hidpi/undo-rtl.png b/sources/plugins/undo/icons/hidpi/undo-rtl.png
new file mode 100644
index 00000000..a7883643
--- /dev/null
+++ b/sources/plugins/undo/icons/hidpi/undo-rtl.png
Binary files differ
diff --git a/sources/plugins/undo/icons/hidpi/undo.png b/sources/plugins/undo/icons/hidpi/undo.png
new file mode 100644
index 00000000..206d38ab
--- /dev/null
+++ b/sources/plugins/undo/icons/hidpi/undo.png
Binary files differ
diff --git a/sources/plugins/undo/icons/redo-rtl.png b/sources/plugins/undo/icons/redo-rtl.png
new file mode 100644
index 00000000..dd12c682
--- /dev/null
+++ b/sources/plugins/undo/icons/redo-rtl.png
Binary files differ
diff --git a/sources/plugins/undo/icons/redo.png b/sources/plugins/undo/icons/redo.png
new file mode 100644
index 00000000..75a18720
--- /dev/null
+++ b/sources/plugins/undo/icons/redo.png
Binary files differ
diff --git a/sources/plugins/undo/icons/undo-rtl.png b/sources/plugins/undo/icons/undo-rtl.png
new file mode 100644
index 00000000..75a18720
--- /dev/null
+++ b/sources/plugins/undo/icons/undo-rtl.png
Binary files differ
diff --git a/sources/plugins/undo/icons/undo.png b/sources/plugins/undo/icons/undo.png
new file mode 100644
index 00000000..f81b3b39
--- /dev/null
+++ b/sources/plugins/undo/icons/undo.png
Binary files differ
diff --git a/sources/plugins/undo/lang/af.js b/sources/plugins/undo/lang/af.js
new file mode 100644
index 00000000..186256bc
--- /dev/null
+++ b/sources/plugins/undo/lang/af.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'af', {
6 redo: 'Oordoen',
7 undo: 'Ontdoen'
8} );
diff --git a/sources/plugins/undo/lang/ar.js b/sources/plugins/undo/lang/ar.js
new file mode 100644
index 00000000..c5ead34c
--- /dev/null
+++ b/sources/plugins/undo/lang/ar.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'ar', {
6 redo: 'إعادة',
7 undo: 'تراجع'
8} );
diff --git a/sources/plugins/undo/lang/bg.js b/sources/plugins/undo/lang/bg.js
new file mode 100644
index 00000000..61e1d2ae
--- /dev/null
+++ b/sources/plugins/undo/lang/bg.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'bg', {
6 redo: 'Връщане на предишен статус',
7 undo: 'Възтанови'
8} );
diff --git a/sources/plugins/undo/lang/bn.js b/sources/plugins/undo/lang/bn.js
new file mode 100644
index 00000000..edf4d93e
--- /dev/null
+++ b/sources/plugins/undo/lang/bn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'bn', {
6 redo: 'রি-ডু',
7 undo: 'আনডু'
8} );
diff --git a/sources/plugins/undo/lang/bs.js b/sources/plugins/undo/lang/bs.js
new file mode 100644
index 00000000..88cd77db
--- /dev/null
+++ b/sources/plugins/undo/lang/bs.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'bs', {
6 redo: 'Ponovi',
7 undo: 'Vrati'
8} );
diff --git a/sources/plugins/undo/lang/ca.js b/sources/plugins/undo/lang/ca.js
new file mode 100644
index 00000000..0a44406a
--- /dev/null
+++ b/sources/plugins/undo/lang/ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'ca', {
6 redo: 'Refés',
7 undo: 'Desfés'
8} );
diff --git a/sources/plugins/undo/lang/cs.js b/sources/plugins/undo/lang/cs.js
new file mode 100644
index 00000000..51f8979a
--- /dev/null
+++ b/sources/plugins/undo/lang/cs.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'cs', {
6 redo: 'Znovu',
7 undo: 'Zpět'
8} );
diff --git a/sources/plugins/undo/lang/cy.js b/sources/plugins/undo/lang/cy.js
new file mode 100644
index 00000000..1e5a30d3
--- /dev/null
+++ b/sources/plugins/undo/lang/cy.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'cy', {
6 redo: 'Ailwneud',
7 undo: 'Dadwneud'
8} );
diff --git a/sources/plugins/undo/lang/da.js b/sources/plugins/undo/lang/da.js
new file mode 100644
index 00000000..8c1563ed
--- /dev/null
+++ b/sources/plugins/undo/lang/da.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'da', {
6 redo: 'Annullér fortryd',
7 undo: 'Fortryd'
8} );
diff --git a/sources/plugins/undo/lang/de.js b/sources/plugins/undo/lang/de.js
new file mode 100644
index 00000000..93d55862
--- /dev/null
+++ b/sources/plugins/undo/lang/de.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'de', {
6 redo: 'Wiederherstellen',
7 undo: 'Rückgängig'
8} );
diff --git a/sources/plugins/undo/lang/el.js b/sources/plugins/undo/lang/el.js
new file mode 100644
index 00000000..4961355f
--- /dev/null
+++ b/sources/plugins/undo/lang/el.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'el', {
6 redo: 'Επανάληψη',
7 undo: 'Αναίρεση'
8} );
diff --git a/sources/plugins/undo/lang/en-au.js b/sources/plugins/undo/lang/en-au.js
new file mode 100644
index 00000000..9d748e05
--- /dev/null
+++ b/sources/plugins/undo/lang/en-au.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'en-au', {
6 redo: 'Redo',
7 undo: 'Undo'
8} );
diff --git a/sources/plugins/undo/lang/en-ca.js b/sources/plugins/undo/lang/en-ca.js
new file mode 100644
index 00000000..facd173e
--- /dev/null
+++ b/sources/plugins/undo/lang/en-ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'en-ca', {
6 redo: 'Redo',
7 undo: 'Undo'
8} );
diff --git a/sources/plugins/undo/lang/en-gb.js b/sources/plugins/undo/lang/en-gb.js
new file mode 100644
index 00000000..5b52e0d4
--- /dev/null
+++ b/sources/plugins/undo/lang/en-gb.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'en-gb', {
6 redo: 'Redo',
7 undo: 'Undo'
8} );
diff --git a/sources/plugins/undo/lang/en.js b/sources/plugins/undo/lang/en.js
new file mode 100644
index 00000000..875bfe87
--- /dev/null
+++ b/sources/plugins/undo/lang/en.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'en', {
6 redo: 'Redo',
7 undo: 'Undo'
8} );
diff --git a/sources/plugins/undo/lang/eo.js b/sources/plugins/undo/lang/eo.js
new file mode 100644
index 00000000..9298e2b3
--- /dev/null
+++ b/sources/plugins/undo/lang/eo.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'eo', {
6 redo: 'Refari',
7 undo: 'Malfari'
8} );
diff --git a/sources/plugins/undo/lang/es.js b/sources/plugins/undo/lang/es.js
new file mode 100644
index 00000000..e518bce2
--- /dev/null
+++ b/sources/plugins/undo/lang/es.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'es', {
6 redo: 'Rehacer',
7 undo: 'Deshacer'
8} );
diff --git a/sources/plugins/undo/lang/et.js b/sources/plugins/undo/lang/et.js
new file mode 100644
index 00000000..3ad8f16d
--- /dev/null
+++ b/sources/plugins/undo/lang/et.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'et', {
6 redo: 'Toimingu kordamine',
7 undo: 'Tagasivõtmine'
8} );
diff --git a/sources/plugins/undo/lang/eu.js b/sources/plugins/undo/lang/eu.js
new file mode 100644
index 00000000..a9d000ce
--- /dev/null
+++ b/sources/plugins/undo/lang/eu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'eu', {
6 redo: 'Berregin',
7 undo: 'Desegin'
8} );
diff --git a/sources/plugins/undo/lang/fa.js b/sources/plugins/undo/lang/fa.js
new file mode 100644
index 00000000..a6fa2206
--- /dev/null
+++ b/sources/plugins/undo/lang/fa.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'fa', {
6 redo: 'بازچیدن',
7 undo: 'واچیدن'
8} );
diff --git a/sources/plugins/undo/lang/fi.js b/sources/plugins/undo/lang/fi.js
new file mode 100644
index 00000000..2df2f2e1
--- /dev/null
+++ b/sources/plugins/undo/lang/fi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'fi', {
6 redo: 'Toista',
7 undo: 'Kumoa'
8} );
diff --git a/sources/plugins/undo/lang/fo.js b/sources/plugins/undo/lang/fo.js
new file mode 100644
index 00000000..bd64e096
--- /dev/null
+++ b/sources/plugins/undo/lang/fo.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'fo', {
6 redo: 'Vend aftur',
7 undo: 'Angra'
8} );
diff --git a/sources/plugins/undo/lang/fr-ca.js b/sources/plugins/undo/lang/fr-ca.js
new file mode 100644
index 00000000..57c8e1f3
--- /dev/null
+++ b/sources/plugins/undo/lang/fr-ca.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'fr-ca', {
6 redo: 'Refaire',
7 undo: 'Annuler'
8} );
diff --git a/sources/plugins/undo/lang/fr.js b/sources/plugins/undo/lang/fr.js
new file mode 100644
index 00000000..6e799791
--- /dev/null
+++ b/sources/plugins/undo/lang/fr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'fr', {
6 redo: 'Rétablir',
7 undo: 'Annuler'
8} );
diff --git a/sources/plugins/undo/lang/gl.js b/sources/plugins/undo/lang/gl.js
new file mode 100644
index 00000000..2569d825
--- /dev/null
+++ b/sources/plugins/undo/lang/gl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'gl', {
6 redo: 'Refacer',
7 undo: 'Desfacer'
8} );
diff --git a/sources/plugins/undo/lang/gu.js b/sources/plugins/undo/lang/gu.js
new file mode 100644
index 00000000..5fd239ba
--- /dev/null
+++ b/sources/plugins/undo/lang/gu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'gu', {
6 redo: 'રિડૂ; પછી હતી એવી સ્થિતિ પાછી લાવવી',
7 undo: 'રદ કરવું; પહેલાં હતી એવી સ્થિતિ પાછી લાવવી'
8} );
diff --git a/sources/plugins/undo/lang/he.js b/sources/plugins/undo/lang/he.js
new file mode 100644
index 00000000..e03d5206
--- /dev/null
+++ b/sources/plugins/undo/lang/he.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'he', {
6 redo: 'חזרה על צעד אחרון',
7 undo: 'ביטול צעד אחרון'
8} );
diff --git a/sources/plugins/undo/lang/hi.js b/sources/plugins/undo/lang/hi.js
new file mode 100644
index 00000000..6306757a
--- /dev/null
+++ b/sources/plugins/undo/lang/hi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'hi', {
6 redo: 'रीडू',
7 undo: 'अन्डू'
8} );
diff --git a/sources/plugins/undo/lang/hr.js b/sources/plugins/undo/lang/hr.js
new file mode 100644
index 00000000..5fbf931f
--- /dev/null
+++ b/sources/plugins/undo/lang/hr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'hr', {
6 redo: 'Ponovi',
7 undo: 'Poništi'
8} );
diff --git a/sources/plugins/undo/lang/hu.js b/sources/plugins/undo/lang/hu.js
new file mode 100644
index 00000000..fc1e4a7a
--- /dev/null
+++ b/sources/plugins/undo/lang/hu.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'hu', {
6 redo: 'Ismétlés',
7 undo: 'Visszavonás'
8} );
diff --git a/sources/plugins/undo/lang/id.js b/sources/plugins/undo/lang/id.js
new file mode 100644
index 00000000..828ad66d
--- /dev/null
+++ b/sources/plugins/undo/lang/id.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'id', {
6 redo: 'Kembali lakukan',
7 undo: 'Batalkan perlakuan'
8} );
diff --git a/sources/plugins/undo/lang/is.js b/sources/plugins/undo/lang/is.js
new file mode 100644
index 00000000..850178bc
--- /dev/null
+++ b/sources/plugins/undo/lang/is.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'is', {
6 redo: 'Hætta við afturköllun',
7 undo: 'Afturkalla'
8} );
diff --git a/sources/plugins/undo/lang/it.js b/sources/plugins/undo/lang/it.js
new file mode 100644
index 00000000..0dd1a1d9
--- /dev/null
+++ b/sources/plugins/undo/lang/it.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'it', {
6 redo: 'Ripristina',
7 undo: 'Annulla'
8} );
diff --git a/sources/plugins/undo/lang/ja.js b/sources/plugins/undo/lang/ja.js
new file mode 100644
index 00000000..c2136f5c
--- /dev/null
+++ b/sources/plugins/undo/lang/ja.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'ja', {
6 redo: 'やり直す',
7 undo: '元に戻す'
8} );
diff --git a/sources/plugins/undo/lang/ka.js b/sources/plugins/undo/lang/ka.js
new file mode 100644
index 00000000..6a618af1
--- /dev/null
+++ b/sources/plugins/undo/lang/ka.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'ka', {
6 redo: 'გამეორება',
7 undo: 'გაუქმება'
8} );
diff --git a/sources/plugins/undo/lang/km.js b/sources/plugins/undo/lang/km.js
new file mode 100644
index 00000000..51e443c8
--- /dev/null
+++ b/sources/plugins/undo/lang/km.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'km', {
6 redo: 'ធ្វើ​ឡើង​វិញ',
7 undo: 'មិន​ធ្វើ​វិញ'
8} );
diff --git a/sources/plugins/undo/lang/ko.js b/sources/plugins/undo/lang/ko.js
new file mode 100644
index 00000000..a1c54b2a
--- /dev/null
+++ b/sources/plugins/undo/lang/ko.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'ko', {
6 redo: '다시 실행',
7 undo: '실행 취소'
8} );
diff --git a/sources/plugins/undo/lang/ku.js b/sources/plugins/undo/lang/ku.js
new file mode 100644
index 00000000..38ae12b1
--- /dev/null
+++ b/sources/plugins/undo/lang/ku.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'ku', {
6 redo: 'هەڵگەڕاندنەوە',
7 undo: 'پووچکردنەوە'
8} );
diff --git a/sources/plugins/undo/lang/lt.js b/sources/plugins/undo/lang/lt.js
new file mode 100644
index 00000000..4712429a
--- /dev/null
+++ b/sources/plugins/undo/lang/lt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'lt', {
6 redo: 'Atstatyti',
7 undo: 'Atšaukti'
8} );
diff --git a/sources/plugins/undo/lang/lv.js b/sources/plugins/undo/lang/lv.js
new file mode 100644
index 00000000..134f19c7
--- /dev/null
+++ b/sources/plugins/undo/lang/lv.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'lv', {
6 redo: 'Atkārtot',
7 undo: 'Atcelt'
8} );
diff --git a/sources/plugins/undo/lang/mk.js b/sources/plugins/undo/lang/mk.js
new file mode 100644
index 00000000..56b5a85f
--- /dev/null
+++ b/sources/plugins/undo/lang/mk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'mk', {
6 redo: 'Redo', // MISSING
7 undo: 'Undo'
8} );
diff --git a/sources/plugins/undo/lang/mn.js b/sources/plugins/undo/lang/mn.js
new file mode 100644
index 00000000..d1a919dd
--- /dev/null
+++ b/sources/plugins/undo/lang/mn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'mn', {
6 redo: 'Өмнөх үйлдлээ сэргээх',
7 undo: 'Хүчингүй болгох'
8} );
diff --git a/sources/plugins/undo/lang/ms.js b/sources/plugins/undo/lang/ms.js
new file mode 100644
index 00000000..e9fc94d3
--- /dev/null
+++ b/sources/plugins/undo/lang/ms.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'ms', {
6 redo: 'Ulangkan',
7 undo: 'Batalkan'
8} );
diff --git a/sources/plugins/undo/lang/nb.js b/sources/plugins/undo/lang/nb.js
new file mode 100644
index 00000000..ca295927
--- /dev/null
+++ b/sources/plugins/undo/lang/nb.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'nb', {
6 redo: 'Gjør om',
7 undo: 'Angre'
8} );
diff --git a/sources/plugins/undo/lang/nl.js b/sources/plugins/undo/lang/nl.js
new file mode 100644
index 00000000..c5b48096
--- /dev/null
+++ b/sources/plugins/undo/lang/nl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'nl', {
6 redo: 'Opnieuw uitvoeren',
7 undo: 'Ongedaan maken'
8} );
diff --git a/sources/plugins/undo/lang/no.js b/sources/plugins/undo/lang/no.js
new file mode 100644
index 00000000..e56f3271
--- /dev/null
+++ b/sources/plugins/undo/lang/no.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'no', {
6 redo: 'Gjør om',
7 undo: 'Angre'
8} );
diff --git a/sources/plugins/undo/lang/pl.js b/sources/plugins/undo/lang/pl.js
new file mode 100644
index 00000000..76ccd5f7
--- /dev/null
+++ b/sources/plugins/undo/lang/pl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'pl', {
6 redo: 'Ponów',
7 undo: 'Cofnij'
8} );
diff --git a/sources/plugins/undo/lang/pt-br.js b/sources/plugins/undo/lang/pt-br.js
new file mode 100644
index 00000000..72a5df9a
--- /dev/null
+++ b/sources/plugins/undo/lang/pt-br.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'pt-br', {
6 redo: 'Refazer',
7 undo: 'Desfazer'
8} );
diff --git a/sources/plugins/undo/lang/pt.js b/sources/plugins/undo/lang/pt.js
new file mode 100644
index 00000000..29ee5267
--- /dev/null
+++ b/sources/plugins/undo/lang/pt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'pt', {
6 redo: 'Refazer',
7 undo: 'Anular'
8} );
diff --git a/sources/plugins/undo/lang/ro.js b/sources/plugins/undo/lang/ro.js
new file mode 100644
index 00000000..bfc197c3
--- /dev/null
+++ b/sources/plugins/undo/lang/ro.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'ro', {
6 redo: 'Starea ulterioară (redo)',
7 undo: 'Starea anterioară (undo)'
8} );
diff --git a/sources/plugins/undo/lang/ru.js b/sources/plugins/undo/lang/ru.js
new file mode 100644
index 00000000..acf8ce4d
--- /dev/null
+++ b/sources/plugins/undo/lang/ru.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'ru', {
6 redo: 'Повторить',
7 undo: 'Отменить'
8} );
diff --git a/sources/plugins/undo/lang/si.js b/sources/plugins/undo/lang/si.js
new file mode 100644
index 00000000..96c9bc90
--- /dev/null
+++ b/sources/plugins/undo/lang/si.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'si', {
6 redo: 'නැවත කිරීම',
7 undo: 'වෙනස් කිරීම'
8} );
diff --git a/sources/plugins/undo/lang/sk.js b/sources/plugins/undo/lang/sk.js
new file mode 100644
index 00000000..28cf9375
--- /dev/null
+++ b/sources/plugins/undo/lang/sk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'sk', {
6 redo: 'Znovu',
7 undo: 'Späť'
8} );
diff --git a/sources/plugins/undo/lang/sl.js b/sources/plugins/undo/lang/sl.js
new file mode 100644
index 00000000..f649d441
--- /dev/null
+++ b/sources/plugins/undo/lang/sl.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'sl', {
6 redo: 'Ponovi',
7 undo: 'Razveljavi'
8} );
diff --git a/sources/plugins/undo/lang/sq.js b/sources/plugins/undo/lang/sq.js
new file mode 100644
index 00000000..37e17f95
--- /dev/null
+++ b/sources/plugins/undo/lang/sq.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'sq', {
6 redo: 'Ribëje',
7 undo: 'Rizhbëje'
8} );
diff --git a/sources/plugins/undo/lang/sr-latn.js b/sources/plugins/undo/lang/sr-latn.js
new file mode 100644
index 00000000..b2527a7f
--- /dev/null
+++ b/sources/plugins/undo/lang/sr-latn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'sr-latn', {
6 redo: 'Ponovi akciju',
7 undo: 'Poni�ti akciju'
8} );
diff --git a/sources/plugins/undo/lang/sr.js b/sources/plugins/undo/lang/sr.js
new file mode 100644
index 00000000..0b7f9f23
--- /dev/null
+++ b/sources/plugins/undo/lang/sr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'sr', {
6 redo: 'Понови акцију',
7 undo: 'Поништи акцију'
8} );
diff --git a/sources/plugins/undo/lang/sv.js b/sources/plugins/undo/lang/sv.js
new file mode 100644
index 00000000..5537b5ad
--- /dev/null
+++ b/sources/plugins/undo/lang/sv.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'sv', {
6 redo: 'Gör om',
7 undo: 'Ångra'
8} );
diff --git a/sources/plugins/undo/lang/th.js b/sources/plugins/undo/lang/th.js
new file mode 100644
index 00000000..29671829
--- /dev/null
+++ b/sources/plugins/undo/lang/th.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'th', {
6 redo: 'ทำซ้ำคำสั่ง',
7 undo: 'ยกเลิกคำสั่ง'
8} );
diff --git a/sources/plugins/undo/lang/tr.js b/sources/plugins/undo/lang/tr.js
new file mode 100644
index 00000000..3c757f77
--- /dev/null
+++ b/sources/plugins/undo/lang/tr.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'tr', {
6 redo: 'Tekrarla',
7 undo: 'Geri Al'
8} );
diff --git a/sources/plugins/undo/lang/tt.js b/sources/plugins/undo/lang/tt.js
new file mode 100644
index 00000000..d4335572
--- /dev/null
+++ b/sources/plugins/undo/lang/tt.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'tt', {
6 redo: 'Кабатлау',
7 undo: 'Кайтару'
8} );
diff --git a/sources/plugins/undo/lang/ug.js b/sources/plugins/undo/lang/ug.js
new file mode 100644
index 00000000..73348fc3
--- /dev/null
+++ b/sources/plugins/undo/lang/ug.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'ug', {
6 redo: 'قايتىلا ',
7 undo: 'يېنىۋال'
8} );
diff --git a/sources/plugins/undo/lang/uk.js b/sources/plugins/undo/lang/uk.js
new file mode 100644
index 00000000..23e308a2
--- /dev/null
+++ b/sources/plugins/undo/lang/uk.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'uk', {
6 redo: 'Повторити',
7 undo: 'Повернути'
8} );
diff --git a/sources/plugins/undo/lang/vi.js b/sources/plugins/undo/lang/vi.js
new file mode 100644
index 00000000..8b11bfd2
--- /dev/null
+++ b/sources/plugins/undo/lang/vi.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'vi', {
6 redo: 'Làm lại thao tác',
7 undo: 'Khôi phục thao tác'
8} );
diff --git a/sources/plugins/undo/lang/zh-cn.js b/sources/plugins/undo/lang/zh-cn.js
new file mode 100644
index 00000000..48116a7e
--- /dev/null
+++ b/sources/plugins/undo/lang/zh-cn.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'zh-cn', {
6 redo: '重做',
7 undo: '撤消'
8} );
diff --git a/sources/plugins/undo/lang/zh.js b/sources/plugins/undo/lang/zh.js
new file mode 100644
index 00000000..b6a1c4dc
--- /dev/null
+++ b/sources/plugins/undo/lang/zh.js
@@ -0,0 +1,8 @@
1/*
2Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.md or http://ckeditor.com/license
4*/
5CKEDITOR.plugins.setLang( 'undo', 'zh', {
6 redo: '取消復原',
7 undo: '復原'
8} );
diff --git a/sources/plugins/undo/plugin.js b/sources/plugins/undo/plugin.js
new file mode 100644
index 00000000..d5479936
--- /dev/null
+++ b/sources/plugins/undo/plugin.js
@@ -0,0 +1,1328 @@
1/**
2 * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview Undo/Redo system for saving a shapshot for document modification
8 * and other recordable changes.
9 */
10
11'use strict';
12
13( function() {
14 var keystrokes = [
15 CKEDITOR.CTRL + 90 /*Z*/,
16 CKEDITOR.CTRL + 89 /*Y*/,
17 CKEDITOR.CTRL + CKEDITOR.SHIFT + 90 /*Z*/
18 ],
19 backspaceOrDelete = { 8: 1, 46: 1 };
20
21 CKEDITOR.plugins.add( 'undo', {
22 // jscs:disable maximumLineLength
23 lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,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%
24 // jscs:enable maximumLineLength
25 icons: 'redo,redo-rtl,undo,undo-rtl', // %REMOVE_LINE_CORE%
26 hidpi: true, // %REMOVE_LINE_CORE%
27 init: function( editor ) {
28 var undoManager = editor.undoManager = new UndoManager( editor ),
29 editingHandler = undoManager.editingHandler = new NativeEditingHandler( undoManager );
30
31 var undoCommand = editor.addCommand( 'undo', {
32 exec: function() {
33 if ( undoManager.undo() ) {
34 editor.selectionChange();
35 this.fire( 'afterUndo' );
36 }
37 },
38 startDisabled: true,
39 canUndo: false
40 } );
41
42 var redoCommand = editor.addCommand( 'redo', {
43 exec: function() {
44 if ( undoManager.redo() ) {
45 editor.selectionChange();
46 this.fire( 'afterRedo' );
47 }
48 },
49 startDisabled: true,
50 canUndo: false
51 } );
52
53 editor.setKeystroke( [
54 [ keystrokes[ 0 ], 'undo' ],
55 [ keystrokes[ 1 ], 'redo' ],
56 [ keystrokes[ 2 ], 'redo' ]
57 ] );
58
59 undoManager.onChange = function() {
60 undoCommand.setState( undoManager.undoable() ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED );
61 redoCommand.setState( undoManager.redoable() ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED );
62 };
63
64 function recordCommand( event ) {
65 // If the command hasn't been marked to not support undo.
66 if ( undoManager.enabled && event.data.command.canUndo !== false )
67 undoManager.save();
68 }
69
70 // We'll save snapshots before and after executing a command.
71 editor.on( 'beforeCommandExec', recordCommand );
72 editor.on( 'afterCommandExec', recordCommand );
73
74 // Save snapshots before doing custom changes.
75 editor.on( 'saveSnapshot', function( evt ) {
76 undoManager.save( evt.data && evt.data.contentOnly );
77 } );
78
79 // Event manager listeners should be attached on contentDom.
80 editor.on( 'contentDom', editingHandler.attachListeners, editingHandler );
81
82 editor.on( 'instanceReady', function() {
83 // Saves initial snapshot.
84 editor.fire( 'saveSnapshot' );
85 } );
86
87 // Always save an undo snapshot - the previous mode might have
88 // changed editor contents.
89 editor.on( 'beforeModeUnload', function() {
90 editor.mode == 'wysiwyg' && undoManager.save( true );
91 } );
92
93 function toggleUndoManager() {
94 undoManager.enabled = editor.readOnly ? false : editor.mode == 'wysiwyg';
95 undoManager.onChange();
96 }
97
98 // Make the undo manager available only in wysiwyg mode.
99 editor.on( 'mode', toggleUndoManager );
100
101 // Disable undo manager when in read-only mode.
102 editor.on( 'readOnly', toggleUndoManager );
103
104 if ( editor.ui.addButton ) {
105 editor.ui.addButton( 'Undo', {
106 label: editor.lang.undo.undo,
107 command: 'undo',
108 toolbar: 'undo,10'
109 } );
110
111 editor.ui.addButton( 'Redo', {
112 label: editor.lang.undo.redo,
113 command: 'redo',
114 toolbar: 'undo,20'
115 } );
116 }
117
118 /**
119 * Resets the undo stack.
120 *
121 * @member CKEDITOR.editor
122 */
123 editor.resetUndo = function() {
124 // Reset the undo stack.
125 undoManager.reset();
126
127 // Create the first image.
128 editor.fire( 'saveSnapshot' );
129 };
130
131 /**
132 * Amends the top of the undo stack (last undo image) with the current DOM changes.
133 *
134 * function() {
135 * editor.fire( 'saveSnapshot' );
136 * editor.document.body.append(...);
137 * // Makes new changes following the last undo snapshot a part of it.
138 * editor.fire( 'updateSnapshot' );
139 * ..
140 * }
141 *
142 * @event updateSnapshot
143 * @member CKEDITOR.editor
144 * @param {CKEDITOR.editor} editor This editor instance.
145 */
146 editor.on( 'updateSnapshot', function() {
147 if ( undoManager.currentImage )
148 undoManager.update();
149 } );
150
151 /**
152 * Locks the undo manager to prevent any save/update operations.
153 *
154 * It is convenient to lock the undo manager before performing DOM operations
155 * that should not be recored (e.g. auto paragraphing).
156 *
157 * See {@link CKEDITOR.plugins.undo.UndoManager#lock} for more details.
158 *
159 * **Note:** In order to unlock the undo manager, {@link #unlockSnapshot} has to be fired
160 * the same number of times that `lockSnapshot` has been fired.
161 *
162 * @since 4.0
163 * @event lockSnapshot
164 * @member CKEDITOR.editor
165 * @param {CKEDITOR.editor} editor This editor instance.
166 * @param data
167 * @param {Boolean} [data.dontUpdate] When set to `true`, the last snapshot will not be updated
168 * with the current content and selection. Read more in the {@link CKEDITOR.plugins.undo.UndoManager#lock} method.
169 * @param {Boolean} [data.forceUpdate] When set to `true`, the last snapshot will always be updated
170 * with the current content and selection. Read more in the {@link CKEDITOR.plugins.undo.UndoManager#lock} method.
171 */
172 editor.on( 'lockSnapshot', function( evt ) {
173 var data = evt.data;
174 undoManager.lock( data && data.dontUpdate, data && data.forceUpdate );
175 } );
176
177 /**
178 * Unlocks the undo manager and updates the latest snapshot.
179 *
180 * @since 4.0
181 * @event unlockSnapshot
182 * @member CKEDITOR.editor
183 * @param {CKEDITOR.editor} editor This editor instance.
184 */
185 editor.on( 'unlockSnapshot', undoManager.unlock, undoManager );
186 }
187 } );
188
189 CKEDITOR.plugins.undo = {};
190
191 /**
192 * Main logic for the Redo/Undo feature.
193 *
194 * @private
195 * @class CKEDITOR.plugins.undo.UndoManager
196 * @constructor Creates an UndoManager class instance.
197 * @param {CKEDITOR.editor} editor
198 */
199 var UndoManager = CKEDITOR.plugins.undo.UndoManager = function( editor ) {
200 /**
201 * An array storing the number of key presses, count in a row. Use {@link #keyGroups} members as index.
202 *
203 * **Note:** The keystroke count will be reset after reaching the limit of characters per snapshot.
204 *
205 * @since 4.4.4
206 */
207 this.strokesRecorded = [ 0, 0 ];
208
209 /**
210 * When the `locked` property is not `null`, the undo manager is locked, so
211 * operations like `save` or `update` are forbidden.
212 *
213 * The manager can be locked and unlocked by the {@link #lock} and {@link #unlock}
214 * methods, respectively.
215 *
216 * @readonly
217 * @property {Object} [locked=null]
218 */
219 this.locked = null;
220
221 /**
222 * Contains the previously processed key group, based on {@link #keyGroups}.
223 * `-1` means an unknown group.
224 *
225 * @since 4.4.4
226 * @readonly
227 * @property {Number} [previousKeyGroup=-1]
228 */
229 this.previousKeyGroup = -1;
230
231 /**
232 * The maximum number of snapshots in the stack. Configurable via {@link CKEDITOR.config#undoStackSize}.
233 *
234 * @readonly
235 * @property {Number} [limit]
236 */
237 this.limit = editor.config.undoStackSize || 20;
238
239 /**
240 * The maximum number of characters typed/deleted in one undo step.
241 *
242 * @since 4.4.5
243 * @readonly
244 */
245 this.strokesLimit = 25;
246
247 this.editor = editor;
248
249 // Reset the undo stack.
250 this.reset();
251 };
252
253 UndoManager.prototype = {
254 /**
255 * Handles keystroke support for the undo manager. It is called on `keyup` event for
256 * keystrokes that can change the editor content.
257 *
258 * @param {Number} keyCode The key code.
259 * @param {Boolean} [strokesPerSnapshotExceeded] When set to `true`, the method will
260 * behave as if the strokes limit was exceeded regardless of the {@link #strokesRecorded} value.
261 */
262 type: function( keyCode, strokesPerSnapshotExceeded ) {
263 var keyGroup = UndoManager.getKeyGroup( keyCode ),
264 // Count of keystrokes in current a row.
265 // Note if strokesPerSnapshotExceeded will be exceeded, it'll be restarted.
266 strokesRecorded = this.strokesRecorded[ keyGroup ] + 1;
267
268 strokesPerSnapshotExceeded =
269 ( strokesPerSnapshotExceeded || strokesRecorded >= this.strokesLimit );
270
271 if ( !this.typing )
272 onTypingStart( this );
273
274 if ( strokesPerSnapshotExceeded ) {
275 // Reset the count of strokes, so it'll be later assigned to this.strokesRecorded.
276 strokesRecorded = 0;
277
278 this.editor.fire( 'saveSnapshot' );
279 } else {
280 // Fire change event.
281 this.editor.fire( 'change' );
282 }
283
284 // Store recorded strokes count.
285 this.strokesRecorded[ keyGroup ] = strokesRecorded;
286 // This prop will tell in next itaration what kind of group was processed previously.
287 this.previousKeyGroup = keyGroup;
288 },
289
290 /**
291 * Whether the new `keyCode` belongs to a different group than the previous one ({@link #previousKeyGroup}).
292 *
293 * @since 4.4.5
294 * @param {Number} keyCode
295 * @returns {Boolean}
296 */
297 keyGroupChanged: function( keyCode ) {
298 return UndoManager.getKeyGroup( keyCode ) != this.previousKeyGroup;
299 },
300
301 /**
302 * Resets the undo stack.
303 */
304 reset: function() {
305 // Stack for all the undo and redo snapshots, they're always created/removed
306 // in consistency.
307 this.snapshots = [];
308
309 // Current snapshot history index.
310 this.index = -1;
311
312 this.currentImage = null;
313
314 this.hasUndo = false;
315 this.hasRedo = false;
316 this.locked = null;
317
318 this.resetType();
319 },
320
321 /**
322 * Resets all typing variables.
323 *
324 * @see #type
325 */
326 resetType: function() {
327 this.strokesRecorded = [ 0, 0 ];
328 this.typing = false;
329 this.previousKeyGroup = -1;
330 },
331
332 /**
333 * Refreshes the state of the {@link CKEDITOR.plugins.undo.UndoManager undo manager}
334 * as well as the state of the `undo` and `redo` commands.
335 */
336 refreshState: function() {
337 // These lines can be handled within onChange() too.
338 this.hasUndo = !!this.getNextImage( true );
339 this.hasRedo = !!this.getNextImage( false );
340 // Reset typing
341 this.resetType();
342 this.onChange();
343 },
344
345 /**
346 * Saves a snapshot of the document image for later retrieval.
347 *
348 * @param {Boolean} onContentOnly If set to `true`, the snapshot will be saved only if the content has changed.
349 * @param {CKEDITOR.plugins.undo.Image} image An optional image to save. If skipped, current editor will be used.
350 * @param {Boolean} [autoFireChange=true] If set to `false`, will not trigger the {@link CKEDITOR.editor#change} event to editor.
351 */
352 save: function( onContentOnly, image, autoFireChange ) {
353 var editor = this.editor;
354 // Do not change snapshots stack when locked, editor is not ready,
355 // editable is not ready or when editor is in mode difference than 'wysiwyg'.
356 if ( this.locked || editor.status != 'ready' || editor.mode != 'wysiwyg' )
357 return false;
358
359 var editable = editor.editable();
360 if ( !editable || editable.status != 'ready' )
361 return false;
362
363 var snapshots = this.snapshots;
364
365 // Get a content image.
366 if ( !image )
367 image = new Image( editor );
368
369 // Do nothing if it was not possible to retrieve an image.
370 if ( image.contents === false )
371 return false;
372
373 // Check if this is a duplicate. In such case, do nothing.
374 if ( this.currentImage ) {
375 if ( image.equalsContent( this.currentImage ) ) {
376 if ( onContentOnly )
377 return false;
378
379 if ( image.equalsSelection( this.currentImage ) )
380 return false;
381 } else if ( autoFireChange !== false ) {
382 editor.fire( 'change' );
383 }
384 }
385
386 // Drop future snapshots.
387 snapshots.splice( this.index + 1, snapshots.length - this.index - 1 );
388
389 // If we have reached the limit, remove the oldest one.
390 if ( snapshots.length == this.limit )
391 snapshots.shift();
392
393 // Add the new image, updating the current index.
394 this.index = snapshots.push( image ) - 1;
395
396 this.currentImage = image;
397
398 if ( autoFireChange !== false )
399 this.refreshState();
400 return true;
401 },
402
403 /**
404 * Sets editor content/selection to the one stored in `image`.
405 *
406 * @param {CKEDITOR.plugins.undo.Image} image
407 */
408 restoreImage: function( image ) {
409 // Bring editor focused to restore selection.
410 var editor = this.editor,
411 sel;
412
413 if ( image.bookmarks ) {
414 editor.focus();
415 // Retrieve the selection beforehand. (#8324)
416 sel = editor.getSelection();
417 }
418
419 // Start transaction - do not allow any mutations to the
420 // snapshots stack done when selecting bookmarks (much probably
421 // by selectionChange listener).
422 this.locked = { level: 999 };
423
424 this.editor.loadSnapshot( image.contents );
425
426 if ( image.bookmarks )
427 sel.selectBookmarks( image.bookmarks );
428 else if ( CKEDITOR.env.ie ) {
429 // IE BUG: If I don't set the selection to *somewhere* after setting
430 // document contents, then IE would create an empty paragraph at the bottom
431 // the next time the document is modified.
432 var $range = this.editor.document.getBody().$.createTextRange();
433 $range.collapse( true );
434 $range.select();
435 }
436
437 this.locked = null;
438
439 this.index = image.index;
440 this.currentImage = this.snapshots[ this.index ];
441
442 // Update current image with the actual editor
443 // content, since actualy content may differ from
444 // the original snapshot due to dom change. (#4622)
445 this.update();
446 this.refreshState();
447
448 editor.fire( 'change' );
449 },
450
451 /**
452 * Gets the closest available image.
453 *
454 * @param {Boolean} isUndo If `true`, it will return the previous image.
455 * @returns {CKEDITOR.plugins.undo.Image} Next image or `null`.
456 */
457 getNextImage: function( isUndo ) {
458 var snapshots = this.snapshots,
459 currentImage = this.currentImage,
460 image, i;
461
462 if ( currentImage ) {
463 if ( isUndo ) {
464 for ( i = this.index - 1; i >= 0; i-- ) {
465 image = snapshots[ i ];
466 if ( !currentImage.equalsContent( image ) ) {
467 image.index = i;
468 return image;
469 }
470 }
471 } else {
472 for ( i = this.index + 1; i < snapshots.length; i++ ) {
473 image = snapshots[ i ];
474 if ( !currentImage.equalsContent( image ) ) {
475 image.index = i;
476 return image;
477 }
478 }
479 }
480 }
481
482 return null;
483 },
484
485 /**
486 * Checks the current redo state.
487 *
488 * @returns {Boolean} Whether the document has a previous state to retrieve.
489 */
490 redoable: function() {
491 return this.enabled && this.hasRedo;
492 },
493
494 /**
495 * Checks the current undo state.
496 *
497 * @returns {Boolean} Whether the document has a future state to restore.
498 */
499 undoable: function() {
500 return this.enabled && this.hasUndo;
501 },
502
503 /**
504 * Performs an undo operation on current index.
505 */
506 undo: function() {
507 if ( this.undoable() ) {
508 this.save( true );
509
510 var image = this.getNextImage( true );
511 if ( image )
512 return this.restoreImage( image ), true;
513 }
514
515 return false;
516 },
517
518 /**
519 * Performs a redo operation on current index.
520 */
521 redo: function() {
522 if ( this.redoable() ) {
523 // Try to save. If no changes have been made, the redo stack
524 // will not change, so it will still be redoable.
525 this.save( true );
526
527 // If instead we had changes, we can't redo anymore.
528 if ( this.redoable() ) {
529 var image = this.getNextImage( false );
530 if ( image )
531 return this.restoreImage( image ), true;
532 }
533 }
534
535 return false;
536 },
537
538 /**
539 * Updates the last snapshot of the undo stack with the current editor content.
540 *
541 * @param {CKEDITOR.plugins.undo.Image} [newImage] The image which will replace the current one.
542 * If it is not set, it defaults to the image taken from the editor.
543 */
544 update: function( newImage ) {
545 // Do not change snapshots stack is locked.
546 if ( this.locked )
547 return;
548
549 if ( !newImage )
550 newImage = new Image( this.editor );
551
552 var i = this.index,
553 snapshots = this.snapshots;
554
555 // Find all previous snapshots made for the same content (which differ
556 // only by selection) and replace all of them with the current image.
557 while ( i > 0 && this.currentImage.equalsContent( snapshots[ i - 1 ] ) )
558 i -= 1;
559
560 snapshots.splice( i, this.index - i + 1, newImage );
561 this.index = i;
562 this.currentImage = newImage;
563 },
564
565 /**
566 * Amends the last snapshot and changes its selection (only in case when content
567 * is equal between these two).
568 *
569 * @since 4.4.4
570 * @param {CKEDITOR.plugins.undo.Image} newSnapshot New snapshot with new selection.
571 * @returns {Boolean} Returns `true` if selection was amended.
572 */
573 updateSelection: function( newSnapshot ) {
574 if ( !this.snapshots.length )
575 return false;
576
577 var snapshots = this.snapshots,
578 lastImage = snapshots[ snapshots.length - 1 ];
579
580 if ( lastImage.equalsContent( newSnapshot ) ) {
581 if ( !lastImage.equalsSelection( newSnapshot ) ) {
582 snapshots[ snapshots.length - 1 ] = newSnapshot;
583 this.currentImage = newSnapshot;
584 return true;
585 }
586 }
587
588 return false;
589 },
590
591 /**
592 * Locks the snapshot stack to prevent any save/update operations and when necessary,
593 * updates the tip of the snapshot stack with the DOM changes introduced during the
594 * locked period, after the {@link #unlock} method is called.
595 *
596 * It is mainly used to ensure any DOM operations that should not be recorded
597 * (e.g. auto paragraphing) are not added to the stack.
598 *
599 * **Note:** For every `lock` call you must call {@link #unlock} once to unlock the undo manager.
600 *
601 * @since 4.0
602 * @param {Boolean} [dontUpdate] When set to `true`, the last snapshot will not be updated
603 * with current content and selection. By default, if undo manager was up to date when the lock started,
604 * the last snapshot will be updated to the current state when unlocking. This means that all changes
605 * done during the lock will be merged into the previous snapshot or the next one. Use this option to gain
606 * more control over this behavior. For example, it is possible to group changes done during the lock into
607 * a separate snapshot.
608 * @param {Boolean} [forceUpdate] When set to `true`, the last snapshot will always be updated with the
609 * current content and selection regardless of the current state of the undo manager.
610 * When not set, the last snapshot will be updated only if the undo manager was up to date when locking.
611 * Additionally, this option makes it possible to lock the snapshot when the editor is not in the `wysiwyg` mode,
612 * because when it is passed, the snapshots will not need to be compared.
613 */
614 lock: function( dontUpdate, forceUpdate ) {
615 if ( !this.locked ) {
616 if ( dontUpdate )
617 this.locked = { level: 1 };
618 else {
619 var update = null;
620
621 if ( forceUpdate )
622 update = true;
623 else {
624 // Make a contents image. Don't include bookmarks, because:
625 // * we don't compare them,
626 // * there's a chance that DOM has been changed since
627 // locked (e.g. fake) selection was made, so createBookmark2 could fail.
628 // http://dev.ckeditor.com/ticket/11027#comment:3
629 var imageBefore = new Image( this.editor, true );
630
631 // If current editor content matches the tip of snapshot stack,
632 // the stack tip must be updated by unlock, to include any changes made
633 // during this period.
634 if ( this.currentImage && this.currentImage.equalsContent( imageBefore ) )
635 update = imageBefore;
636 }
637
638 this.locked = { update: update, level: 1 };
639 }
640
641 // Increase the level of lock.
642 } else {
643 this.locked.level++;
644 }
645 },
646
647 /**
648 * Unlocks the snapshot stack and checks to amend the last snapshot.
649 *
650 * See {@link #lock} for more details.
651 *
652 * @since 4.0
653 */
654 unlock: function() {
655 if ( this.locked ) {
656 // Decrease level of lock and check if equals 0, what means that undoM is completely unlocked.
657 if ( !--this.locked.level ) {
658 var update = this.locked.update;
659
660 this.locked = null;
661
662 // forceUpdate was passed to lock().
663 if ( update === true )
664 this.update();
665 // update is instance of Image.
666 else if ( update ) {
667 var newImage = new Image( this.editor, true );
668
669 if ( !update.equalsContent( newImage ) )
670 this.update();
671 }
672 }
673 }
674 }
675 };
676
677 /**
678 * Codes for navigation keys like *Arrows*, *Page Up/Down*, etc.
679 * Used by the {@link #isNavigationKey} method.
680 *
681 * @since 4.4.5
682 * @readonly
683 * @static
684 */
685 UndoManager.navigationKeyCodes = {
686 37: 1, 38: 1, 39: 1, 40: 1, // Arrows.
687 36: 1, 35: 1, // Home, End.
688 33: 1, 34: 1 // PgUp, PgDn.
689 };
690
691 /**
692 * Key groups identifier mapping. Used for accessing members in
693 * {@link #strokesRecorded}.
694 *
695 * * `FUNCTIONAL` &ndash; identifier for the *Backspace* / *Delete* key.
696 * * `PRINTABLE` &ndash; identifier for printable keys.
697 *
698 * Example usage:
699 *
700 * undoManager.strokesRecorded[ undoManager.keyGroups.FUNCTIONAL ];
701 *
702 * @since 4.4.5
703 * @readonly
704 * @static
705 */
706 UndoManager.keyGroups = {
707 PRINTABLE: 0,
708 FUNCTIONAL: 1
709 };
710
711 /**
712 * Checks whether a key is one of navigation keys (*Arrows*, *Page Up/Down*, etc.).
713 * See also the {@link #navigationKeyCodes} property.
714 *
715 * @since 4.4.5
716 * @static
717 * @param {Number} keyCode
718 * @returns {Boolean}
719 */
720 UndoManager.isNavigationKey = function( keyCode ) {
721 return !!UndoManager.navigationKeyCodes[ keyCode ];
722 };
723
724 /**
725 * Returns the group to which the passed `keyCode` belongs.
726 *
727 * @since 4.4.5
728 * @static
729 * @param {Number} keyCode
730 * @returns {Number}
731 */
732 UndoManager.getKeyGroup = function( keyCode ) {
733 var keyGroups = UndoManager.keyGroups;
734
735 return backspaceOrDelete[ keyCode ] ? keyGroups.FUNCTIONAL : keyGroups.PRINTABLE;
736 };
737
738 /**
739 * @since 4.4.5
740 * @static
741 * @param {Number} keyGroup
742 * @returns {Number}
743 */
744 UndoManager.getOppositeKeyGroup = function( keyGroup ) {
745 var keyGroups = UndoManager.keyGroups;
746 return ( keyGroup == keyGroups.FUNCTIONAL ? keyGroups.PRINTABLE : keyGroups.FUNCTIONAL );
747 };
748
749 /**
750 * Whether we need to use a workaround for functional (*Backspace*, *Delete*) keys not firing
751 * the `keypress` event in Internet Explorer in this environment and for the specified `keyCode`.
752 *
753 * @since 4.4.5
754 * @static
755 * @param {Number} keyCode
756 * @returns {Boolean}
757 */
758 UndoManager.ieFunctionalKeysBug = function( keyCode ) {
759 return CKEDITOR.env.ie && UndoManager.getKeyGroup( keyCode ) == UndoManager.keyGroups.FUNCTIONAL;
760 };
761
762 // Helper method called when undoManager.typing val was changed to true.
763 function onTypingStart( undoManager ) {
764 // It's safe to now indicate typing state.
765 undoManager.typing = true;
766
767 // Manually mark snapshot as available.
768 undoManager.hasUndo = true;
769 undoManager.hasRedo = false;
770
771 undoManager.onChange();
772 }
773
774 /**
775 * Contains a snapshot of the editor content and selection at a given point in time.
776 *
777 * @private
778 * @class CKEDITOR.plugins.undo.Image
779 * @constructor Creates an Image class instance.
780 * @param {CKEDITOR.editor} editor The editor instance on which the image is created.
781 * @param {Boolean} [contentsOnly] If set to `true`, the image will only contain content without the selection.
782 */
783 var Image = CKEDITOR.plugins.undo.Image = function( editor, contentsOnly ) {
784 this.editor = editor;
785
786 editor.fire( 'beforeUndoImage' );
787
788 var contents = editor.getSnapshot();
789
790 // In IE, we need to remove the expando attributes.
791 if ( CKEDITOR.env.ie && contents )
792 contents = contents.replace( /\s+data-cke-expando=".*?"/g, '' );
793
794 this.contents = contents;
795
796 if ( !contentsOnly ) {
797 var selection = contents && editor.getSelection();
798 this.bookmarks = selection && selection.createBookmarks2( true );
799 }
800
801 editor.fire( 'afterUndoImage' );
802 };
803
804 // Attributes that browser may changing them when setting via innerHTML.
805 var protectedAttrs = /\b(?:href|src|name)="[^"]*?"/gi;
806
807 Image.prototype = {
808 /**
809 * @param {CKEDITOR.plugins.undo.Image} otherImage Image to compare to.
810 * @returns {Boolean} Returns `true` if content in `otherImage` is the same.
811 */
812 equalsContent: function( otherImage ) {
813 var thisContents = this.contents,
814 otherContents = otherImage.contents;
815
816 // For IE7 and IE QM: Comparing only the protected attribute values but not the original ones.(#4522)
817 if ( CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.quirks ) ) {
818 thisContents = thisContents.replace( protectedAttrs, '' );
819 otherContents = otherContents.replace( protectedAttrs, '' );
820 }
821
822 if ( thisContents != otherContents )
823 return false;
824
825 return true;
826 },
827
828 /**
829 * @param {CKEDITOR.plugins.undo.Image} otherImage Image to compare to.
830 * @returns {Boolean} Returns `true` if selection in `otherImage` is the same.
831 */
832 equalsSelection: function( otherImage ) {
833 var bookmarksA = this.bookmarks,
834 bookmarksB = otherImage.bookmarks;
835
836 if ( bookmarksA || bookmarksB ) {
837 if ( !bookmarksA || !bookmarksB || bookmarksA.length != bookmarksB.length )
838 return false;
839
840 for ( var i = 0; i < bookmarksA.length; i++ ) {
841 var bookmarkA = bookmarksA[ i ],
842 bookmarkB = bookmarksB[ i ];
843
844 if ( bookmarkA.startOffset != bookmarkB.startOffset || bookmarkA.endOffset != bookmarkB.endOffset ||
845 !CKEDITOR.tools.arrayCompare( bookmarkA.start, bookmarkB.start ) ||
846 !CKEDITOR.tools.arrayCompare( bookmarkA.end, bookmarkB.end ) ) {
847 return false;
848 }
849 }
850 }
851
852 return true;
853 }
854
855 /**
856 * Editor content.
857 *
858 * @readonly
859 * @property {String} contents
860 */
861
862 /**
863 * Bookmarks representing the selection in an image.
864 *
865 * @readonly
866 * @property {Object[]} bookmarks Array of bookmark2 objects, see {@link CKEDITOR.dom.range#createBookmark2} for definition.
867 */
868 };
869
870 /**
871 * A class encapsulating all native event listeners which have to be used in
872 * order to handle undo manager integration for native editing actions (excluding drag and drop and paste support
873 * handled by the Clipboard plugin).
874 *
875 * @since 4.4.4
876 * @private
877 * @class CKEDITOR.plugins.undo.NativeEditingHandler
878 * @member CKEDITOR.plugins.undo Undo manager owning the handler.
879 * @constructor
880 * @param {CKEDITOR.plugins.undo.UndoManager} undoManager
881 */
882 var NativeEditingHandler = CKEDITOR.plugins.undo.NativeEditingHandler = function( undoManager ) {
883 // We'll use keyboard + input events to determine if snapshot should be created.
884 // Since `input` event is fired before `keyup`. We can tell in `keyup` event if input occured.
885 // That will tell us if any printable data was inserted.
886 // On `input` event we'll increase input fired counter for proper key code.
887 // Eventually it might be canceled by paste/drop using `ignoreInputEvent` flag.
888 // Order of events can be found in http://www.w3.org/TR/DOM-Level-3-Events/
889
890 /**
891 * An undo manager instance owning the editing handler.
892 *
893 * @property {CKEDITOR.plugins.undo.UndoManager} undoManager
894 */
895 this.undoManager = undoManager;
896
897 /**
898 * See {@link #ignoreInputEventListener}.
899 *
900 * @since 4.4.5
901 * @private
902 */
903 this.ignoreInputEvent = false;
904
905 /**
906 * A stack of pressed keys.
907 *
908 * @since 4.4.5
909 * @property {CKEDITOR.plugins.undo.KeyEventsStack} keyEventsStack
910 */
911 this.keyEventsStack = new KeyEventsStack();
912
913 /**
914 * An image of the editor during the `keydown` event (therefore without DOM modification).
915 *
916 * @property {CKEDITOR.plugins.undo.Image} lastKeydownImage
917 */
918 this.lastKeydownImage = null;
919 };
920
921 NativeEditingHandler.prototype = {
922 /**
923 * The `keydown` event listener.
924 *
925 * @param {CKEDITOR.dom.event} evt
926 */
927 onKeydown: function( evt ) {
928 var keyCode = evt.data.getKey();
929
930 // The composition is in progress - ignore the key. (#12597)
931 if ( keyCode === 229 ) {
932 return;
933 }
934
935 // Block undo/redo keystrokes when at the bottom/top of the undo stack (#11126 and #11677).
936 if ( CKEDITOR.tools.indexOf( keystrokes, evt.data.getKeystroke() ) > -1 ) {
937 evt.data.preventDefault();
938 return;
939 }
940
941 // Cleaning tab functional keys.
942 this.keyEventsStack.cleanUp( evt );
943
944 var undoManager = this.undoManager;
945
946 // Gets last record for provided keyCode. If not found will create one.
947 var last = this.keyEventsStack.getLast( keyCode );
948 if ( !last ) {
949 this.keyEventsStack.push( keyCode );
950 }
951
952 // We need to store an image which will be used in case of key group
953 // change.
954 this.lastKeydownImage = new Image( undoManager.editor );
955
956 if ( UndoManager.isNavigationKey( keyCode ) || this.undoManager.keyGroupChanged( keyCode ) ) {
957 if ( undoManager.strokesRecorded[ 0 ] || undoManager.strokesRecorded[ 1 ] ) {
958 // We already have image, so we'd like to reuse it.
959
960 // #12300
961 undoManager.save( false, this.lastKeydownImage, false );
962 undoManager.resetType();
963 }
964 }
965 },
966
967 /**
968 * The `input` event listener.
969 */
970 onInput: function() {
971 // Input event is ignored if paste/drop event were fired before.
972 if ( this.ignoreInputEvent ) {
973 // Reset flag - ignore only once.
974 this.ignoreInputEvent = false;
975 return;
976 }
977
978 var lastInput = this.keyEventsStack.getLast();
979 // Nothing in key events stack, but input event called. Interesting...
980 // That's because on Android order of events is buggy and also keyCode is set to 0.
981 if ( !lastInput ) {
982 lastInput = this.keyEventsStack.push( 0 );
983 }
984
985 // Increment inputs counter for provided key code.
986 this.keyEventsStack.increment( lastInput.keyCode );
987
988 // Exceeded limit.
989 if ( this.keyEventsStack.getTotalInputs() >= this.undoManager.strokesLimit ) {
990 this.undoManager.type( lastInput.keyCode, true );
991 this.keyEventsStack.resetInputs();
992 }
993 },
994
995 /**
996 * The `keyup` event listener.
997 *
998 * @param {CKEDITOR.dom.event} evt
999 */
1000 onKeyup: function( evt ) {
1001 var undoManager = this.undoManager,
1002 keyCode = evt.data.getKey(),
1003 totalInputs = this.keyEventsStack.getTotalInputs();
1004
1005 // Remove record from stack for provided key code.
1006 this.keyEventsStack.remove( keyCode );
1007
1008 // Second part of the workaround for IEs functional keys bug. We need to check whether something has really
1009 // changed because we blindly mocked the keypress event.
1010 // Also we need to be aware that lastKeydownImage might not be available (#12327).
1011 if ( UndoManager.ieFunctionalKeysBug( keyCode ) && this.lastKeydownImage &&
1012 this.lastKeydownImage.equalsContent( new Image( undoManager.editor, true ) ) ) {
1013 return;
1014 }
1015
1016 if ( totalInputs > 0 ) {
1017 undoManager.type( keyCode );
1018 } else if ( UndoManager.isNavigationKey( keyCode ) ) {
1019 // Note content snapshot has been checked in keydown.
1020 this.onNavigationKey( true );
1021 }
1022 },
1023
1024 /**
1025 * Method called for navigation change. At first it will check if current content does not differ
1026 * from the last saved snapshot.
1027 *
1028 * * If the content is different, the method creates a standard, extra snapshot.
1029 * * If the content is not different, the method will compare the selection, and will
1030 * amend the last snapshot selection if it changed.
1031 *
1032 * @param {Boolean} skipContentCompare If set to `true`, it will not compare content, and only do a selection check.
1033 */
1034 onNavigationKey: function( skipContentCompare ) {
1035 var undoManager = this.undoManager;
1036
1037 // We attempt to save content snapshot, if content didn't change, we'll
1038 // only amend selection.
1039 if ( skipContentCompare || !undoManager.save( true, null, false ) )
1040 undoManager.updateSelection( new Image( undoManager.editor ) );
1041
1042 undoManager.resetType();
1043 },
1044
1045 /**
1046 * Makes the next `input` event to be ignored.
1047 */
1048 ignoreInputEventListener: function() {
1049 this.ignoreInputEvent = true;
1050 },
1051
1052 /**
1053 * Attaches editable listeners required to provide the undo functionality.
1054 */
1055 attachListeners: function() {
1056 var editor = this.undoManager.editor,
1057 editable = editor.editable(),
1058 that = this;
1059
1060 // We'll create a snapshot here (before DOM modification), because we'll
1061 // need unmodified content when we got keygroup toggled in keyup.
1062 editable.attachListener( editable, 'keydown', function( evt ) {
1063 that.onKeydown( evt );
1064
1065 // On IE keypress isn't fired for functional (backspace/delete) keys.
1066 // Let's pretend that something's changed.
1067 if ( UndoManager.ieFunctionalKeysBug( evt.data.getKey() ) ) {
1068 that.onInput();
1069 }
1070 }, null, null, 999 );
1071
1072 // Only IE can't use input event, because it's not fired in contenteditable.
1073 editable.attachListener( editable, ( CKEDITOR.env.ie ? 'keypress' : 'input' ), that.onInput, that, null, 999 );
1074
1075 // Keyup executes main snapshot logic.
1076 editable.attachListener( editable, 'keyup', that.onKeyup, that, null, 999 );
1077
1078 // On paste and drop we need to ignore input event.
1079 // It would result with calling undoManager.type() on any following key.
1080 editable.attachListener( editable, 'paste', that.ignoreInputEventListener, that, null, 999 );
1081 editable.attachListener( editable, 'drop', that.ignoreInputEventListener, that, null, 999 );
1082
1083 // Click should create a snapshot if needed, but shouldn't cause change event.
1084 // Don't pass onNavigationKey directly as a listener because it accepts one argument which
1085 // will conflict with evt passed to listener.
1086 // #12324 comment:4
1087 editable.attachListener( editable.isInline() ? editable : editor.document.getDocumentElement(), 'click', function() {
1088 that.onNavigationKey();
1089 }, null, null, 999 );
1090
1091 // When pressing `Tab` key while editable is focused, `keyup` event is not fired.
1092 // Which means that record for `tab` key stays in key events stack.
1093 // We assume that when editor is blurred `tab` key is already up.
1094 editable.attachListener( this.undoManager.editor, 'blur', function() {
1095 that.keyEventsStack.remove( 9 /*Tab*/ );
1096 }, null, null, 999 );
1097 }
1098 };
1099
1100 /**
1101 * This class represents a stack of pressed keys and stores information
1102 * about how many `input` events each key press has caused.
1103 *
1104 * @since 4.4.5
1105 * @private
1106 * @class CKEDITOR.plugins.undo.KeyEventsStack
1107 * @constructor
1108 */
1109 var KeyEventsStack = CKEDITOR.plugins.undo.KeyEventsStack = function() {
1110 /**
1111 * @readonly
1112 */
1113 this.stack = [];
1114 };
1115
1116 KeyEventsStack.prototype = {
1117 /**
1118 * Pushes a literal object with two keys: `keyCode` and `inputs` (whose initial value is set to `0`) to stack.
1119 * It is intended to be called on the `keydown` event.
1120 *
1121 * @param {Number} keyCode
1122 */
1123 push: function( keyCode ) {
1124 var length = this.stack.push( { keyCode: keyCode, inputs: 0 } );
1125 return this.stack[ length - 1 ];
1126 },
1127
1128 /**
1129 * Returns the index of the last registered `keyCode` in the stack.
1130 * If no `keyCode` is provided, then the function will return the index of the last item.
1131 * If an item is not found, it will return `-1`.
1132 *
1133 * @param {Number} [keyCode]
1134 * @returns {Number}
1135 */
1136 getLastIndex: function( keyCode ) {
1137 if ( typeof keyCode != 'number' ) {
1138 return this.stack.length - 1; // Last index or -1.
1139 } else {
1140 var i = this.stack.length;
1141 while ( i-- ) {
1142 if ( this.stack[ i ].keyCode == keyCode ) {
1143 return i;
1144 }
1145 }
1146 return -1;
1147 }
1148 },
1149
1150 /**
1151 * Returns the last key recorded in the stack. If `keyCode` is provided, then it will return
1152 * the last record for this `keyCode`.
1153 *
1154 * @param {Number} [keyCode]
1155 * @returns {Object} Last matching record or `null`.
1156 */
1157 getLast: function( keyCode ) {
1158 var index = this.getLastIndex( keyCode );
1159 if ( index != -1 ) {
1160 return this.stack[ index ];
1161 } else {
1162 return null;
1163 }
1164 },
1165
1166 /**
1167 * Increments registered input events for stack record for a given `keyCode`.
1168 *
1169 * @param {Number} keyCode
1170 */
1171 increment: function( keyCode ) {
1172 var found = this.getLast( keyCode );
1173 if ( !found ) { // %REMOVE_LINE%
1174 throw new Error( 'Trying to increment, but could not found by keyCode: ' + keyCode + '.' ); // %REMOVE_LINE%
1175 } // %REMOVE_LINE%
1176
1177 found.inputs++;
1178 },
1179
1180 /**
1181 * Removes the last record from the stack for the provided `keyCode`.
1182 *
1183 * @param {Number} keyCode
1184 */
1185 remove: function( keyCode ) {
1186 var index = this.getLastIndex( keyCode );
1187
1188 if ( index != -1 ) {
1189 this.stack.splice( index, 1 );
1190 }
1191 },
1192
1193 /**
1194 * Resets the `inputs` value to `0` for a given `keyCode` or in entire stack if a
1195 * `keyCode` is not specified.
1196 *
1197 * @param {Number} [keyCode]
1198 */
1199 resetInputs: function( keyCode ) {
1200 if ( typeof keyCode == 'number' ) {
1201 var last = this.getLast( keyCode );
1202
1203 if ( !last ) { // %REMOVE_LINE%
1204 throw new Error( 'Trying to reset inputs count, but could not found by keyCode: ' + keyCode + '.' ); // %REMOVE_LINE%
1205 } // %REMOVE_LINE%
1206
1207 last.inputs = 0;
1208 } else {
1209 var i = this.stack.length;
1210 while ( i-- ) {
1211 this.stack[ i ].inputs = 0;
1212 }
1213 }
1214 },
1215
1216 /**
1217 * Sums up inputs number for each key code and returns it.
1218 *
1219 * @returns {Number}
1220 */
1221 getTotalInputs: function() {
1222 var i = this.stack.length,
1223 total = 0;
1224
1225 while ( i-- ) {
1226 total += this.stack[ i ].inputs;
1227 }
1228 return total;
1229 },
1230
1231 /**
1232 * Cleans the stack based on a provided `keydown` event object. The rationale behind this method
1233 * is that some keystrokes cause the `keydown` event to be fired in the editor, but not the `keyup` event.
1234 * For instance, *Alt+Tab* will fire `keydown`, but since the editor is blurred by it, then there is
1235 * no `keyup`, so the keystroke is not removed from the stack.
1236 *
1237 * @param {CKEDITOR.dom.event} event
1238 */
1239 cleanUp: function( event ) {
1240 var nativeEvent = event.data.$;
1241
1242 if ( !( nativeEvent.ctrlKey || nativeEvent.metaKey ) ) {
1243 this.remove( 17 );
1244 }
1245 if ( !nativeEvent.shiftKey ) {
1246 this.remove( 16 );
1247 }
1248 if ( !nativeEvent.altKey ) {
1249 this.remove( 18 );
1250 }
1251 }
1252 };
1253} )();
1254
1255/**
1256 * The number of undo steps to be saved. The higher value is set, the more
1257 * memory is used for it.
1258 *
1259 * config.undoStackSize = 50;
1260 *
1261 * @cfg {Number} [undoStackSize=20]
1262 * @member CKEDITOR.config
1263 */
1264
1265/**
1266 * Fired when the editor is about to save an undo snapshot. This event can be
1267 * fired by plugins and customizations to make the editor save undo snapshots.
1268 *
1269 * @event saveSnapshot
1270 * @member CKEDITOR.editor
1271 * @param {CKEDITOR.editor} editor This editor instance.
1272 */
1273
1274/**
1275 * Fired before an undo image is to be created. An *undo image* represents the
1276 * editor state at some point. It is saved into the undo store, so the editor is
1277 * able to recover the editor state on undo and redo operations.
1278 *
1279 * @since 3.5.3
1280 * @event beforeUndoImage
1281 * @member CKEDITOR.editor
1282 * @param {CKEDITOR.editor} editor This editor instance.
1283 * @see CKEDITOR.editor#afterUndoImage
1284 */
1285
1286/**
1287 * Fired after an undo image is created. An *undo image* represents the
1288 * editor state at some point. It is saved into the undo store, so the editor is
1289 * able to recover the editor state on undo and redo operations.
1290 *
1291 * @since 3.5.3
1292 * @event afterUndoImage
1293 * @member CKEDITOR.editor
1294 * @param {CKEDITOR.editor} editor This editor instance.
1295 * @see CKEDITOR.editor#beforeUndoImage
1296 */
1297
1298/**
1299 * Fired when the content of the editor is changed.
1300 *
1301 * Due to performance reasons, it is not verified if the content really changed.
1302 * The editor instead watches several editing actions that usually result in
1303 * changes. This event may thus in some cases be fired when no changes happen
1304 * or may even get fired twice.
1305 *
1306 * If it is important not to get the `change` event fired too often, you should compare the
1307 * previous and the current editor content inside the event listener. It is
1308 * not recommended to do that on every `change` event.
1309 *
1310 * Please note that the `change` event is only fired in the {@link #property-mode wysiwyg mode}.
1311 * In order to implement similar functionality in the source mode, you can listen for example to the {@link #key}
1312 * event or the native [`input`](https://developer.mozilla.org/en-US/docs/Web/Reference/Events/input)
1313 * event (not supported by Internet Explorer 8).
1314 *
1315 * editor.on( 'mode', function() {
1316 * if ( this.mode == 'source' ) {
1317 * var editable = editor.editable();
1318 * editable.attachListener( editable, 'input', function() {
1319 * // Handle changes made in the source mode.
1320 * } );
1321 * }
1322 * } );
1323 *
1324 * @since 4.2
1325 * @event change
1326 * @member CKEDITOR.editor
1327 * @param {CKEDITOR.editor} editor This editor instance.
1328 */