From 5cb2269b99dabc933efc519a7f2350662227db98 Mon Sep 17 00:00:00 2001 From: Kajetan Litwinowicz Date: Wed, 31 Jan 2018 12:15:40 +0100 Subject: [PATCH 001/642] Improving color contrast on Widget hover border Changed Widget ( figure selector in our css ) border and border radius to none, added outline with same value as border, but without radius. Changed Widget and Widget editable hover and focus outline to 3px and changed colors to more contrasting. --- CHANGES.md | 1 + contents.css | 3 +-- plugins/widget/plugin.js | 6 ++--- tests/plugins/widget/manual/outline.html | 32 ++++++++++++++++++++++++ tests/plugins/widget/manual/outline.md | 17 +++++++++++++ 5 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 tests/plugins/widget/manual/outline.html create mode 100644 tests/plugins/widget/manual/outline.md diff --git a/CHANGES.md b/CHANGES.md index 49235662df2..e1cb61dea89 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,7 @@ Fixed Issues: * [#1426](https://github.com/ckeditor/ckeditor-dev/issues/1426): [IE8-9] Fixed: Missing balloon toolbar background in Kama skin. Thanks to [Christian Elmer](https://github.com/keinkurt)! * [#1010](https://github.com/ckeditor/ckeditor-dev/issues/1010): Fixed: CSS `border` shorthand property was incorrectly expanded ignoring `border-color` style. * [#1470](https://github.com/ckeditor/ckeditor-dev/issues/1470): Fixed: [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) is not visible after drag and drop of a widget it is attached to. +* [#1535](https://github.com/ckeditor/ckeditor-dev/issues/1535): Fixed: [Widget](https://ckeditor.com/cke4/addon/widget) border color has low contrast. API Changes: diff --git a/contents.css b/contents.css index 183c3d8659c..fccfab764c0 100644 --- a/contents.css +++ b/contents.css @@ -113,8 +113,7 @@ span[lang] figure { text-align: center; - border: solid 1px #ccc; - border-radius: 2px; + outline: solid 1px #ccc; background: rgba(0,0,0,0.05); padding: 10px; margin: 10px 20px; diff --git a/plugins/widget/plugin.js b/plugins/widget/plugin.js index a61fb0b3166..08ad8da4afe 100644 --- a/plugins/widget/plugin.js +++ b/plugins/widget/plugin.js @@ -31,16 +31,16 @@ 'display:inline-block' + '}' + '.cke_widget_wrapper:hover>.cke_widget_element{' + - 'outline:2px solid yellow;' + + 'outline:2px solid #ffd25c;' + 'cursor:default' + '}' + '.cke_widget_wrapper:hover .cke_widget_editable{' + - 'outline:2px solid yellow' + + 'outline:2px solid #ffd25c' + '}' + '.cke_widget_wrapper.cke_widget_focused>.cke_widget_element,' + // We need higher specificity than hover style. '.cke_widget_wrapper .cke_widget_editable.cke_widget_editable_focused{' + - 'outline:2px solid #ace' + + 'outline:2px solid #47a4f5' + '}' + '.cke_widget_editable{' + 'cursor:text' + diff --git a/tests/plugins/widget/manual/outline.html b/tests/plugins/widget/manual/outline.html new file mode 100644 index 00000000000..48e36f8cc86 --- /dev/null +++ b/tests/plugins/widget/manual/outline.html @@ -0,0 +1,32 @@ + + + + +
+

Classic

+
+ +
+ +
+

Inline

+
+
+
Saturn V +
Roll out of Saturn V on launch pad
+
+

Some text.

+
+
+ + + diff --git a/tests/plugins/widget/manual/outline.md b/tests/plugins/widget/manual/outline.md new file mode 100644 index 00000000000..41c4c3c58b8 --- /dev/null +++ b/tests/plugins/widget/manual/outline.md @@ -0,0 +1,17 @@ +@bender-ui: collapsed +@bender-tags: 4.9.0, 1535, feature +@bender-ckeditor-plugins: wysiwygarea,toolbar,elementspath,clipboard,floatingspace,image2 + +## For each editor instance: + +1. Hover on widget. +1. Focus widget. +1. Focus widget editable. + +### Expected: + +Widget outline on hover has orange color and 2px thickness. + +### Unexpected: + +Widget outline on hover has yellow color. From 7892e7e6c92b677ae21e3c9c213c4c188823839a Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 2 Feb 2018 13:27:10 +0100 Subject: [PATCH 002/642] Adjusted changelog entry. --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index e1cb61dea89..337551f0701 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,7 +26,7 @@ Fixed Issues: * [#1426](https://github.com/ckeditor/ckeditor-dev/issues/1426): [IE8-9] Fixed: Missing balloon toolbar background in Kama skin. Thanks to [Christian Elmer](https://github.com/keinkurt)! * [#1010](https://github.com/ckeditor/ckeditor-dev/issues/1010): Fixed: CSS `border` shorthand property was incorrectly expanded ignoring `border-color` style. * [#1470](https://github.com/ckeditor/ckeditor-dev/issues/1470): Fixed: [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) is not visible after drag and drop of a widget it is attached to. -* [#1535](https://github.com/ckeditor/ckeditor-dev/issues/1535): Fixed: [Widget](https://ckeditor.com/cke4/addon/widget) border color has low contrast. +* [#1535](https://github.com/ckeditor/ckeditor-dev/issues/1535): Fixed: Improve [Widget](https://ckeditor.com/cke4/addon/widget) mouse over border contrast. API Changes: From b848e2c4e67198432457a67d5055f2e072a0cfd7 Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Fri, 2 Feb 2018 10:14:41 +0100 Subject: [PATCH 003/642] Add dependancy to filebrowser from filetools, update docs description. --- plugins/filebrowser/plugin.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/filebrowser/plugin.js b/plugins/filebrowser/plugin.js index 93eb7daad17..33446fad5a0 100644 --- a/plugins/filebrowser/plugin.js +++ b/plugins/filebrowser/plugin.js @@ -414,7 +414,7 @@ } CKEDITOR.plugins.add( 'filebrowser', { - requires: 'popup', + requires: 'popup,filetools', init: function( editor ) { editor._.filebrowserFn = CKEDITOR.tools.addFunction( setUrl, editor ); editor.on( 'destroy', function() { @@ -608,12 +608,10 @@ * {@link CKEDITOR.config#fileTools_requestHeaders} option. * * `'form'` - File is uploaded by submitting a traditional `
` element. _Note: That was the only option available until CKEditor 4.9.0._ * - * Note: please be aware that `'xhr'` requires the [File Tools](https://ckeditor.com/cke4/addon/filetools) plugin to work - * properly. Without the plugin or using a browser that does not support - * {@link CKEDITOR.fileTools#isFileUploadSupported file uploading}, will fallback to the `'form'` method despite configuration - * option. + * Example: * - * // All browsers will use form element with submit method to upload a file. + * // All browsers will use form element with submit method + * // to upload a file through filebrowser plugin. * config.filebrowserUploadMethod = 'form'; * * @since 4.9.0 From 56ad18d1d16cea98af45dd01e08c40496ab6aea2 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 5 Feb 2018 11:01:20 +0100 Subject: [PATCH 004/642] Docs: corrected config.filebrowserUploadMethod. Provided snippet will not use File Tools plugin. --- plugins/filebrowser/plugin.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/filebrowser/plugin.js b/plugins/filebrowser/plugin.js index 33446fad5a0..b233cd7504c 100644 --- a/plugins/filebrowser/plugin.js +++ b/plugins/filebrowser/plugin.js @@ -610,8 +610,7 @@ * * Example: * - * // All browsers will use form element with submit method - * // to upload a file through filebrowser plugin. + * // All browsers will use plain form element to upload a file. * config.filebrowserUploadMethod = 'form'; * * @since 4.9.0 From c443b3a0765ec46b5a20d18f48a8a012243f5196 Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Fri, 5 Jan 2018 13:54:52 +0100 Subject: [PATCH 005/642] Update main sample page with new CKEditor logo. Adapt colors to be more coherent with new logo. --- samples/css/samples.css | 40 +++++++++++++++++++++------------------- samples/img/logo.png | Bin 5891 -> 12450 bytes 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/samples/css/samples.css b/samples/css/samples.css index be8eaeedf68..19db37f9691 100644 --- a/samples/css/samples.css +++ b/samples/css/samples.css @@ -133,6 +133,8 @@ html { } .header-a .header-a-logo img { border: transparent; + width: 160px; + height: 60px; } .navigation-a { height: 30px; @@ -282,12 +284,12 @@ html { color: #8a8a8a; } .footer-a a { - color: #27C0D8; + color: #0287D0; text-decoration: none; - border-bottom: 1px dotted #27C0D8; + border-bottom: 1px dotted #0287D0; } .footer-a a:hover { - color: #23adc2; + color: #0267B0; } .footer-a p { margin: 0; @@ -333,7 +335,7 @@ html { .content blockquote, .content pre { background: none; - border-left: 4px solid #27C0D8; + border-left: 4px solid #0287D0; padding: 1.5em 2.25em; } .content p a, @@ -345,9 +347,9 @@ html { .content h3 a, .content h4 a, .content h5 a { - color: #27C0D8; + color: #0287D0; text-decoration: none; - border-bottom: 1px dotted #27C0D8; + border-bottom: 1px dotted #0287D0; } .content p a:hover, .content ul a:hover, @@ -358,7 +360,7 @@ html { .content h3 a:hover, .content h4 a:hover, .content h5 a:hover { - color: #23adc2; + color: #0267B0; } .content h1, .content h2, @@ -672,7 +674,7 @@ body a.button-a:hover, body button.button-a:hover, body input.button-a:hover { color: #fff; - background: #23adc2; + background: #0267B0; } body a.button-a:focus, body button.button-a:focus, @@ -704,7 +706,7 @@ body a.navigation-b ul li a:hover, body button.navigation-b ul li a:hover, body input.navigation-b ul li a:hover { color: #fff; - background: #27C0D8; + background: #0287D0; } body a.button-a-background:active, body button.button-a-background:active, @@ -719,7 +721,7 @@ body a.navigation-b ul li a:hover:hover, body button.navigation-b ul li a:hover:hover, body input.navigation-b ul li a:hover:hover { color: #fff; - background: #23adc2; + background: #0267B0; } .balloon-a { font-size: 12px; @@ -826,7 +828,7 @@ body input.navigation-b ul li a:hover:hover { line-height: 25.2px; line-height: 1.57rem; font-weight: bold; - background-color: #27C0D8; + background-color: #0287D0; overflow: hidden; display: inline-block; padding: 0.75em 0.25em; @@ -872,7 +874,7 @@ body input.navigation-b ul li a:hover:hover { display: block; height: 1.5em; width: 1.5em; - background: #25b4cb; + background: #0267B0; -webkit-border-radius: 4.5px; -webkit-background-clip: padding-box; -moz-border-radius: 4.5px; @@ -888,7 +890,7 @@ body input.navigation-b ul li a:hover:hover { right: 0; bottom: 3px; left: 0; - background-color: #34c4da; + background-color: #22A7D0; -webkit-border-bottom-left-radius: 4.5px; -moz-border-radius-bottomleft: 4.5px; border-bottom-left-radius: 4.5px; @@ -900,7 +902,7 @@ body input.navigation-b ul li a:hover:hover { background-clip: padding-box; } .switch:hover .switch-inner .handler:before { - background: #45c9dd; + background: #0288C0; } .switch input[data-num="2"]:checked ~ .switch-inner > .handler { margin-left: auto; @@ -1007,7 +1009,7 @@ footer > div { border-top: 1px solid #D9D9D9; } .adjoined-top { - background-color: #27C0D8; + background-color: #0287D0; color: #fff; } .adjoined-top .content h1, @@ -1040,7 +1042,7 @@ footer > div { } .adjoined-top .content code { font-size: inherit; - color: #27C0D8; + color: #0287D0; } .adjoined-bottom { position: relative; @@ -1048,7 +1050,7 @@ footer > div { .adjoined-bottom:before { z-index: -1; content: ''; - background: #27C0D8; + background: #0287D0; position: absolute; top: 0; left: 0; @@ -1065,7 +1067,7 @@ main .grid-container.freed-width { max-width: none; } .switch { - background: #25b4cb; + background: #0267B0; float: right; overflow: visible; } @@ -1091,7 +1093,7 @@ main .grid-container.freed-width { #main #editor { background: #FFF; padding: 2% 4%; - border: dashed 5px #27C0D8; + border: dashed 5px #0287D0; } #main .adjoined-top:before { height: 335px; diff --git a/samples/img/logo.png b/samples/img/logo.png index 96d86e27c137e248693721e35485b590b7ab805e..c62de21d7ba308ea656ca64d329b85bfd6d25574 100644 GIT binary patch literal 12450 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 Z{|{I2?1a58H2(kq002ovPDHLkV1ju Date: Thu, 18 Jan 2018 14:30:07 +0100 Subject: [PATCH 006/642] Update less file to use new color and logo's style. Correct path to lesshat. --- samples/less/custom.less | 12 ++++++++++++ samples/less/samples.less | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/samples/less/custom.less b/samples/less/custom.less index ca29bd69386..8804c96da04 100644 --- a/samples/less/custom.less +++ b/samples/less/custom.less @@ -1,3 +1,5 @@ +@global-link-font-color:#0287D0; + main .grid-container, header .grid-container, .navigation-a > div, @@ -161,3 +163,13 @@ header { } ); } } + +// Double compress image to have better quality on HiDPI. +.header-a { + .header-a-logo { + img { + width: 160px; + height: 60px; + } + } +} diff --git a/samples/less/samples.less b/samples/less/samples.less index 914478af1e2..1eef1d544c4 100644 --- a/samples/less/samples.less +++ b/samples/less/samples.less @@ -2,7 +2,7 @@ @components-dir: "../../node_modules/cksource-samples-framework/components"; // Good 'ol Lesshat. -@import "../../node_modules/cksource-samples-framework/node_modules/lesshat/build/lesshat"; +@import "../../node_modules/lesshat/build/lesshat"; // Generic components of the page. @import "@{components-dir}/global/global"; @@ -28,4 +28,4 @@ @import "custom"; // Toolbar modifier. -@import "../toolbarconfigurator/less/toolbarmodifier"; \ No newline at end of file +@import "../toolbarconfigurator/less/toolbarmodifier"; From 8af45bfb313ecd2187e74b612fd8baae64eea9e5 Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Thu, 18 Jan 2018 14:23:16 +0100 Subject: [PATCH 007/642] Update css acording to new less rules. --- samples/css/samples.css | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/samples/css/samples.css b/samples/css/samples.css index 19db37f9691..118868e3a93 100644 --- a/samples/css/samples.css +++ b/samples/css/samples.css @@ -133,8 +133,6 @@ html { } .header-a .header-a-logo img { border: transparent; - width: 160px; - height: 60px; } .navigation-a { height: 30px; @@ -289,7 +287,7 @@ html { border-bottom: 1px dotted #0287D0; } .footer-a a:hover { - color: #0267B0; + color: #0277b7; } .footer-a p { margin: 0; @@ -360,7 +358,7 @@ html { .content h3 a:hover, .content h4 a:hover, .content h5 a:hover { - color: #0267B0; + color: #0277b7; } .content h1, .content h2, @@ -674,7 +672,7 @@ body a.button-a:hover, body button.button-a:hover, body input.button-a:hover { color: #fff; - background: #0267B0; + background: #0277b7; } body a.button-a:focus, body button.button-a:focus, @@ -721,7 +719,7 @@ body a.navigation-b ul li a:hover:hover, body button.navigation-b ul li a:hover:hover, body input.navigation-b ul li a:hover:hover { color: #fff; - background: #0267B0; + background: #0277b7; } .balloon-a { font-size: 12px; @@ -874,7 +872,7 @@ body input.navigation-b ul li a:hover:hover { display: block; height: 1.5em; width: 1.5em; - background: #0267B0; + background: #027dc1; -webkit-border-radius: 4.5px; -webkit-background-clip: padding-box; -moz-border-radius: 4.5px; @@ -890,7 +888,7 @@ body input.navigation-b ul li a:hover:hover { right: 0; bottom: 3px; left: 0; - background-color: #22A7D0; + background-color: #0291df; -webkit-border-bottom-left-radius: 4.5px; -moz-border-radius-bottomleft: 4.5px; border-bottom-left-radius: 4.5px; @@ -902,7 +900,7 @@ body input.navigation-b ul li a:hover:hover { background-clip: padding-box; } .switch:hover .switch-inner .handler:before { - background: #0288C0; + background: #029ef3; } .switch input[data-num="2"]:checked ~ .switch-inner > .handler { margin-left: auto; @@ -1067,7 +1065,7 @@ main .grid-container.freed-width { max-width: none; } .switch { - background: #0267B0; + background: #027dc1; float: right; overflow: visible; } @@ -1179,6 +1177,18 @@ header .balloon-a { display: none; } } +.header-a .header-a-logo img { + width: 160px; + height: 60px; +} +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ #toolbar .cke_toolbar { pointer-events: none; -webkit-user-select: none; @@ -1631,4 +1641,4 @@ div.toolbarModifier-hints dl dd:after { #help-content { display: none; } -/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2dsb2JhbC9nbG9iYWwubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2NvcmUvY29yZS5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvZ3JpZC9ncmlkLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvbm9kZV9tb2R1bGVzL2xlc3NoYXQvYnVpbGQvbGVzc2hhdC5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvaGVhZGVyLWEvaGVhZGVyLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL25hdmlnYXRpb24tYS9uYXZpZ2F0aW9uLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL25hdmlnYXRpb24tYi9uYXZpZ2F0aW9uLWIubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2Zvb3Rlci1hL2Zvb3Rlci1hLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9jb250ZW50L2NvbnRlbnQubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2J1dHRvbi1hL2J1dHRvbi1hLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9iYWxsb29uLWEvYmFsbG9vbi1hLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9pY29uL2ljb24ubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL3N3aXRjaC9zd2l0Y2gubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL3RvZ2dsZXIvdG9nZ2xlci5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvbW9kYWwvbW9kYWwubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2Jhc2ljc2FtcGxlL2NvcmUubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2Jhc2ljc2FtcGxlL2Fkam9pbmVkLmxlc3MiLCIuLi8uLi9zYW1wbGVzL2xlc3MvY3VzdG9tLmxlc3MiLCIuLi8uLi9zYW1wbGVzL3Rvb2xiYXJjb25maWd1cmF0b3IvbGVzcy90b29sYmFybW9kaWZpZXIubGVzcyIsIi4uLy4uL3NhbXBsZXMvdG9vbGJhcmNvbmZpZ3VyYXRvci9sZXNzL2Jhc2UubGVzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBc0RBLFFBSGlDO0VBeUNoQztJQUNDLHdCQUFBOzs7QUMxRkY7QUFBUztBQUFPO0FBQVM7QUFBWTtBQUFRO0FBQVE7QUFBUTtBQUFRO0FBQU07QUFBTTtBQUFLO0VBQ3JGLGNBQUE7O0FBR0Q7QUFBTTtFQUNMLFNBQUE7RUFDQSxVQUFBO0VBQ0Esd0JETitCLHVDQ00vQjtFQUNBLGdCQUFBO0VBQ0EsY0FBQTs7QUNIQSxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZQUFZO0VBQ1gsV0FBQTs7QUY0Q0YsUUFIaUM7RUVqQ2hDO0VBS0MsWUFBWTtFQUFaLFlBQVk7RUFBWixZQUFZO0VBQVosWUFBWTtFQUFaLFlBQVk7RUFBWixZQUFZO0VBQVosWUFBWTtFQUFaLFlBQVk7RUFBWixZQUFZO0lBSlosV0FBQTs7O0FBYUYsQ0FBQztFQ3FSQyw4QkFBQTtFQUNBLDJCQUFBO0VBQ0Esc0JBQUE7RURyUkQsZ0JBQUE7RUFDQSxpQkFBQTtFQUNBLFdBQUE7O0FBSUEsQ0FEQSxxQkFDQztBQUFELGVBQUM7QUFBUSxDQURULHFCQUNVO0FBQUQsZUFBQztFQUNULFNBQVMsRUFBVDtFQUNBLGNBQUE7RUFDQSxnQkFBQTtFQUNBLGtCQUFBO0VBQ0EsWUFBQTtFQUNBLGNBQUE7RUFDQSxRQUFBO0VBQ0EsU0FBQTs7QUFLRCxDQURBLHFCQUNDO0FBQUQsZUFBQztFQUNBLFdBQUE7O0FBSUY7RUMyUEUsOEJBQUE7RUFDQSwyQkFBQTtFQUNBLHNCQUFBO0VEM1BELGlCQUFBO0VBQ0Esa0JBQUE7O0FBS0Msc0JBREQsRUFBQyxxQkFDQztFQUNBLGVBQUE7O0FBR0Qsc0JBTEQsRUFBQyxxQkFLQztFQUNBLGdCQUFBOztBRmpCSCxRQUhpQztFRTBCOUIsc0JBREQsRUFBQyxxQkFDQztJQUNBLGdCQUFBOztFQUdELHNCQUxELEVBQUMscUJBS0M7SUFDQSxpQkFBQTs7O0FFN0VKO0VBQ0MsaUJBQUE7RUFHQSxnQkFBQTs7QUFKRCxTQU1DO0VBQ0MsZ0JBQUE7O0FKMENGLFFBSGlDO0VBNkNqQyxTSXJGQztJQUlFLGtCQUFBOzs7QUFWSCxTQU1DLGVBT0M7RUFDQyxtQkFBQTs7QUNWSDtFQUNDLFlBQUE7RUFDQSxtQkFBQTtFQUNBLGtCQUFBO0VBQ0EsT0FBQTtFQUNBLFFBQUE7RUFDQSxNQUFBO0VBQ0EsVUFBQTtFQUNBLGdCQUFBOztBTHFDRCxRQUhpQztFQTZDakM7SUs1RUUsa0JBQUE7OztBQVhGLGFBY0M7RUFDQyxnQkFBQTtFQUNBLFNBQUE7RUFDQSxnQkFBQTs7QUFqQkYsYUFjQyxHQUtDO0FBbkJGLGFBY0MsR0FLSyxHQUFHO0VBQ04scUJBQUE7O0FMeUJILFFBSGlDO0VBNkNqQyxhS3pFQztJQVVFLFdBQUE7SUFDQSx1QkFBQTtJQUNBLG1CQUFBO0lBQ0EscUJBQUE7SUFDQSxXQUFBOztFQUVBLGFBaEJGLEdBZ0JHO0VBQVMsYUFoQlosR0FnQmE7SUFDVixhQUFBOzs7QUFLRCxhQXRCRixHQXFCRSxhQUNDO0VBQ0EsZ0JBQUE7O0FMUUosUUFIaUM7RUE2Q2pDLGFLekVDLEdBcUJFLGFBQ0M7SUFJQyxnQkFBQTs7O0FBSUYsYUE5QkYsR0FxQkUsYUFTQztFQUNBLGlCQUFBOztBTEFKLFFBSGlDO0VBNkNqQyxhS3pFQyxHQXFCRSxhQVNDO0lBSUMsa0JBQUE7OztBQU1GLGFBeENGLEdBdUNDLEdBQ0c7RUFDRCxpQkFBQTs7QUF2REosYUFjQyxHQXVDQyxHQUtDO0VMeENGLGVBQUE7RUFDQSxtQkFBQTtFQUNBLGlCQUFBO0VBQ0Esb0JBQUE7RUt1Q0csaUJBQUE7RUFDQSxXQUFBO0VBQ0EsV0FBQTtFQUNBLGlCQUFBO0VBQ0EscUJBQUE7RUFDQSx5QkFBQTs7QUFFQSxhQXJESCxHQXVDQyxHQUtDLEVBU0U7RUFDQSxlQUFBO0VBQ0EsV0FBQTs7QUFRSix5QkFBQztBQUFTLHlCQUFDO0VBQ1Ysc0JBQWtCLHFyQkFBbEI7O0FDcEZGO0VBQ0MsaUJBQUE7RUFDQSxnQkFBQTtFQUNBLGlCQUFBOztBTmdERCxRQUhpQztFQTZDakM7SU12RkUsa0JBQUE7SUFDQSxnQkFBQTtJQUdBLFVBQUE7OztBQVZGLGFBYUM7RUFDQyxVQUFBO0VBQ0EsZ0JBQUE7RUFDQSxTQUFBO0VBQ0EsaUJBQUE7O0FBakJGLGFBYUMsR0FNQztBQW5CRixhQWFDLEdBTUssR0FBRztFQUNOLHFCQUFBOztBTitCSCxRQUhpQztFQTZDakMsYU1oRkM7SUFXRSxjQUFBO0lBQ0EsV0FBQTtJQUNBLHFCQUFBOzs7QU55QkgsUUFIaUM7RUE2Q2pDLGFNaEZDLEdBZ0JDO0lBRUUsa0JBQUE7OztBQUdELGFBckJGLEdBZ0JDLEdBS0c7RUFDRCxpQkFBQTs7QU5nQkosUUFIaUM7RUE2Q2pDLGFNaEZDLEdBZ0JDLEdBS0c7SUFJQSxjQUFBOzs7QUF0Q0wsYUFhQyxHQWdCQyxHQWFDO0VId1FELDhCQUFBO0VBQ0EsMkJBQUE7RUFDQSxzQkFBQTtFR3hRRSx5QkFBQTtFQUNBLHFCQUFBO0VBQ0EsYUFBQTs7QU5LSixRQUhpQztFQTZDakMsYU1oRkMsR0FnQkMsR0FhQztJQU9FLFdBQUE7SUhxT0gsd0JBQUE7SUFBaUMsb0NBQUE7SUFDakMscUJBQUE7SUFBOEIsNkJBQUE7SUFDOUIsZ0JBQUE7SUFBeUIsNEJBQUE7OztBSXhSM0I7RVB3QkMsZUFBQTtFQUNBLG9CQUFBO0VBQ0EsbUJBQUE7RUFDQSxvQkFBQTtFT3hCQSxtQkFBQTtFQUNBLHNCQUFBO0VBQ0EsZ0JBQUE7RUFDQSxjQUFBOztBQU5ELFNQNEVDO0VBQ0MsY0FBQTtFQUNBLHFCQUFBO0VBRUEsaUNBQUE7O0FBRUEsU0FORCxFQU1FO0VBQ0EsY0FBQTs7QU9uRkgsU0FRQztFQUNDLFNBQUE7RUFDQSxxQkFBQTtFQUNBLGtCQUFBOztBQ1hGO0VSd0JDLGVBQUE7RUFDQSxtQkFBQTtFQUNBLG1CQUFBO0VBQ0Esb0JBQUE7RVF6QkEsZ0JBQUE7RUFDQSxrQkFBQTtFQUNBLHFCQUFBOztBQUpELFFBU0M7RUFDQyxnQkFBQTs7QUFWRixRQWFDO0FBYkQsUUFhSztBQWJMLFFBYVM7QUFiVCxRQWFjO0FBYmQsUUFhMEIsU0FBUSxJQUFJO0FBYnRDLFFBYXdEO0VBQ3RELGlCQUFBOztBQWRGLFFBaUJDO0FBakJELFFBaUJPO0VMcVFMLDBCQUFBO0VBQWlDLG9DQUFBO0VBQ2pDLHVCQUFBO0VBQThCLDZCQUFBO0VBQzlCLGtCQUFBO0VBQXlCLDRCQUFBO0VLclF6QixnQkFBQTs7QUFuQkYsUUFzQkM7QUF0QkQsUUFzQk07QUF0Qk4sUUFzQlk7QUF0QlosUUFzQmlCO0VBQ2YsbUJBQUE7O0FBdkJGLFFBMEJDO0FBMUJELFFBMEJhO0VBQ1gsZ0JBQUE7RUFDQSw4QkFBQTtFQUNBLHFCQUFBOztBQTdCRixRQW9DQyxFUndDQTtBUTVFRCxRQW9DSSxHUndDSDtBUTVFRCxRQW9DUSxHUndDUDtBUTVFRCxRQW9DWSxXUndDWDtBUTVFRCxRQW9Dd0IsR1J3Q3ZCO0FRNUVELFFBb0M0QixHUndDM0I7QVE1RUQsUUFvQ2dDLEdSd0MvQjtBUTVFRCxRQW9Db0MsR1J3Q25DO0FRNUVELFFBb0N3QyxHUndDdkM7RUFDQyxjQUFBO0VBQ0EscUJBQUE7RUFFQSxpQ0FBQTs7QUFFQSxRUTlDRCxFUndDQSxFQU1FO0FBQUQsUVE5Q0UsR1J3Q0gsRUFNRTtBQUFELFFROUNNLEdSd0NQLEVBTUU7QUFBRCxRUTlDVSxXUndDWCxFQU1FO0FBQUQsUVE5Q3NCLEdSd0N2QixFQU1FO0FBQUQsUVE5QzBCLEdSd0MzQixFQU1FO0FBQUQsUVE5QzhCLEdSd0MvQixFQU1FO0FBQUQsUVE5Q2tDLEdSd0NuQyxFQU1FO0FBQUQsUVE5Q3NDLEdSd0N2QyxFQU1FO0VBQ0EsY0FBQTs7QVFuRkgsUUF3Q0M7QUF4Q0QsUUF3Q0s7QUF4Q0wsUUF3Q1M7QUF4Q1QsUUF3Q2E7QUF4Q2IsUUF3Q2lCO0VBQ2YsV0FBQTtFQUNBLGdCQUFBOztBQTFDRixRQXdDQyxHQUtDO0FBN0NGLFFBd0NLLEdBS0g7QUE3Q0YsUUF3Q1MsR0FLUDtBQTdDRixRQXdDYSxHQUtYO0FBN0NGLFFBd0NpQixHQUtmO0FBN0NGLFFBd0NDLEdBS087QUE3Q1IsUUF3Q0ssR0FLRztBQTdDUixRQXdDUyxHQUtEO0FBN0NSLFFBd0NhLEdBS0w7QUE3Q1IsUUF3Q2lCLEdBS1Q7RUFDTCxrQkFBQTs7QUE5Q0gsUUF3Q0MsR0FVQyxFQUFDO0FBbERILFFBd0NLLEdBVUgsRUFBQztBQWxESCxRQXdDUyxHQVVQLEVBQUM7QUFsREgsUUF3Q2EsR0FVWCxFQUFDO0FBbERILFFBd0NpQixHQVVmLEVBQUM7RUFDQSxnQkFBQTtFQUNBLHNCQUFBO0VBQ0EsVUFBQTtFQUNBLFNBQUE7O0FBR0QsUUFqQkQsR0FpQkUsTUFDQSxFQUFDO0FBREYsUUFqQkcsR0FpQkYsTUFDQSxFQUFDO0FBREYsUUFqQk8sR0FpQk4sTUFDQSxFQUFDO0FBREYsUUFqQlcsR0FpQlYsTUFDQSxFQUFDO0FBREYsUUFqQmUsR0FpQmQsTUFDQSxFQUFDO0VBQ0EsVUFBQTs7QUFJRixRQXZCRCxHQXVCRSxPQUNBO0FBREQsUUF2QkcsR0F1QkYsT0FDQTtBQURELFFBdkJPLEdBdUJOLE9BQ0E7QUFERCxRQXZCVyxHQXVCVixPQUNBO0FBREQsUUF2QmUsR0F1QmQsT0FDQTtFTDhERCwwREFBQTtFQUNBLHVEQUFBO0VBQ0EscURBQUE7RUFDQSxrREFBQTtFSy9ERSxVQUFBOztBQWxFSixRQXVFQztBQXZFRCxRQXVFUTtBQXZFUixRQXVFZ0IsU0FBUSxJQUFJO0VMK00xQiwwQkFBQTtFQUFpQyxvQ0FBQTtFQUNqQyx1QkFBQTtFQUE4Qiw2QkFBQTtFQUM5QixrQkFBQTtFQUF5Qiw0QkFBQTtFQW1CekIsdURBQUE7RUFDQSxvREFBQTtFQUNBLCtDQUFBO0VLbE9BLGFBQUE7RUFDQSxjQUFBO0VBRUEseUJBQUE7RUFDQSxrQkFBQTs7QUFFQSxRQVZELE1BVUU7QUFBRCxRQVZNLE9BVUw7QUFBRCxRQVZjLFNBQVEsSUFBSSxnQkFVekI7RUFDQSxxQkFBQTtFQUNBLFVBQUE7RUx3TkQsd0VBQUE7RUFDQSxxRUFBQTtFQUNBLGdFQUFBOztBSzdTRixRQThGQztFQUNDLDhCQUFBO0VBQ0EsZUFBQTs7QUFoR0YsUUFtR0M7RUFDQyxrQkFBQTtFQUNBLDZCUm5HMkMsd0JRbUczQztFUjdFRCxlQUFBO0VBQ0EsZUFBQTtFQUNBLG1CQUFBO0VBQ0EsbUJBQUE7O0FRM0JELFFBeUdDO0VBQ0Msa0JBQUE7O0FBMUdGLFFBNkdDO0VSckZBLGVBQUE7RUFDQSxrQkFBQTtFQUNBLG1CQUFBO0VBQ0Esb0JBQUE7RVFvRkMsbUJBQUE7O0FBL0dGLFFBa0hDO0VSMUZBLGlCQUFBO0VBQ0EsaUJBQUE7RUFDQSxvQkFBQTtFQUNBLG9CQUFBO0VReUZDLGlCQUFBOztBQXBIRixRQXVIQztFUi9GQSxlQUFBO0VBQ0EsaUJBQUE7RUFDQSxtQkFBQTtFQUNBLG1CQUFBO0VROEZDLGdCQUFBO0VBQ0Esa0JBQUE7O0FBMUhGLFFBNkhDO0VSckdBLGlCQUFBO0VBQ0EsaUJBQUE7RUFDQSxvQkFBQTtFQUNBLG9CQUFBO0VRb0dDLGdCQUFBO0VBQ0Esa0JBQUE7O0FBaElGLFFBbUlDO0VSM0dBLGlCQUFBO0VBQ0EsaUJBQUE7RUFDQSxvQkFBQTtFQUNBLG9CQUFBO0VRMEdDLGdCQUFBO0VBQ0Esa0JBQUE7O0FBdElGLFFBeUlDO0VBQ0MsU0FBQTtFQUNBLDZCQUFBO0VBQ0EsZUFBQTs7QUFJQSxRQURELE1BQ0U7RUFDQSxhQUFBO0VBQ0Esa0JBQUE7O0FBR0QsUUFORCxNQU1FO0VMaURELDBCQUFBO0VBQ0EsdUJBQUE7RUFDQSxrQkFBQTs7QUt4TUYsUUE0SkM7RVJwSUEsZUFBQTtFQUNBLGtCQUFBO0VBQ0EsbUJBQUE7RUFDQSxvQkFBQTtFUW1JQyxvQlI3SjhCLHVDUTZKOUI7RUFDQSxnQkFBQTtFTDRJQSx1REFBQTtFQUNBLG9EQUFBO0VBQ0EsK0NBQUE7O0FLN1NGLFFBdUtDLEVBQ0M7RUFDQyxzQkFBQTs7QUF6S0gsUUF1S0MsRUFLQztFQUNDLGNBQUE7O0FBN0tILFFBaUxDO0VBQ0MsVUFBQTtFQUNBLFNBQUE7RUFFQSxXQUFBO0VBQ0EsY0FBQTtFQUNBLGdCQUFBOztBQXZMRixRQTBMQztBQTFMRCxRQTBMTTtFUmxLTCxrQkFBQTtFQUNBLG1CQUFBO0VBQ0EsbUJBQUE7RUFDQSxvQkFBQTtFUWtLQyxnSkFBQTs7QUE3TEYsUUEwTEMsSUFLQztBQS9MRixRQTBMTSxLQUtKO0VBQ0MsU0FBQTs7QUFoTUgsUUFxTUMsSUFBSTtFQUNILGVBQUE7RUFDQSxjQUFBOztBQXZNRixRQTBNQztFQUNDLFdBQUE7O0FBM01GLFFBOE1DLEdBRUM7QUFoTkYsUUE4TUssR0FFSDtBQWhORixRQThNQyxHQUVLO0FBaE5OLFFBOE1LLEdBRUM7RUFDSCxnQkFBQTs7QUFqTkgsUUE4TUMsR0FNQztBQXBORixRQThNSyxHQU1IO0VSNUxELGVBQUE7RUFDQSxtQkFBQTtFQUNBLG9CQUFBO0VBQ0Esb0JBQUE7O0FRM0JELFFBME5DLFNBQVEsSUFBSTtFQUNYLFdBQUE7O0FBM05GLFFBOE5DLElBQUc7RUFDRix1QkFBQTtFQUNBLGFBQUE7RUFDQSxxQkFBQTs7O0FBR0EsUUFORCxJQUFHLEtBTUQ7RUFDQSxTQUFTLE1BQVQ7RUFDQSxpQkFBQTs7QUNqT0QsSUFERCxFQUNFO0FBQUQsSUFERSxPQUNEO0FBQUQsSUFEVSxNQUNUO0VOaVJELDBCQUFBO0VBQWlDLG9DQUFBO0VBQ2pDLHVCQUFBO0VBQThCLDZCQUFBO0VBQzlCLGtCQUFBO0VBQXlCLDRCQUFBO0VIaFExQixlQUFBO0VBQ0EsbUJBQUE7RUFDQSxtQkFBQTtFQUNBLG9CQUFBO0VTbkJFLFlBQUE7RUFDQSxpQkFBQTtFQUNBLGdCQUFBO0VBQ0EsZ0JBQUE7RUFDQSxjQUFBO0VBQ0EsbUJBQUE7RUFDQSxxQkFBQTtFQUNBLHFCQUFBO0VBQ0EsZUFBQTtFQUNBLFNBQUE7RUFDQSxzQkFBQTtFQUlBLGFBQUE7RUFHQSx1QkFBQTs7QUFFQSxJQXZCRixFQUNFLFNBc0JDO0FBQUQsSUF2QkMsT0FDRCxTQXNCQztBQUFELElBdkJTLE1BQ1QsU0FzQkM7RUFDQSxrQkFBQTs7QUFHRCxJQTNCRixFQUNFLFNBMEJDO0FBQUQsSUEzQkMsT0FDRCxTQTBCQztBQUFELElBM0JTLE1BQ1QsU0EwQkM7RUFDQSxtQkFBQTs7QUFvQkQsSUFoREYsRUFDRSxTQStDQztBQUFELElBaERDLE9BQ0QsU0ErQ0M7QUFBRCxJQWhEUyxNQUNULFNBK0NDO0VOa09GLDRCQUFBO0VBQWlDLG9DQUFBO0VBQ2pDLHlCQUFBO0VBQThCLDZCQUFBO0VBQzlCLG9CQUFBO0VBQXlCLDRCQUFBO0VNblB2QixXQUFBO0VBQ0EsVUFBQTtFQUNBLG1CQUFBO0VBQ0EsZ0JBQUE7RUFDQSxrQkFBQTtFQUNBLGtCQUFBOztBQUVBLElBeENILEVBQ0UsU0ErQ0MsaUJBUkM7QUFBRCxJQXhDQSxPQUNELFNBK0NDLGlCQVJDO0FBQUQsSUF4Q1EsTUFDVCxTQStDQyxpQkFSQztFQUNBLGtCQUFBO0VBQ0EsU0FBQTtFQUNBLFFBQUE7RUFDQSxxQkFBQTs7QVRHTCxRQUhpQztFQTZDakMsSVN6RkMsRUFDRSxTQW1EQztFVHFDSixJU3pGSSxPQUNELFNBbURDO0VUcUNKLElTekZZLE1BQ1QsU0FtREM7SU44TkYsNEJBQUE7SUFBaUMsb0NBQUE7SUFDakMseUJBQUE7SUFBOEIsNkJBQUE7SUFDOUIsb0JBQUE7SUFBeUIsNEJBQUE7SU1uUHZCLFdBQUE7SUFDQSxVQUFBO0lBQ0EsbUJBQUE7SUFDQSxnQkFBQTtJQUNBLGtCQUFBO0lBQ0Esa0JBQUE7O0VBRUEsSUF4Q0gsRUFDRSxTQW1EQywwQkFaQztFQUFELElBeENBLE9BQ0QsU0FtREMsMEJBWkM7RUFBRCxJQXhDUSxNQUNULFNBbURDLDBCQVpDO0lBQ0Esa0JBQUE7SUFDQSxTQUFBO0lBQ0EsUUFBQTtJQUNBLHFCQUFBOztFQUpELElBeENILEVBQ0UsU0FtREMsMEJBWkM7RUFBRCxJQXhDQSxPQUNELFNBbURDLDBCQVpDO0VBQUQsSUF4Q1EsTUFDVCxTQW1EQywwQkFaQztJQUNBLGtCQUFBO0lBQ0EsU0FBQTtJQUNBLFFBQUE7SUFDQSxxQkFBQTs7O0FBY0YsSUExREYsRUFDRSxTQXlEQztBQUFELElBMURDLE9BQ0QsU0F5REM7QUFBRCxJQTFEUyxNQUNULFNBeURDO0FBQ0QsSUEzREYsRUFDRSxTQTBEQztBQUFELElBM0RDLE9BQ0QsU0EwREM7QUFBRCxJQTNEUyxNQUNULFNBMERDO0VBQ0EsV0FBQTtFQUNBLG1CQUFBOztBQUdELElBaEVGLEVBQ0UsU0ErREM7QUFBRCxJQWhFQyxPQUNELFNBK0RDO0FBQUQsSUFoRVMsTUFDVCxTQStEQztFQUNBLHFCQUFBO0VBQ0EsVUFBQTtFTnFPRix5RUFBQTtFQUNBLHNFQUFBO0VBQ0EsaUVBQUE7O0FNNU5BLElBN0VELEVBNkVFO0FBQUQsSUE3RUUsT0E2RUQ7QUFBRCxJQTdFVSxNQTZFVDtFQUNBLG1CQUFBOztBQUVBLElBaEZGLEVBNkVFLGNBR0M7QUFBRCxJQWhGQyxPQTZFRCxjQUdDO0FBQUQsSUFoRlMsTUE2RVQsY0FHQztBQUNELElBakZGLEVBNkVFLGNBSUM7QUFBRCxJQWpGQyxPQTZFRCxjQUlDO0FBQUQsSUFqRlMsTUE2RVQsY0FJQztFQUNBLGNBQUE7RUFDQSxtQkFBQTs7QUFJRixJQXZGRCxFQXVGRTtBQUFELElBdkZFLE9BdUZEO0FBQUQsSUF2RlUsTUF1RlQ7QUFBRCxJQXZGRCxFSGlERyxhQXhDSCxHQWdCQyxHQWFDLEVBV0U7QUdzQ0gsSUF2RkUsT0hpREEsYUF4Q0gsR0FnQkMsR0FhQyxFQVdFO0FHc0NILElBdkZVLE1IaURSLGFBeENILEdBZ0JDLEdBYUMsRUFXRTtFR3VDRixXQUFBO0VBQ0EsbUJBQUE7O0FBRUEsSUEzRkYsRUF1RkUsb0JBSUM7QUFBRCxJQTNGQyxPQXVGRCxvQkFJQztBQUFELElBM0ZTLE1BdUZULG9CQUlDO0FBQ0QsSUE1RkYsRUF1RkUsb0JBS0M7QUFBRCxJQTVGQyxPQXVGRCxvQkFLQztBQUFELElBNUZTLE1BdUZULG9CQUtDO0FBREQsSUEzRkYsRUhpREcsYUF4Q0gsR0FnQkMsR0FhQyxFQVdFLE1HMENEO0FBQUQsSUEzRkMsT0hpREEsYUF4Q0gsR0FnQkMsR0FhQyxFQVdFLE1HMENEO0FBQUQsSUEzRlMsTUhpRFIsYUF4Q0gsR0FnQkMsR0FhQyxFQVdFLE1HMENEO0FBQ0QsSUE1RkYsRUhpREcsYUF4Q0gsR0FnQkMsR0FhQyxFQVdFLE1HMkNEO0FBQUQsSUE1RkMsT0hpREEsYUF4Q0gsR0FnQkMsR0FhQyxFQVdFLE1HMkNEO0FBQUQsSUE1RlMsTUhpRFIsYUF4Q0gsR0FnQkMsR0FhQyxFQVdFLE1HMkNEO0VBQ0EsV0FBQTtFQUNBLG1CQUFBOztBQ2hHSjtFVnNCQyxlQUFBO0VBQ0Esa0JBQUE7RUFDQSxtQkFBQTtFQUNBLG9CQUFBO0VHMlBDLDBCQUFBO0VBQWlDLG9DQUFBO0VBQ2pDLHVCQUFBO0VBQThCLDZCQUFBO0VBQzlCLGtCQUFBO0VBQXlCLDRCQUFBO0VPblIxQixnQ0FBQTtFQUVBLG1CQUFBO0VBQ0EscUJBQUE7RUFDQSxtQkFBQTtFQUNBLHdCQUFBO0VBQ0EsZ0JBQUE7RUFDQSxrQkFBQTtFQUNBLGFBQUE7RUFDQSxvQkFBQTtFQUNBLGNBQUE7O0FBRUEsVUFBQztFQUNBLGNBQUE7O0FBR0QsVUFBQztFQUNBLFNBQVMsRUFBVDtFQUNBLFFBQUE7RUFDQSxTQUFBO0VBQ0EsbUJBQUE7RUFDQSxrQkFBQTs7QUFNRCxhQUFDO0FBQUQsYUFBQztFQUNBLFVBQUE7RUFDQSw4QkFBQTtFQUNBLHlEQUFBOztBQU1ELGFBQUM7QUFBRCxhQUFDO0VBQ0EsYUFBQTtFQUNBLDhCQUFBO0VBQ0EseURBQUE7O0FBTUQsYUFBQztBQUFELGFBQUM7RUFDQSxVQUFBOztBQU1ELGFBQUM7QUFBRCxhQUFDO0VBQ0EsV0FBQTs7QUN2REYsY0FBYztBQUNkLGVBQWU7RUFDZCxTQUFTLEVBQVQ7RUFDQSxxQkFBQTtFQUNBLFdBQUE7RUFDQSxZQUFBO0VBQ0Esc0JBQUE7RUFDQSw0QkFBQTs7QUFHRCxjQUFjO0VBQ2Isa0JBQUE7O0FBR0QsZUFBZTtFQUNkLGlCQUFBOztBQUlBLGNBQUM7QUFBUyxjQUFDO0VBQ1Ysc0JBQWtCLDZjQUFsQjs7QUFLRCxtQkFBQztBQUFTLG1CQUFDO0VBQ1Ysc0JBQWtCLDZpQkFBbEI7O0FBS0QsV0FBQztBQUFTLFdBQUM7RUFDVixzQkFBa0IsNmlCQUFsQjs7QUM1QkYsSUFBSyxRQUVKO0VBQ0Msc0JBQUE7O0FBSEYsSUFBSyxRQU1KLE1BQUs7RUFDSixnQkFBQTtFQUNBLHFCQUFBOztBQVJGLElBQUssUUFXSjtFQUNDLHlCQUFBO0VBQ0EsMEJBQUE7O0FBRUEsSUFmRyxRQVdKLE1BSUU7RUFDQSxXQUFBOztBQUdELElBbkJHLFFBV0osTUFRRTtFQUNBLFlBQUE7O0FBcEJILElBQUssUUF3Qko7RUFDQyxhQUFBOztBQUlGO0VaWkMsZUFBQTtFQUNBLG1CQUFBO0VBQ0EsbUJBQUE7RUFDQSxvQkFBQTtFWVdBLGlCQUFBO0VBQ0EseUJBQUE7RUFDQSxnQkFBQTtFQUNBLHFCQUFBO0VBQ0Esc0JBQUE7RUFDQSxXQUFBO0VUMk9DLDBCQUFBO0VBQWlDLG9DQUFBO0VBQ2pDLHVCQUFBO0VBQThCLDZCQUFBO0VBQzlCLGtCQUFBO0VBQXlCLDRCQUFBO0VTM08xQixrQkFBQTs7QUFURCxPQVdDLE1BQUs7RUFDSixhQUFBOztBQVpGLE9BZUM7RUFDQyxrQkFBQTtFQUNBLFVBQUE7RUFDQSxXQUFBO0VBQ0EsZUFBQTtFQUNBLGlCQUFBOztBQUVBLE9BUEQsTUFPRTtFQUNBLDBCQUFBOztBQXZCSCxPQTJCQztFQUNDLFdBQUE7RUFDQSxzQkFBQTtFQUNBLGFBQUE7RUFDQSxjQUFBO0VBQ0EsWUFBQTtFQUNBLGdCQUFBO0VUaU5BLDRCQUFBO0VBQWlDLG9DQUFBO0VBQ2pDLHlCQUFBO0VBQThCLDZCQUFBO0VBQzlCLG9CQUFBO0VBQXlCLDRCQUFBOztBU3BQM0IsT0EyQkMsY0FTQztFQUNDLGdCQUFBO0VBQ0Esa0JBQUE7RUFDQSxjQUFBO0VBQ0EsYUFBQTtFQUNBLFlBQUE7RUFDQSxtQkFBQTtFVHdNRCw0QkFBQTtFQUFpQyxvQ0FBQTtFQUNqQyx5QkFBQTtFQUE4Qiw2QkFBQTtFQUM5QixvQkFBQTtFQUF5Qiw0QkFBQTs7QVN2TXhCLE9BbEJGLGNBU0MsU0FTRTtFQUNBLFNBQVMsRUFBVDtFQUNBLGNBQUE7RUFDQSxrQkFBQTtFQUNBLE1BQUE7RUFDQSxRQUFBO0VBQ0EsV0FBQTtFQUNBLE9BQUE7RUFFQSx5QkFBQTtFVHNLRix3Q0FBQTtFQUNBLG9DQUFBO0VBQ0EsZ0NBQUE7RUFLQSx5Q0FBQTtFQUE4QyxvQ0FBQTtFQUM5QyxxQ0FBQTtFQUEwQyw2QkFBQTtFQUMxQyxpQ0FBQTtFQUFzQyw0QkFBQTs7QVN2S3ZDLE9BQUMsTUFDQSxjQUFjLFNBQVE7RUFDckIsbUJBQUE7O0FBaEVILE9Bb0VDLE1BQUssY0FBZ0IsUUFFcEIsZ0JBQWdCO0VBQ2YsaUJBQUE7O0FBdkVILE9Bb0VDLE1BQUssY0FBZ0IsUUFTcEIsUUFBTztFQUNOLHNCQUFBO0VBQ0Esc0JBQUE7O0FBL0VILE9BbUZDLE1BQUssY0FBZ0IsUUFBUyxRQUFPO0VBQ3BDLHFCQUFBO0VBQ0EscUJBQUE7O0FDekhGO0VWazNCRSx5QkFBQTtFQUNBLHNCQUFBO0VBQ0EscUJBQUE7RUFDQSxpQkFBQTs7QVVyM0JGLFFBR0M7RUFDQyxlQUFBOztBQUpGLFFBTUM7RUFDQyxnQkFBQTs7QUFQRixRQVVDO0VBQ0MsYUFBQTs7QUFHRCxRQUFDLFVBQ0E7RUFDQyxhQUFBOztBQUZGLFFBQUMsVUFLQTtFQUNDLGdCQUFBOztBQUtIO0VBQ0MsZ0JBQUE7O0FBRUEsa0JBQUM7RUFDQSxTQUFBOztBQU1ELHNCQUFDO0FBQUQsdUJBQUM7QUFBUyxzQkFBQztBQUFELHVCQUFDO0VBQ1Ysc0JBQWtCLHlzQkFBbEI7O0FBSUEsc0JBREEsV0FDQztBQUFELHVCQURBLFdBQ0M7QUFBUyxzQkFEVixXQUNXO0FBQUQsdUJBRFYsV0FDVztFQUNWLHNCQUFrQixxdEJBQWxCOztBQU1GLHNCQUFDO0FBQ0Qsc0JBQUM7RUFDQSw2QkFBQTs7QUFLRCx1QkFBQztBQUNELHVCQUFDO0VBQ0EsZ0NBQUE7O0FDdERGO0VBQ0MsYUFBQTtFQUNBLGtCQUFBO0VBQ0EsdUJBQUE7RUFDQSxnQkFBQTtFWDRTQyw4QkFBQTtFQUNBLDJCQUFBO0VBQ0Esc0JBQUE7RVd6U0QscUJBQUE7RUFDQSxtQkFBQTtFWGd2QkMsd0NBQUE7RUFDQSxxQ0FBQTtFQUNBLG1DQUFBO0VBQ0Esb0NBQUE7RUFDQSxnQ0FBQTs7QVdqdkJELE1BQUM7RVh1UUEsNEJBQUE7RUFBaUMsb0NBQUE7RUFDakMseUJBQUE7RUFBOEIsNkJBQUE7RUFDOUIsb0JBQUE7RUFBeUIsNEJBQUE7RVd2UXpCLGVBQUE7RUFDQSxZQUFBO0VBQ0EsV0FBQTtFQUNBLGtCQUFBO0VBQ0EsU0FBQTtFQUNBLFdBQUE7RUFDQSxlQUFBO0VBQ0Esa0JBQUE7RUFDQSxpQkFBQTtFQUNBLG1CQUFBOztBQ3pCRixJQUFLO0FBQ0wsTUFBTztBQUNQLGFBQWM7QUFDZCxNQUFPO0VBQ04sZ0JBQUE7O0FBSUQ7RUFDQyxnQkFBQTs7QUFHRDtFQUNDLDZCQUFBOztBQ1hBLFNBQUM7RUFDQSx5QkFBQTtFQUNBLFdBQUE7O0FBRkQsU0FBQyxJQUlBLFNBQ0M7QUFMRixTQUFDLElBSUEsU0FDSztBQUxOLFNBQUMsSUFJQSxTQUNTO0FBTFYsU0FBQyxJQUlBLFNBQ2E7QUFMZCxTQUFDLElBSUEsU0FDaUI7RUFDZixXQUFBOztBQU5ILFNBQUMsSUFJQSxTQUtDO0VoQllGLGVBQUE7RUFDQSxtQkFBQTtFQUNBLG1CQUFBO0VBQ0Esb0JBQUE7RWdCYkcsZ0JBQUE7O0FBWEgsU0FBQyxJQUlBLFNBS0MsRUFJQztFQUNDLHFCQUFBO0VBQ0EsOEJBQUE7RUFDQSxjQUFBOztBQUVBLFNBbEJILElBSUEsU0FLQyxFQUlDLEVBS0U7RUFDQSxjQUFBOztBQW5CTCxTQUFDLElBSUEsU0FvQkM7RUFDQyxXQUFBOztBQXpCSCxTQUFDLElBSUEsU0F3QkM7RUFDQyxXQUFBOztBQTdCSCxTQUFDLElBSUEsU0E0QkM7RUFDQyxrQkFBQTtFQUNBLGNBQUE7O0FBS0gsU0FBQztFQUNBLGtCQUFBOztBQUVBLFNBSEEsT0FHQztFQUNBLFdBQUE7RUFDQSxTQUFTLEVBQVQ7RUFDQSxtQkFBQTtFQUNBLGtCQUFBO0VBQ0EsTUFBQTtFQUNBLE9BQUE7RUFDQSxRQUFBO0VBQ0EsV0FBQTs7QUN4REgsSUFBSztBQUNMLE1BQU87QUFDUCxhQUFjO0FBQ2QsTUFBTztFQUNOLGlCQUFBOztBQUdELElBQUssZ0JBQWU7RUFDbkIsZUFBQTs7QUFHRDtFQUNDLG1CQUFBO0VBQ0EsWUFBQTtFQUNBLGlCQUFBOztBQUhELE9BTUM7RUFFQyxrQkFBQTtFQUNBLFVBQUE7RUFDQSxVQUFBO0VBQ0EsbUJBQUE7RUFHQSxtQkFBQTtFQUNBLDRCQUFBOztBQUVBLE9BWEQsV0FXRTtFQUNBLHlEQUFBOztBQUtILFFBQVM7RUFDUixnQkFBQTtFQUNBLFNBQUE7RUFDQSx3QkFBQTs7QUFFQSxRQUxRLG1CQUtQO0VBQ0EsWUFBQTs7QUFLRixLQUFNO0VBQ0wsZ0JBQUE7RUFDQSxjQUFBO0VBQ0EsMEJBQUE7O0FBR0QsS0FBTSxjQUFhO0VBQ2xCLGFBQUE7O0FBSUEsUUFEUSxjQUNQO0VBQ0EsYUFBQTs7QUFGRixRQUFTLGNBS1I7RUFDQyxhQUFBOztBQUlGLFFBQ0M7RUFDQyxpQkFBQTs7QUFJRjtFQUNDLGlCQUFBOztBQURELFNBR0M7RUFDQyxXQUFBO0VBQ0EsaUJBQUE7O0FBTEYsU0FHQyxNQUlDO0VBQ0MsZ0JBQUE7O0FBRUEsU0FQRixNQUlDLFNBR0U7RUFDQSx1QkFBQTtFQUNBLFdBQUE7O0FBRkQsU0FQRixNQUlDLFNBR0UsTUFJQTtFQUNDLDBCQUFBOztBQWZMLFNBR0MsTUFpQkM7RUFDQyxXQUFBO0VBQ0EsYUFBQTs7QUFHRCxTQXRCRCxNQXNCRTtFQUNBLGdCQUFBOztBQUtIO0VBQ0MsZ0JBQUE7RUFDQSxTQUFBO0VBQ0EsVUFBQTtFQUNBLHdCQUFBOztBQUVBLHVCQUFDO0VBQ0EsWUFBQTtFQUNBLFVBQUE7O0FBS0Y7RUFDQyxpQkFBQTs7QUFERCxNQUdDLElBQUc7RUFDRixpQkFBQTs7QUFKRixNQU9DO0VBQ0MsaUJBQUE7O0FBUkYsTUFPQyxjQUdDO0VBQ0MsaUJBQUE7O0FBWEgsTUFPQyxjQU9DO0VBRUMsa0JBQUE7O0FBaEJILE1Bb0JDO0VBQ0Msa0JBQUE7RUFDQSxTQUFBO0VBRUEsU0FBQTtFQUNBLGtCQUFBOztBakJ0RkYsUUFIaUM7RUE2Q2pDLE1pQnVDQztJQVVFLFVBQUE7SUFDQSxpQkFBQTtJQUVBLFVBQUE7SUFDQSxtQkFBQTs7RUFFQSxNQWhCRixXQWdCRztJQUNBLFVBQUE7SUFDQSxXQUFBOzs7QWpCbkdKLFFBSGlDO0VBNkNqQyxNaUJ1Q0M7SUF3QkUsYUFBQTs7O0FDOUlILFFBQVM7RUFDUixvQkFBQTtFZm0yQkMseUJBQUE7RUFDQSxzQkFBQTtFQUNBLHFCQUFBO0VBQ0EsaUJBQUE7RWVwMkJELGVBQUE7O0FBSUQsb0JBQXFCO0VmNmVsQixPQUFBO0VBQVMseUJBQUE7RUFDVixvQkFBQTtFQUNBLGlCQUFBO0VBQ0EsWUFBQTs7QWU1ZUYsWUFBWTtFQUNYLGtCQUFBO0Vmd2VFLE9BQUE7RUFBUywwQkFBQTtFQUNWLGtCQUFBO0VBQ0EsZUFBQTtFQUNBLFVBQUE7O0FldGVELFlBTlcsT0FNVjtFQUNBLFNBQVMsRUFBVDtFQUNBLGNBQUE7RUFDQSxrQkFBQTtFQUNBLE1BQUE7RUFDQSxVQUFBO0VBQ0EsV0FBQTtFQUNBLE9BQUE7RWZnUEEsMEJBQUE7RUFBaUMsb0NBQUE7RUFDakMsdUJBQUE7RUFBOEIsNkJBQUE7RUFDOUIsa0JBQUE7RUFBeUIsNEJBQUE7RUFtQnpCLDRDQUFBO0VBQ0EseUNBQUE7RUFDQSxvQ0FBQTs7QWVwUkYsWUFBWSxPQWtCWDtFZmdRQyx3QkFBQTtFQUNBLHFCQUFBO0VBQ0EsZ0JBQUE7RWVoUUEscUJBQUE7O0FBcEJGLFlBQVksT0F1Qlg7QUF2QkQsWUFBWSxPQXdCWDtFQUNDLGtCQUFBO0VBQ0EsVUFBQTs7QUExQkYsWUFBWSxPQTZCWDtFZnFQQyx3QkFBQTtFQUNBLHFCQUFBO0VBQ0EsZ0JBQUE7O0FlbFBGO0VmdXpCRSx5QkFBQTtFQUNBLHNCQUFBO0VBQ0EscUJBQUE7RUFDQSxpQkFBQTs7QWV2ekJGO0VBQ0MsY0FBQTtFQUNBLG9CQUFBO0VBQ0EsZ0JBQUE7RUFDQSxnQkFBQTs7QUFHQyxRQURELE9BQU0sU0FDSjtFQUNBLGVBQUE7RUFFQSxxQkFBQTtFQUNBLGdCQUFBO0VBQ0EsVUFBQTtFQUNBLHlCQUFBOztBQUdELFFBVkQsT0FBTSxTQVVKO0VBQ0EsYUFBQTs7QUFHRCxRQWRELE9BQU0sU0FjSjtFQUNBLFdBQUE7RUFDQSxpQkFBQTs7QUFHRCxRQW5CRCxPQUFNLFNBbUJKO0VBQ0EsWUFBQTtFQUNBLGdCQUFBOztBQTNCSCxRQU1DLE9BQU0sU0F3Qkw7RUFDQyxjQUFBOztBQU1ILGdCQUFnQjtBQUNoQixnQkFBZ0I7QUFDaEIsc0JBQXNCO0VBQ3JCLGFBQUE7O0FBR0QsZ0JBQWlCO0FBQ2pCLFFBQVMsT0FBTTtBQUNmLGdCQUFpQixTQUFRLFdBQVc7RUFDbkMsYUFBQTs7QUFHRCxHQUFHO0VBQ0YsVUFBQTtFQUNBLGdCQUFBO0VBQ0EsV0FBQTtFQUNBLGtCQUFBO0VBQ0EsY0FBQTtFQUNBLHlCQUFBOztBQU5ELEdBQUcsZ0JBUUY7RUFDQyxTQUFBOztBQVRGLEdBQUcsZ0JBWUY7RUFDQyxhQUFBOztBQUdELEdBaEJFLGdCQWdCRCxjQUFlO0VBQ2Ysa0JBQUE7RWZrWUMsT0FBQTtFQUFTLHlCQUFBO0VBQ1Ysb0JBQUE7RUFDQSxpQkFBQTtFQUNBLFlBQUE7O0FldFpGLEdBQUcsZ0JBdUJGLE9BQU87RUFDTixpQkFBQTs7QUFJRCxHQTVCRSxnQkE0QkE7RUFDRCxVQUFBO0VBQ0EsU0FBQTtFQUNBLDBCQUFBO0VBQ0EsV0FBQTs7QUFFQSxHQWxDQyxnQkE0QkEsS0FNQTtFQUNBLDJCQUFBOztBQUdELEdBdENDLGdCQTRCQSxLQVVBO0VBQ0Esd0JBQUE7O0FBWEYsR0E1QkUsZ0JBNEJBLEtBZUQ7RUFDQyxVQUFBO0VBQ0EsU0FBQTs7QUFJRCxHQWpEQyxnQkE0QkEsS0FxQkM7RUFDRCxrQkFBQTs7QUFFQSxHQXBEQSxnQkE0QkEsS0FxQkMsS0FHQTtFQUNBLGlCQUFBO0VBQ0EsaUJBQUE7RUFDQSxlQUFBOztBQUdELEdBMURBLGdCQTRCQSxLQXFCQyxLQVNBO0FBQ0QsR0EzREEsZ0JBNEJBLEtBcUJDLEtBVUE7RUFDQSw2QkFBQTs7QUFHRCxHQS9EQSxnQkE0QkEsS0FxQkMsS0FjQTtFQUNBLDBCQUFBOztBQUVBLEdBbEVELGdCQTRCQSxLQXFCQyxLQWNBLHNCQUdDO0VBQ0EsZ0JBQUE7O0FBSUYsR0F2RUEsZ0JBNEJBLEtBcUJDLEtBc0JBLG1CQUFtQjtBQUNwQixHQXhFQSxnQkE0QkEsS0FxQkMsS0F1QkEsbUJBQW1CO0FBQ3BCLEdBekVBLGdCQTRCQSxLQXFCQyxLQXdCQSx1QkFBdUI7QUFDeEIsR0ExRUEsZ0JBNEJBLEtBcUJDLEtBeUJBLHVCQUF1QjtFQUN2QixnQkFBQTtFQUNBLFVBQUE7O0FBR0QsR0EvRUEsZ0JBNEJBLEtBcUJDLEtBOEJBLG1CQUFtQjtBQUNwQixHQWhGQSxnQkE0QkEsS0FxQkMsS0ErQkEsdUJBQXVCO0FBQ3hCLEdBakZBLGdCQTRCQSxLQXFCQyxLQWdDQSxtQkFBbUIsT0FBTztBQUMzQixHQWxGQSxnQkE0QkEsS0FxQkMsS0FpQ0EsdUJBQXVCLE9BQU87RUFDOUIsbUJBQUE7O0FBR0QsR0F0RkEsZ0JBNEJBLEtBcUJDLEtBcUNBLG1CQUFtQjtBQUNwQixHQXZGQSxnQkE0QkEsS0FxQkMsS0FzQ0EsdUJBQXVCO0VBQ3ZCLG1CQUFBOztBQUdELEdBM0ZBLGdCQTRCQSxLQXFCQyxLQTBDQTtFQU1BLG1CQUFBOztBQUxBLEdBNUZELGdCQTRCQSxLQXFCQyxLQTBDQSx1QkFDQztFQUNBLFNBQVMsRUFBVDtFQUNBLFdBQUE7O0FBS0QsR0FuR0QsZ0JBNEJBLEtBcUJDLEtBMENBLHVCQVFFO0VBQ0QsZ0JBQUE7O0FBSUYsR0F4R0EsZ0JBNEJBLEtBcUJDLEtBdURDO0FBQUssR0F4R1AsZ0JBNEJBLEtBcUJDLEtBdURRO0VBQ1IsbUJBQUE7RUFDQSxzQkFBQTs7QUF6REYsR0FqREMsZ0JBNEJBLEtBcUJDLEtBNkREO0VBQ0MsaUJBQUE7RUFDQSxnQkFBQTs7QUEvREYsR0FqREMsZ0JBNEJBLEtBcUJDLEtBNkRELEVBSUM7RUFDQyxtQkFBQTtFQUNBLGVBQUE7O0FBbkVILEdBakRDLGdCQTRCQSxLQXFCQyxLQTZERCxFQUlDLEtBSUM7RUFDQyxtQkFBQTtFQUNBLGlCQUFBO0VBQ0EsZUFBQTtFQUNBLGdCQUFBO0VmNkNKLDBCQUFBO0VBQWlDLG9DQUFBO0VBQ2pDLHVCQUFBO0VBQThCLDZCQUFBO0VBQzlCLGtCQUFBO0VBQXlCLDRCQUFBO0VlN0NyQixzQkFBQTtFQUNBLGNBQUE7RUFDQSxpQkFBQTtFQUNBLFlBQUE7O0FBR0MsR0FsSUosZ0JBNEJBLEtBcUJDLEtBNkRELEVBSUMsS0FJQyxPQVdFLElBQUksV0FDSDtBQUNELEdBbklKLGdCQTRCQSxLQXFCQyxLQTZERCxFQUlDLEtBSUMsT0FXRSxJQUFJLFdBRUg7RUFDQSxXQUFBO0VBQ0EseUJBQUE7RUFDQSx5QkFBQTs7QUFJRixHQTFJSCxnQkE0QkEsS0FxQkMsS0E2REQsRUFJQyxLQUlDLE9Bb0JFLEtBQUs7RUFDTCxlQUFBO0Vmd1FKLE9BQUE7RUFBUyx5QkFBQTtFQUNWLG9CQUFBO0VBQ0EsaUJBQUE7RUFDQSxZQUFBOztBZXJXQSxHQWpEQyxnQkE0QkEsS0FxQkMsS0FrR0Q7RUFDQyx5QkFBQTtFQUNBLFVBQUE7RUFDQSxXQUFBOztBQXJHRixHQWpEQyxnQkE0QkEsS0FxQkMsS0FrR0QsR0FNQztFQUNDLGtCQUFBO0VBQ0EscUJBQUE7RUFHQSxjQUFBOztBQUVBLEdBaEtGLGdCQTRCQSxLQXFCQyxLQWtHRCxHQU1DLEdBT0U7RUFDQSwwQkFBQTs7QUFFQSxHQW5LSCxnQkE0QkEsS0FxQkMsS0FrR0QsR0FNQyxHQU9FLHNCQUdDO0VBQ0EsYUFBQTs7QUFKRixHQWhLRixnQkE0QkEsS0FxQkMsS0FrR0QsR0FNQyxHQU9FLHNCQU9BO0VmQUosMEJBQUE7RUFBaUMsb0NBQUE7RUFDakMsdUJBQUE7RUFBOEIsNkJBQUE7RUFDOUIsa0JBQUE7RUFBeUIsNEJBQUE7RWVBcEIsY0FBQTs7QUFFQSxHQTNLSixnQkE0QkEsS0FxQkMsS0FrR0QsR0FNQyxHQU9FLHNCQU9BLHFCQUlFO0VBQ0EsK0JBQUE7O0FBWkgsR0FoS0YsZ0JBNEJBLEtBcUJDLEtBa0dELEdBTUMsR0FPRSxzQkFPQSxxQkFRQztFQUNDLHNCQUFBOztBQUtILEdBckxGLGdCQTRCQSxLQXFCQyxLQWtHRCxHQU1DLEdBNEJHO0FBQUssR0FyTFQsZ0JBNEJBLEtBcUJDLEtBa0dELEdBTUMsR0E0QlU7RUFDUixtQkFBQTtFQUNBLHNCQUFBOztBQXRJSixHQWpEQyxnQkE0QkEsS0FxQkMsS0FrR0QsR0FNQyxHQWtDQztFQUNDLFVBQUE7O0FBM0lKLEdBakRDLGdCQTRCQSxLQXFCQyxLQWtHRCxHQU1DLEdBa0NDLEdBSUM7RUFDQyxVQUFBO0VBQ0EscUJBQUE7RUFDQSxlQUFBO0VBQ0EscUJBQUE7O0FBbEpMLEdBakRDLGdCQTRCQSxLQXFCQyxLQWtHRCxHQU1DLEdBa0NDLEdBSUMsR0FPQztFQUNDLGVBQUE7RUFDQSxtQkFBQTs7QUF2Sk4sR0FqREMsZ0JBNEJBLEtBcUJDLEtBa0dELEdBTUMsR0FrQ0MsR0FJQyxHQVlDO0FBMUpMLEdBakRDLGdCQTRCQSxLQXFCQyxLQWtHRCxHQU1DLEdBa0NDLEdBSUMsR0FhQztFQUNDLGVBQUE7RUFDQSxTQUFBO0VBQ0Esc0JBQUE7RUFDQSxzQkFBQTtFQ2xTUCxrQkFBQTtFQUNBLG1CQUFBO0VBRUEsb0JBQUE7RUFDQSxvQkFBQTs7QUR3U0EsR0ExTkUsZ0JBME5BO0VBQ0QsZ0JBQUE7O0FBSUQsR0EvTkUsZ0JBK05EO0VBQ0EsWUFBQTtFQUNBLFlBQUE7RUFDQSxnQkFBQTtFQUNBLGdCQUFBO0VBQ0Esa0JBQUE7O0FBTEQsR0EvTkUsZ0JBK05ELE1BT0E7RUN4VEQsa0JBQUE7RUFDQSxrQkFBQTtFQUVBLG9CQUFBO0VBQ0Esb0JBQUE7RURzVEUscUJBQUE7RUFDQSxtQkFBQTtFQUNBLDZCQUFBO0VBQ0EsYUFBQTtFQUNBLG9CQUFBOztBQWJGLEdBL05FLGdCQStORCxNQWdCQTtFQUVDLG9CQUFBO0VBQ0EsZ0JBQUE7O0FBbkJGLEdBL05FLGdCQStORCxNQWdCQSxHQUtDO0VBQ0MsaUJBQUE7RUFDQSxTQUFBO0VBQ0EscUJBQUE7O0FBR0QsR0ExUEEsZ0JBK05ELE1BZ0JBLEdBV0c7RUFDRCxrQkFBQTs7QUE1QkgsR0EvTkUsZ0JBK05ELE1BZ0JBLEdBZUM7RUFDQyxXQUFBO0VBQ0EsVUFBQTtFQUNBLFdBQUE7RUFDQSxpQkFBQTtFQUNBLDBCQUFBO0VBQ0EsbUJBQUE7RUFDQSxtQkFBQTtFZmxFRiw4QkFBQTtFQUNBLDJCQUFBO0VBQ0Esc0JBQUE7O0FlMEJELEdBL05FLGdCQStORCxNQWdCQSxHQWVDLEdBVUM7RUFDQyxnQkFBQTtFQUNBLFlBQUE7RUFDQSxzQkFBQTs7QUE1Q0osR0EvTkUsZ0JBK05ELE1BZ0JBLEdBZ0NDO0VBQ0MsaUJBQUE7RUFDQSxZQUFBO0VBQ0Esb0JBQUE7O0FBbkRILEdBL05FLGdCQStORCxNQWdCQSxHQWdDQyxHQUtDO0VBQ0Msa0JBQUE7O0FBR0QsR0F4UkQsZ0JBK05ELE1BZ0JBLEdBZ0NDLEdBU0U7RUFDQSxTQUFTLE9BQVQ7RUFDQSxjQUFBO0VBQ0EsV0FBQTtFQUNBLFlBQUE7RUFDQSxTQUFBO0VBQ0EsUUFBQTs7QUFPTDtBQUNBLGdCQUFpQixTQUFRO0FBQ3pCO0VmaElFLDBCQUFBO0VBQWlDLG9DQUFBO0VBQ2pDLHVCQUFBO0VBQThCLDZCQUFBO0VBQzlCLGtCQUFBO0VBQXlCLDRCQUFBO0VlZ0kxQixzQkFBQTtFQzNYQSxrQkFBQTtFQUNBLG1CQUFBO0VBRUEsb0JBQUE7RUFDQSxvQkFBQTs7QUQyWEQsZ0JBQWlCLFNBQVE7QUFDekIsV0FBWTtBQUNaO0VDallDLGtCQUFBO0VBQ0EsbUJBQUE7RUFFQSxvQkFBQTtFQUNBLG9CQUFBO0VEK1hBLGdKQUFBOztBQUdELFdBQVk7RUFDWCxZQUFBO0VBQ0EsVUFBQTtFQUNBLFNBQUE7O0FBR0QsZ0JBQWlCLFNBQVE7RWZ2SHZCLDhCQUFBO0VBQ0EsMkJBQUE7RUFDQSxzQkFBQTtFZXVIRCxjQUFBO0VBQ0EsYUFBQTtFQUNBLFdBQUE7RUFDQSxpQkFBQTtFQUNBLFNBQUE7RUFDQSxZQUFBO0VBQ0EsYUFBQTtFQUNBLGdCQUFBO0VBQ0EsV0FBQTtFQUNBLGdCQUFBO0VBQ0EsaUJBQUE7RUFDQSxjQUFBOztBQUdELGlCQUFpQjtFQUNoQixVQUFBO0VBQ0EsY0FBQTtFQzlaQSxlQUFBO0VBQ0EsbUJBQUE7RUFFQSxtQkFBQTtFQUNBLG9CQUFBO0VEa2FBLGdKQUFBOztBQVZELGlCQUFpQixpQkFJaEI7RUFDQyxjQUFBO0VBQ0EsbUJBQUE7O0FBTUQsaUJBWmdCLGlCQVlkLEtBQUk7RUFDTCxtQkFBQTs7O0FBS0Y7RUFDQyxvQkFBQTs7QUFERCx1QkFHQyxTQUFTO0VBQ1IsbUJBQUE7RUFDQSxpQkFBQTs7QUFMRix1QkFRQztFQUVDLFlBQUE7RUFHQSxnQkFBQTs7QUFJRjtFQUNDLGVBQUE7RUFDQSxNQUFBO0VBQ0EsV0FBQTtFQUNBLFdBQUE7O0FBSkQsZ0JBTUM7RUFDQyxpQkFBQTs7QUFQRixnQkFNQyxrQkFHQztFQUNDLGdCQUFBOztBQVZILGdCQU1DLGtCQUdDLE9BR0M7RUFDQyxnQkFBQTs7QUFPSjtFQUNDLGtCQUFBO0VBQ0EsVUFBQTtFQUNBLFVBQUE7O0FBRUEsS0FBQztFQUNBLGFBQUEifQ== */ +/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2dsb2JhbC9nbG9iYWwubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2NvcmUvY29yZS5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvZ3JpZC9ncmlkLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvbGVzc2hhdC9idWlsZC9sZXNzaGF0Lmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9oZWFkZXItYS9oZWFkZXItYS5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvbmF2aWdhdGlvbi1hL25hdmlnYXRpb24tYS5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvbmF2aWdhdGlvbi1iL25hdmlnYXRpb24tYi5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvZm9vdGVyLWEvZm9vdGVyLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2NvbnRlbnQvY29udGVudC5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvYnV0dG9uLWEvYnV0dG9uLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2JhbGxvb24tYS9iYWxsb29uLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2ljb24vaWNvbi5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvc3dpdGNoL3N3aXRjaC5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvdG9nZ2xlci90b2dnbGVyLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9tb2RhbC9tb2RhbC5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvYmFzaWNzYW1wbGUvY29yZS5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvYmFzaWNzYW1wbGUvYWRqb2luZWQubGVzcyIsIi4uLy4uL3NhbXBsZXMvbGVzcy9jdXN0b20ubGVzcyIsIi4uLy4uL3NhbXBsZXMvdG9vbGJhcmNvbmZpZ3VyYXRvci9sZXNzL3Rvb2xiYXJtb2RpZmllci5sZXNzIiwiLi4vLi4vc2FtcGxlcy90b29sYmFyY29uZmlndXJhdG9yL2xlc3MvYmFzZS5sZXNzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFtREMsUUFBZ0M7RUF5Q2hDO0lBQ0Msd0JBQUE7OztBQzFGRjtBQUFTO0FBQU87QUFBUztBQUFZO0FBQVE7QUFBUTtBQUFRO0FBQVE7QUFBTTtBQUFNO0FBQUs7RUFDckYsY0FBQTs7QUFHRDtBQUFNO0VBQ0wsU0FBQTtFQUNBLFVBQUE7RUFDQSx3QkROK0IsdUNDTS9CO0VBQ0EsZ0JBQUE7RUFDQSxjQUFBOztBQ0hBLFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxXQUFBOztBRnlDRCxRQUFnQztFRWpDaEM7RUFLQyxZQUFZO0VBQVosWUFBWTtFQUFaLFlBQVk7RUFBWixZQUFZO0VBQVosWUFBWTtFQUFaLFlBQVk7RUFBWixZQUFZO0VBQVosWUFBWTtFQUFaLFlBQVk7SUFKWixXQUFBOzs7QUFhRixDQUFDO0VDcVJDLDhCQUFBO0VBQ0EsMkJBQUE7RUFDQSxzQkFBQTtFRHJSRCxnQkFBQTtFQUNBLGlCQUFBO0VBQ0EsV0FBQTs7QUFJQSxDQURBLHFCQUNDO0FBQUQsZUFBQztBQUFRLENBRFQscUJBQ1U7QUFBRCxlQUFDO0VBQ1QsU0FBUyxFQUFUO0VBQ0EsY0FBQTtFQUNBLGdCQUFBO0VBQ0Esa0JBQUE7RUFDQSxZQUFBO0VBQ0EsY0FBQTtFQUNBLFFBQUE7RUFDQSxTQUFBOztBQUtELENBREEscUJBQ0M7QUFBRCxlQUFDO0VBQ0EsV0FBQTs7QUFJRjtFQzJQRSw4QkFBQTtFQUNBLDJCQUFBO0VBQ0Esc0JBQUE7RUQzUEQsaUJBQUE7RUFDQSxrQkFBQTs7QUFLQyxzQkFERCxFQUFDLHFCQUNDO0VBQ0EsZUFBQTs7QUFHRCxzQkFMRCxFQUFDLHFCQUtDO0VBQ0EsZ0JBQUE7O0FGcEJGLFFBQWdDO0VFMEI5QixzQkFERCxFQUFDLHFCQUNDO0lBQ0EsZ0JBQUE7O0VBR0Qsc0JBTEQsRUFBQyxxQkFLQztJQUNBLGlCQUFBOzs7QUU3RUo7RUFDQyxpQkFBQTtFQUdBLGdCQUFBOztBQUpELFNBTUM7RUFDQyxnQkFBQTs7QUp1Q0QsUUFBZ0M7RUE2Q2pDLFNJckZDO0lBSUUsa0JBQUE7OztBQVZILFNBTUMsZUFPQztFQUNDLG1CQUFBOztBQ1ZIO0VBQ0MsWUFBQTtFQUNBLG1CQUFBO0VBQ0Esa0JBQUE7RUFDQSxPQUFBO0VBQ0EsUUFBQTtFQUNBLE1BQUE7RUFDQSxVQUFBO0VBQ0EsZ0JBQUE7O0FMa0NBLFFBQWdDO0VBNkNqQztJSzVFRSxrQkFBQTs7O0FBWEYsYUFjQztFQUNDLGdCQUFBO0VBQ0EsU0FBQTtFQUNBLGdCQUFBOztBQWpCRixhQWNDLEdBS0M7QUFuQkYsYUFjQyxHQUtLLEdBQUc7RUFDTixxQkFBQTs7QUxzQkYsUUFBZ0M7RUE2Q2pDLGFLekVDO0lBVUUsV0FBQTtJQUNBLHVCQUFBO0lBQ0EsbUJBQUE7SUFDQSxxQkFBQTtJQUNBLFdBQUE7O0VBRUEsYUFoQkYsR0FnQkc7RUFBUyxhQWhCWixHQWdCYTtJQUNWLGFBQUE7OztBQUtELGFBdEJGLEdBcUJFLGFBQ0M7RUFDQSxnQkFBQTs7QUxLSCxRQUFnQztFQTZDakMsYUt6RUMsR0FxQkUsYUFDQztJQUlDLGdCQUFBOzs7QUFJRixhQTlCRixHQXFCRSxhQVNDO0VBQ0EsaUJBQUE7O0FMSEgsUUFBZ0M7RUE2Q2pDLGFLekVDLEdBcUJFLGFBU0M7SUFJQyxrQkFBQTs7O0FBTUYsYUF4Q0YsR0F1Q0MsR0FDRztFQUNELGlCQUFBOztBQXZESixhQWNDLEdBdUNDLEdBS0M7RUx4Q0YsZUFBQTtFQUNBLG1CQUFBO0VBQ0EsaUJBQUE7RUFDQSxvQkFBQTtFS3VDRyxpQkFBQTtFQUNBLFdBQUE7RUFDQSxXQUFBO0VBQ0EsaUJBQUE7RUFDQSxxQkFBQTtFQUNBLHlCQUFBOztBQUVBLGFBckRILEdBdUNDLEdBS0MsRUFTRTtFQUNBLGVBQUE7RUFDQSxXQUFBOztBQVFKLHlCQUFDO0FBQVMseUJBQUM7RUFDVixzQkFBa0IscXJCQUFsQjs7QUNwRkY7RUFDQyxpQkFBQTtFQUNBLGdCQUFBO0VBQ0EsaUJBQUE7O0FONkNBLFFBQWdDO0VBNkNqQztJTXZGRSxrQkFBQTtJQUNBLGdCQUFBO0lBR0EsVUFBQTs7O0FBVkYsYUFhQztFQUNDLFVBQUE7RUFDQSxnQkFBQTtFQUNBLFNBQUE7RUFDQSxpQkFBQTs7QUFqQkYsYUFhQyxHQU1DO0FBbkJGLGFBYUMsR0FNSyxHQUFHO0VBQ04scUJBQUE7O0FONEJGLFFBQWdDO0VBNkNqQyxhTWhGQztJQVdFLGNBQUE7SUFDQSxXQUFBO0lBQ0EscUJBQUE7OztBTnNCRixRQUFnQztFQTZDakMsYU1oRkMsR0FnQkM7SUFFRSxrQkFBQTs7O0FBR0QsYUFyQkYsR0FnQkMsR0FLRztFQUNELGlCQUFBOztBTmFILFFBQWdDO0VBNkNqQyxhTWhGQyxHQWdCQyxHQUtHO0lBSUEsY0FBQTs7O0FBdENMLGFBYUMsR0FnQkMsR0FhQztFSHdRRCw4QkFBQTtFQUNBLDJCQUFBO0VBQ0Esc0JBQUE7RUd4UUUseUJBQUE7RUFDQSxxQkFBQTtFQUNBLGFBQUE7O0FORUgsUUFBZ0M7RUE2Q2pDLGFNaEZDLEdBZ0JDLEdBYUM7SUFPRSxXQUFBO0lIcU9ILHdCQUFBO0lBQWlDLG9DQUFBO0lBQ2pDLHFCQUFBO0lBQThCLDZCQUFBO0lBQzlCLGdCQUFBO0lBQXlCLDRCQUFBOzs7QUl4UjNCO0VQd0JDLGVBQUE7RUFDQSxvQkFBQTtFQUNBLG1CQUFBO0VBQ0Esb0JBQUE7RU94QkEsbUJBQUE7RUFDQSxzQkFBQTtFQUNBLGdCQUFBO0VBQ0EsY0FBQTs7QUFORCxTUDRFQztFQUNDLGNBQUE7RUFDQSxxQkFBQTtFQUVBLGlDQUFBOztBQUVBLFNBTkQsRUFNRTtFQUNBLGNBQUE7O0FPbkZILFNBUUM7RUFDQyxTQUFBO0VBQ0EscUJBQUE7RUFDQSxrQkFBQTs7QUNYRjtFUndCQyxlQUFBO0VBQ0EsbUJBQUE7RUFDQSxtQkFBQTtFQUNBLG9CQUFBO0VRekJBLGdCQUFBO0VBQ0Esa0JBQUE7RUFDQSxxQkFBQTs7QUFKRCxRQVNDO0VBQ0MsZ0JBQUE7O0FBVkYsUUFhQztBQWJELFFBYUs7QUFiTCxRQWFTO0FBYlQsUUFhYztBQWJkLFFBYTBCLFNBQVEsSUFBSTtBQWJ0QyxRQWF3RDtFQUN0RCxpQkFBQTs7QUFkRixRQWlCQztBQWpCRCxRQWlCTztFTHFRTCwwQkFBQTtFQUFpQyxvQ0FBQTtFQUNqQyx1QkFBQTtFQUE4Qiw2QkFBQTtFQUM5QixrQkFBQTtFQUF5Qiw0QkFBQTtFS3JRekIsZ0JBQUE7O0FBbkJGLFFBc0JDO0FBdEJELFFBc0JNO0FBdEJOLFFBc0JZO0FBdEJaLFFBc0JpQjtFQUNmLG1CQUFBOztBQXZCRixRQTBCQztBQTFCRCxRQTBCYTtFQUNYLGdCQUFBO0VBQ0EsOEJBQUE7RUFDQSxxQkFBQTs7QUE3QkYsUUFvQ0MsRVJ3Q0E7QVE1RUQsUUFvQ0ksR1J3Q0g7QVE1RUQsUUFvQ1EsR1J3Q1A7QVE1RUQsUUFvQ1ksV1J3Q1g7QVE1RUQsUUFvQ3dCLEdSd0N2QjtBUTVFRCxRQW9DNEIsR1J3QzNCO0FRNUVELFFBb0NnQyxHUndDL0I7QVE1RUQsUUFvQ29DLEdSd0NuQztBUTVFRCxRQW9Dd0MsR1J3Q3ZDO0VBQ0MsY0FBQTtFQUNBLHFCQUFBO0VBRUEsaUNBQUE7O0FBRUEsUVE5Q0QsRVJ3Q0EsRUFNRTtBQUFELFFROUNFLEdSd0NILEVBTUU7QUFBRCxRUTlDTSxHUndDUCxFQU1FO0FBQUQsUVE5Q1UsV1J3Q1gsRUFNRTtBQUFELFFROUNzQixHUndDdkIsRUFNRTtBQUFELFFROUMwQixHUndDM0IsRUFNRTtBQUFELFFROUM4QixHUndDL0IsRUFNRTtBQUFELFFROUNrQyxHUndDbkMsRUFNRTtBQUFELFFROUNzQyxHUndDdkMsRUFNRTtFQUNBLGNBQUE7O0FRbkZILFFBd0NDO0FBeENELFFBd0NLO0FBeENMLFFBd0NTO0FBeENULFFBd0NhO0FBeENiLFFBd0NpQjtFQUNmLFdBQUE7RUFDQSxnQkFBQTs7QUExQ0YsUUF3Q0MsR0FLQztBQTdDRixRQXdDSyxHQUtIO0FBN0NGLFFBd0NTLEdBS1A7QUE3Q0YsUUF3Q2EsR0FLWDtBQTdDRixRQXdDaUIsR0FLZjtBQTdDRixRQXdDQyxHQUtPO0FBN0NSLFFBd0NLLEdBS0c7QUE3Q1IsUUF3Q1MsR0FLRDtBQTdDUixRQXdDYSxHQUtMO0FBN0NSLFFBd0NpQixHQUtUO0VBQ0wsa0JBQUE7O0FBOUNILFFBd0NDLEdBVUMsRUFBQztBQWxESCxRQXdDSyxHQVVILEVBQUM7QUFsREgsUUF3Q1MsR0FVUCxFQUFDO0FBbERILFFBd0NhLEdBVVgsRUFBQztBQWxESCxRQXdDaUIsR0FVZixFQUFDO0VBQ0EsZ0JBQUE7RUFDQSxzQkFBQTtFQUNBLFVBQUE7RUFDQSxTQUFBOztBQUdELFFBakJELEdBaUJFLE1BQ0EsRUFBQztBQURGLFFBakJHLEdBaUJGLE1BQ0EsRUFBQztBQURGLFFBakJPLEdBaUJOLE1BQ0EsRUFBQztBQURGLFFBakJXLEdBaUJWLE1BQ0EsRUFBQztBQURGLFFBakJlLEdBaUJkLE1BQ0EsRUFBQztFQUNBLFVBQUE7O0FBSUYsUUF2QkQsR0F1QkUsT0FDQTtBQURELFFBdkJHLEdBdUJGLE9BQ0E7QUFERCxRQXZCTyxHQXVCTixPQUNBO0FBREQsUUF2QlcsR0F1QlYsT0FDQTtBQURELFFBdkJlLEdBdUJkLE9BQ0E7RUw4REQsMERBQUE7RUFDQSx1REFBQTtFQUNBLHFEQUFBO0VBQ0Esa0RBQUE7RUsvREUsVUFBQTs7QUFsRUosUUF1RUM7QUF2RUQsUUF1RVE7QUF2RVIsUUF1RWdCLFNBQVEsSUFBSTtFTCtNMUIsMEJBQUE7RUFBaUMsb0NBQUE7RUFDakMsdUJBQUE7RUFBOEIsNkJBQUE7RUFDOUIsa0JBQUE7RUFBeUIsNEJBQUE7RUFtQnpCLHVEQUFBO0VBQ0Esb0RBQUE7RUFDQSwrQ0FBQTtFS2xPQSxhQUFBO0VBQ0EsY0FBQTtFQUVBLHlCQUFBO0VBQ0Esa0JBQUE7O0FBRUEsUUFWRCxNQVVFO0FBQUQsUUFWTSxPQVVMO0FBQUQsUUFWYyxTQUFRLElBQUksZ0JBVXpCO0VBQ0EscUJBQUE7RUFDQSxVQUFBO0VMd05ELHdFQUFBO0VBQ0EscUVBQUE7RUFDQSxnRUFBQTs7QUs3U0YsUUE4RkM7RUFDQyw4QkFBQTtFQUNBLGVBQUE7O0FBaEdGLFFBbUdDO0VBQ0Msa0JBQUE7RUFDQSw2QlJuRzJDLHdCUW1HM0M7RVI3RUQsZUFBQTtFQUNBLGVBQUE7RUFDQSxtQkFBQTtFQUNBLG1CQUFBOztBUTNCRCxRQXlHQztFQUNDLGtCQUFBOztBQTFHRixRQTZHQztFUnJGQSxlQUFBO0VBQ0Esa0JBQUE7RUFDQSxtQkFBQTtFQUNBLG9CQUFBO0VRb0ZDLG1CQUFBOztBQS9HRixRQWtIQztFUjFGQSxpQkFBQTtFQUNBLGlCQUFBO0VBQ0Esb0JBQUE7RUFDQSxvQkFBQTtFUXlGQyxpQkFBQTs7QUFwSEYsUUF1SEM7RVIvRkEsZUFBQTtFQUNBLGlCQUFBO0VBQ0EsbUJBQUE7RUFDQSxtQkFBQTtFUThGQyxnQkFBQTtFQUNBLGtCQUFBOztBQTFIRixRQTZIQztFUnJHQSxpQkFBQTtFQUNBLGlCQUFBO0VBQ0Esb0JBQUE7RUFDQSxvQkFBQTtFUW9HQyxnQkFBQTtFQUNBLGtCQUFBOztBQWhJRixRQW1JQztFUjNHQSxpQkFBQTtFQUNBLGlCQUFBO0VBQ0Esb0JBQUE7RUFDQSxvQkFBQTtFUTBHQyxnQkFBQTtFQUNBLGtCQUFBOztBQXRJRixRQXlJQztFQUNDLFNBQUE7RUFDQSw2QkFBQTtFQUNBLGVBQUE7O0FBSUEsUUFERCxNQUNFO0VBQ0EsYUFBQTtFQUNBLGtCQUFBOztBQUdELFFBTkQsTUFNRTtFTGlERCwwQkFBQTtFQUNBLHVCQUFBO0VBQ0Esa0JBQUE7O0FLeE1GLFFBNEpDO0VScElBLGVBQUE7RUFDQSxrQkFBQTtFQUNBLG1CQUFBO0VBQ0Esb0JBQUE7RVFtSUMsb0JSN0o4Qix1Q1E2SjlCO0VBQ0EsZ0JBQUE7RUw0SUEsdURBQUE7RUFDQSxvREFBQTtFQUNBLCtDQUFBOztBSzdTRixRQXVLQyxFQUNDO0VBQ0Msc0JBQUE7O0FBektILFFBdUtDLEVBS0M7RUFDQyxjQUFBOztBQTdLSCxRQWlMQztFQUNDLFVBQUE7RUFDQSxTQUFBO0VBRUEsV0FBQTtFQUNBLGNBQUE7RUFDQSxnQkFBQTs7QUF2TEYsUUEwTEM7QUExTEQsUUEwTE07RVJsS0wsa0JBQUE7RUFDQSxtQkFBQTtFQUNBLG1CQUFBO0VBQ0Esb0JBQUE7RVFrS0MsZ0pBQUE7O0FBN0xGLFFBMExDLElBS0M7QUEvTEYsUUEwTE0sS0FLSjtFQUNDLFNBQUE7O0FBaE1ILFFBcU1DLElBQUk7RUFDSCxlQUFBO0VBQ0EsY0FBQTs7QUF2TUYsUUEwTUM7RUFDQyxXQUFBOztBQTNNRixRQThNQyxHQUVDO0FBaE5GLFFBOE1LLEdBRUg7QUFoTkYsUUE4TUMsR0FFSztBQWhOTixRQThNSyxHQUVDO0VBQ0gsZ0JBQUE7O0FBak5ILFFBOE1DLEdBTUM7QUFwTkYsUUE4TUssR0FNSDtFUjVMRCxlQUFBO0VBQ0EsbUJBQUE7RUFDQSxvQkFBQTtFQUNBLG9CQUFBOztBUTNCRCxRQTBOQyxTQUFRLElBQUk7RUFDWCxXQUFBOztBQTNORixRQThOQyxJQUFHO0VBQ0YsdUJBQUE7RUFDQSxhQUFBO0VBQ0EscUJBQUE7OztBQUdBLFFBTkQsSUFBRyxLQU1EO0VBQ0EsU0FBUyxNQUFUO0VBQ0EsaUJBQUE7O0FDak9ELElBREQsRUFDRTtBQUFELElBREUsT0FDRDtBQUFELElBRFUsTUFDVDtFTmlSRCwwQkFBQTtFQUFpQyxvQ0FBQTtFQUNqQyx1QkFBQTtFQUE4Qiw2QkFBQTtFQUM5QixrQkFBQTtFQUF5Qiw0QkFBQTtFSGhRMUIsZUFBQTtFQUNBLG1CQUFBO0VBQ0EsbUJBQUE7RUFDQSxvQkFBQTtFU25CRSxZQUFBO0VBQ0EsaUJBQUE7RUFDQSxnQkFBQTtFQUNBLGdCQUFBO0VBQ0EsY0FBQTtFQUNBLG1CQUFBO0VBQ0EscUJBQUE7RUFDQSxxQkFBQTtFQUNBLGVBQUE7RUFDQSxTQUFBO0VBQ0Esc0JBQUE7RUFJQSxhQUFBO0VBR0EsdUJBQUE7O0FBRUEsSUF2QkYsRUFDRSxTQXNCQztBQUFELElBdkJDLE9BQ0QsU0FzQkM7QUFBRCxJQXZCUyxNQUNULFNBc0JDO0VBQ0Esa0JBQUE7O0FBR0QsSUEzQkYsRUFDRSxTQTBCQztBQUFELElBM0JDLE9BQ0QsU0EwQkM7QUFBRCxJQTNCUyxNQUNULFNBMEJDO0VBQ0EsbUJBQUE7O0FBb0JELElBaERGLEVBQ0UsU0ErQ0M7QUFBRCxJQWhEQyxPQUNELFNBK0NDO0FBQUQsSUFoRFMsTUFDVCxTQStDQztFTmtPRiw0QkFBQTtFQUFpQyxvQ0FBQTtFQUNqQyx5QkFBQTtFQUE4Qiw2QkFBQTtFQUM5QixvQkFBQTtFQUF5Qiw0QkFBQTtFTW5QdkIsV0FBQTtFQUNBLFVBQUE7RUFDQSxtQkFBQTtFQUNBLGdCQUFBO0VBQ0Esa0JBQUE7RUFDQSxrQkFBQTs7QUFFQSxJQXhDSCxFQUNFLFNBK0NDLGlCQVJDO0FBQUQsSUF4Q0EsT0FDRCxTQStDQyxpQkFSQztBQUFELElBeENRLE1BQ1QsU0ErQ0MsaUJBUkM7RUFDQSxrQkFBQTtFQUNBLFNBQUE7RUFDQSxRQUFBO0VBQ0EscUJBQUE7O0FUQUosUUFBZ0M7RUE2Q2pDLElTekZDLEVBQ0UsU0FtREM7RVRxQ0osSVN6RkksT0FDRCxTQW1EQztFVHFDSixJU3pGWSxNQUNULFNBbURDO0lOOE5GLDRCQUFBO0lBQWlDLG9DQUFBO0lBQ2pDLHlCQUFBO0lBQThCLDZCQUFBO0lBQzlCLG9CQUFBO0lBQXlCLDRCQUFBO0lNblB2QixXQUFBO0lBQ0EsVUFBQTtJQUNBLG1CQUFBO0lBQ0EsZ0JBQUE7SUFDQSxrQkFBQTtJQUNBLGtCQUFBOztFQUVBLElBeENILEVBQ0UsU0FtREMsMEJBWkM7RUFBRCxJQXhDQSxPQUNELFNBbURDLDBCQVpDO0VBQUQsSUF4Q1EsTUFDVCxTQW1EQywwQkFaQztJQUNBLGtCQUFBO0lBQ0EsU0FBQTtJQUNBLFFBQUE7SUFDQSxxQkFBQTs7RUFKRCxJQXhDSCxFQUNFLFNBbURDLDBCQVpDO0VBQUQsSUF4Q0EsT0FDRCxTQW1EQywwQkFaQztFQUFELElBeENRLE1BQ1QsU0FtREMsMEJBWkM7SUFDQSxrQkFBQTtJQUNBLFNBQUE7SUFDQSxRQUFBO0lBQ0EscUJBQUE7OztBQWNGLElBMURGLEVBQ0UsU0F5REM7QUFBRCxJQTFEQyxPQUNELFNBeURDO0FBQUQsSUExRFMsTUFDVCxTQXlEQztBQUNELElBM0RGLEVBQ0UsU0EwREM7QUFBRCxJQTNEQyxPQUNELFNBMERDO0FBQUQsSUEzRFMsTUFDVCxTQTBEQztFQUNBLFdBQUE7RUFDQSxtQkFBQTs7QUFHRCxJQWhFRixFQUNFLFNBK0RDO0FBQUQsSUFoRUMsT0FDRCxTQStEQztBQUFELElBaEVTLE1BQ1QsU0ErREM7RUFDQSxxQkFBQTtFQUNBLFVBQUE7RU5xT0YseUVBQUE7RUFDQSxzRUFBQTtFQUNBLGlFQUFBOztBTTVOQSxJQTdFRCxFQTZFRTtBQUFELElBN0VFLE9BNkVEO0FBQUQsSUE3RVUsTUE2RVQ7RUFDQSxtQkFBQTs7QUFFQSxJQWhGRixFQTZFRSxjQUdDO0FBQUQsSUFoRkMsT0E2RUQsY0FHQztBQUFELElBaEZTLE1BNkVULGNBR0M7QUFDRCxJQWpGRixFQTZFRSxjQUlDO0FBQUQsSUFqRkMsT0E2RUQsY0FJQztBQUFELElBakZTLE1BNkVULGNBSUM7RUFDQSxjQUFBO0VBQ0EsbUJBQUE7O0FBSUYsSUF2RkQsRUF1RkU7QUFBRCxJQXZGRSxPQXVGRDtBQUFELElBdkZVLE1BdUZUO0FBQUQsSUF2RkQsRUhpREcsYUF4Q0gsR0FnQkMsR0FhQyxFQVdFO0FHc0NILElBdkZFLE9IaURBLGFBeENILEdBZ0JDLEdBYUMsRUFXRTtBR3NDSCxJQXZGVSxNSGlEUixhQXhDSCxHQWdCQyxHQWFDLEVBV0U7RUd1Q0YsV0FBQTtFQUNBLG1CQUFBOztBQUVBLElBM0ZGLEVBdUZFLG9CQUlDO0FBQUQsSUEzRkMsT0F1RkQsb0JBSUM7QUFBRCxJQTNGUyxNQXVGVCxvQkFJQztBQUNELElBNUZGLEVBdUZFLG9CQUtDO0FBQUQsSUE1RkMsT0F1RkQsb0JBS0M7QUFBRCxJQTVGUyxNQXVGVCxvQkFLQztBQURELElBM0ZGLEVIaURHLGFBeENILEdBZ0JDLEdBYUMsRUFXRSxNRzBDRDtBQUFELElBM0ZDLE9IaURBLGFBeENILEdBZ0JDLEdBYUMsRUFXRSxNRzBDRDtBQUFELElBM0ZTLE1IaURSLGFBeENILEdBZ0JDLEdBYUMsRUFXRSxNRzBDRDtBQUNELElBNUZGLEVIaURHLGFBeENILEdBZ0JDLEdBYUMsRUFXRSxNRzJDRDtBQUFELElBNUZDLE9IaURBLGFBeENILEdBZ0JDLEdBYUMsRUFXRSxNRzJDRDtBQUFELElBNUZTLE1IaURSLGFBeENILEdBZ0JDLEdBYUMsRUFXRSxNRzJDRDtFQUNBLFdBQUE7RUFDQSxtQkFBQTs7QUNoR0o7RVZzQkMsZUFBQTtFQUNBLGtCQUFBO0VBQ0EsbUJBQUE7RUFDQSxvQkFBQTtFRzJQQywwQkFBQTtFQUFpQyxvQ0FBQTtFQUNqQyx1QkFBQTtFQUE4Qiw2QkFBQTtFQUM5QixrQkFBQTtFQUF5Qiw0QkFBQTtFT25SMUIsZ0NBQUE7RUFFQSxtQkFBQTtFQUNBLHFCQUFBO0VBQ0EsbUJBQUE7RUFDQSx3QkFBQTtFQUNBLGdCQUFBO0VBQ0Esa0JBQUE7RUFDQSxhQUFBO0VBQ0Esb0JBQUE7RUFDQSxjQUFBOztBQUVBLFVBQUM7RUFDQSxjQUFBOztBQUdELFVBQUM7RUFDQSxTQUFTLEVBQVQ7RUFDQSxRQUFBO0VBQ0EsU0FBQTtFQUNBLG1CQUFBO0VBQ0Esa0JBQUE7O0FBTUQsYUFBQztBQUFELGFBQUM7RUFDQSxVQUFBO0VBQ0EsOEJBQUE7RUFDQSx5REFBQTs7QUFNRCxhQUFDO0FBQUQsYUFBQztFQUNBLGFBQUE7RUFDQSw4QkFBQTtFQUNBLHlEQUFBOztBQU1ELGFBQUM7QUFBRCxhQUFDO0VBQ0EsVUFBQTs7QUFNRCxhQUFDO0FBQUQsYUFBQztFQUNBLFdBQUE7O0FDdkRGLGNBQWM7QUFDZCxlQUFlO0VBQ2QsU0FBUyxFQUFUO0VBQ0EscUJBQUE7RUFDQSxXQUFBO0VBQ0EsWUFBQTtFQUNBLHNCQUFBO0VBQ0EsNEJBQUE7O0FBR0QsY0FBYztFQUNiLGtCQUFBOztBQUdELGVBQWU7RUFDZCxpQkFBQTs7QUFJQSxjQUFDO0FBQVMsY0FBQztFQUNWLHNCQUFrQiw2Y0FBbEI7O0FBS0QsbUJBQUM7QUFBUyxtQkFBQztFQUNWLHNCQUFrQiw2aUJBQWxCOztBQUtELFdBQUM7QUFBUyxXQUFDO0VBQ1Ysc0JBQWtCLDZpQkFBbEI7O0FDNUJGLElBQUssUUFFSjtFQUNDLHNCQUFBOztBQUhGLElBQUssUUFNSixNQUFLO0VBQ0osZ0JBQUE7RUFDQSxxQkFBQTs7QUFSRixJQUFLLFFBV0o7RUFDQyx5QkFBQTtFQUNBLDBCQUFBOztBQUVBLElBZkcsUUFXSixNQUlFO0VBQ0EsV0FBQTs7QUFHRCxJQW5CRyxRQVdKLE1BUUU7RUFDQSxZQUFBOztBQXBCSCxJQUFLLFFBd0JKO0VBQ0MsYUFBQTs7QUFJRjtFWlpDLGVBQUE7RUFDQSxtQkFBQTtFQUNBLG1CQUFBO0VBQ0Esb0JBQUE7RVlXQSxpQkFBQTtFQUNBLHlCQUFBO0VBQ0EsZ0JBQUE7RUFDQSxxQkFBQTtFQUNBLHNCQUFBO0VBQ0EsV0FBQTtFVDJPQywwQkFBQTtFQUFpQyxvQ0FBQTtFQUNqQyx1QkFBQTtFQUE4Qiw2QkFBQTtFQUM5QixrQkFBQTtFQUF5Qiw0QkFBQTtFUzNPMUIsa0JBQUE7O0FBVEQsT0FXQyxNQUFLO0VBQ0osYUFBQTs7QUFaRixPQWVDO0VBQ0Msa0JBQUE7RUFDQSxVQUFBO0VBQ0EsV0FBQTtFQUNBLGVBQUE7RUFDQSxpQkFBQTs7QUFFQSxPQVBELE1BT0U7RUFDQSwwQkFBQTs7QUF2QkgsT0EyQkM7RUFDQyxXQUFBO0VBQ0Esc0JBQUE7RUFDQSxhQUFBO0VBQ0EsY0FBQTtFQUNBLFlBQUE7RUFDQSxnQkFBQTtFVGlOQSw0QkFBQTtFQUFpQyxvQ0FBQTtFQUNqQyx5QkFBQTtFQUE4Qiw2QkFBQTtFQUM5QixvQkFBQTtFQUF5Qiw0QkFBQTs7QVNwUDNCLE9BMkJDLGNBU0M7RUFDQyxnQkFBQTtFQUNBLGtCQUFBO0VBQ0EsY0FBQTtFQUNBLGFBQUE7RUFDQSxZQUFBO0VBQ0EsbUJBQUE7RVR3TUQsNEJBQUE7RUFBaUMsb0NBQUE7RUFDakMseUJBQUE7RUFBOEIsNkJBQUE7RUFDOUIsb0JBQUE7RUFBeUIsNEJBQUE7O0FTdk14QixPQWxCRixjQVNDLFNBU0U7RUFDQSxTQUFTLEVBQVQ7RUFDQSxjQUFBO0VBQ0Esa0JBQUE7RUFDQSxNQUFBO0VBQ0EsUUFBQTtFQUNBLFdBQUE7RUFDQSxPQUFBO0VBRUEseUJBQUE7RVRzS0Ysd0NBQUE7RUFDQSxvQ0FBQTtFQUNBLGdDQUFBO0VBS0EseUNBQUE7RUFBOEMsb0NBQUE7RUFDOUMscUNBQUE7RUFBMEMsNkJBQUE7RUFDMUMsaUNBQUE7RUFBc0MsNEJBQUE7O0FTdkt2QyxPQUFDLE1BQ0EsY0FBYyxTQUFRO0VBQ3JCLG1CQUFBOztBQWhFSCxPQW9FQyxNQUFLLGNBQWdCLFFBRXBCLGdCQUFnQjtFQUNmLGlCQUFBOztBQXZFSCxPQW9FQyxNQUFLLGNBQWdCLFFBU3BCLFFBQU87RUFDTixzQkFBQTtFQUNBLHNCQUFBOztBQS9FSCxPQW1GQyxNQUFLLGNBQWdCLFFBQVMsUUFBTztFQUNwQyxxQkFBQTtFQUNBLHFCQUFBOztBQ3pIRjtFVmszQkUseUJBQUE7RUFDQSxzQkFBQTtFQUNBLHFCQUFBO0VBQ0EsaUJBQUE7O0FVcjNCRixRQUdDO0VBQ0MsZUFBQTs7QUFKRixRQU1DO0VBQ0MsZ0JBQUE7O0FBUEYsUUFVQztFQUNDLGFBQUE7O0FBR0QsUUFBQyxVQUNBO0VBQ0MsYUFBQTs7QUFGRixRQUFDLFVBS0E7RUFDQyxnQkFBQTs7QUFLSDtFQUNDLGdCQUFBOztBQUVBLGtCQUFDO0VBQ0EsU0FBQTs7QUFNRCxzQkFBQztBQUFELHVCQUFDO0FBQVMsc0JBQUM7QUFBRCx1QkFBQztFQUNWLHNCQUFrQix5c0JBQWxCOztBQUlBLHNCQURBLFdBQ0M7QUFBRCx1QkFEQSxXQUNDO0FBQVMsc0JBRFYsV0FDVztBQUFELHVCQURWLFdBQ1c7RUFDVixzQkFBa0IscXRCQUFsQjs7QUFNRixzQkFBQztBQUNELHNCQUFDO0VBQ0EsNkJBQUE7O0FBS0QsdUJBQUM7QUFDRCx1QkFBQztFQUNBLGdDQUFBOztBQ3RERjtFQUNDLGFBQUE7RUFDQSxrQkFBQTtFQUNBLHVCQUFBO0VBQ0EsZ0JBQUE7RVg0U0MsOEJBQUE7RUFDQSwyQkFBQTtFQUNBLHNCQUFBO0VXelNELHFCQUFBO0VBQ0EsbUJBQUE7RVhndkJDLHdDQUFBO0VBQ0EscUNBQUE7RUFDQSxtQ0FBQTtFQUNBLG9DQUFBO0VBQ0EsZ0NBQUE7O0FXanZCRCxNQUFDO0VYdVFBLDRCQUFBO0VBQWlDLG9DQUFBO0VBQ2pDLHlCQUFBO0VBQThCLDZCQUFBO0VBQzlCLG9CQUFBO0VBQXlCLDRCQUFBO0VXdlF6QixlQUFBO0VBQ0EsWUFBQTtFQUNBLFdBQUE7RUFDQSxrQkFBQTtFQUNBLFNBQUE7RUFDQSxXQUFBO0VBQ0EsZUFBQTtFQUNBLGtCQUFBO0VBQ0EsaUJBQUE7RUFDQSxtQkFBQTs7QUN6QkYsSUFBSztBQUNMLE1BQU87QUFDUCxhQUFjO0FBQ2QsTUFBTztFQUNOLGdCQUFBOztBQUlEO0VBQ0MsZ0JBQUE7O0FBR0Q7RUFDQyw2QkFBQTs7QUNYQSxTQUFDO0VBQ0EseUJBQUE7RUFDQSxXQUFBOztBQUZELFNBQUMsSUFJQSxTQUNDO0FBTEYsU0FBQyxJQUlBLFNBQ0s7QUFMTixTQUFDLElBSUEsU0FDUztBQUxWLFNBQUMsSUFJQSxTQUNhO0FBTGQsU0FBQyxJQUlBLFNBQ2lCO0VBQ2YsV0FBQTs7QUFOSCxTQUFDLElBSUEsU0FLQztFaEJZRixlQUFBO0VBQ0EsbUJBQUE7RUFDQSxtQkFBQTtFQUNBLG9CQUFBO0VnQmJHLGdCQUFBOztBQVhILFNBQUMsSUFJQSxTQUtDLEVBSUM7RUFDQyxxQkFBQTtFQUNBLDhCQUFBO0VBQ0EsY0FBQTs7QUFFQSxTQWxCSCxJQUlBLFNBS0MsRUFJQyxFQUtFO0VBQ0EsY0FBQTs7QUFuQkwsU0FBQyxJQUlBLFNBb0JDO0VBQ0MsV0FBQTs7QUF6QkgsU0FBQyxJQUlBLFNBd0JDO0VBQ0MsV0FBQTs7QUE3QkgsU0FBQyxJQUlBLFNBNEJDO0VBQ0Msa0JBQUE7RUFDQSxjQUFBOztBQUtILFNBQUM7RUFDQSxrQkFBQTs7QUFFQSxTQUhBLE9BR0M7RUFDQSxXQUFBO0VBQ0EsU0FBUyxFQUFUO0VBQ0EsbUJBQUE7RUFDQSxrQkFBQTtFQUNBLE1BQUE7RUFDQSxPQUFBO0VBQ0EsUUFBQTtFQUNBLFdBQUE7O0FDdERILElBQUs7QUFDTCxNQUFPO0FBQ1AsYUFBYztBQUNkLE1BQU87RUFDTixpQkFBQTs7QUFHRCxJQUFLLGdCQUFlO0VBQ25CLGVBQUE7O0FBR0Q7RUFDQyxtQkFBQTtFQUNBLFlBQUE7RUFDQSxpQkFBQTs7QUFIRCxPQU1DO0VBRUMsa0JBQUE7RUFDQSxVQUFBO0VBQ0EsVUFBQTtFQUNBLG1CQUFBO0VBR0EsbUJBQUE7RUFDQSw0QkFBQTs7QUFFQSxPQVhELFdBV0U7RUFDQSx5REFBQTs7QUFLSCxRQUFTO0VBQ1IsZ0JBQUE7RUFDQSxTQUFBO0VBQ0Esd0JBQUE7O0FBRUEsUUFMUSxtQkFLUDtFQUNBLFlBQUE7O0FBS0YsS0FBTTtFQUNMLGdCQUFBO0VBQ0EsY0FBQTtFQUNBLDBCQUFBOztBQUdELEtBQU0sY0FBYTtFQUNsQixhQUFBOztBQUlBLFFBRFEsY0FDUDtFQUNBLGFBQUE7O0FBRkYsUUFBUyxjQUtSO0VBQ0MsYUFBQTs7QUFJRixRQUNDO0VBQ0MsaUJBQUE7O0FBSUY7RUFDQyxpQkFBQTs7QUFERCxTQUdDO0VBQ0MsV0FBQTtFQUNBLGlCQUFBOztBQUxGLFNBR0MsTUFJQztFQUNDLGdCQUFBOztBQUVBLFNBUEYsTUFJQyxTQUdFO0VBQ0EsdUJBQUE7RUFDQSxXQUFBOztBQUZELFNBUEYsTUFJQyxTQUdFLE1BSUE7RUFDQywwQkFBQTs7QUFmTCxTQUdDLE1BaUJDO0VBQ0MsV0FBQTtFQUNBLGFBQUE7O0FBR0QsU0F0QkQsTUFzQkU7RUFDQSxnQkFBQTs7QUFLSDtFQUNDLGdCQUFBO0VBQ0EsU0FBQTtFQUNBLFVBQUE7RUFDQSx3QkFBQTs7QUFFQSx1QkFBQztFQUNBLFlBQUE7RUFDQSxVQUFBOztBQUtGO0VBQ0MsaUJBQUE7O0FBREQsTUFHQyxJQUFHO0VBQ0YsaUJBQUE7O0FBSkYsTUFPQztFQUNDLGlCQUFBOztBQVJGLE1BT0MsY0FHQztFQUNDLGlCQUFBOztBQVhILE1BT0MsY0FPQztFQUVDLGtCQUFBOztBQWhCSCxNQW9CQztFQUNDLGtCQUFBO0VBQ0EsU0FBQTtFQUVBLFNBQUE7RUFDQSxrQkFBQTs7QWpCM0ZELFFBQWdDO0VBNkNqQyxNaUJ5Q0M7SUFVRSxVQUFBO0lBQ0EsaUJBQUE7SUFFQSxVQUFBO0lBQ0EsbUJBQUE7O0VBRUEsTUFoQkYsV0FnQkc7SUFDQSxVQUFBO0lBQ0EsV0FBQTs7O0FqQnhHSCxRQUFnQztFQTZDakMsTWlCeUNDO0lBd0JFLGFBQUE7OztBQU1ILFNBQ0MsZUFDQztFQUNDLFlBQUE7RUFDQSxZQUFBOzs7Ozs7Ozs7O0FDeEpILFFBQVM7RUFDUixvQkFBQTtFZmkyQkMseUJBQUE7RUFDQSxzQkFBQTtFQUNBLHFCQUFBO0VBQ0EsaUJBQUE7RWVsMkJELGVBQUE7O0FBSUQsb0JBQXFCO0VmMmVsQixPQUFBO0VBQVMseUJBQUE7RUFDVixvQkFBQTtFQUNBLGlCQUFBO0VBQ0EsWUFBQTs7QWUxZUYsWUFBWTtFQUNYLGtCQUFBO0Vmc2VFLE9BQUE7RUFBUywwQkFBQTtFQUNWLGtCQUFBO0VBQ0EsZUFBQTtFQUNBLFVBQUE7O0FlcGVELFlBTlcsT0FNVjtFQUNBLFNBQVMsRUFBVDtFQUNBLGNBQUE7RUFDQSxrQkFBQTtFQUNBLE1BQUE7RUFDQSxVQUFBO0VBQ0EsV0FBQTtFQUNBLE9BQUE7RWY4T0EsMEJBQUE7RUFBaUMsb0NBQUE7RUFDakMsdUJBQUE7RUFBOEIsNkJBQUE7RUFDOUIsa0JBQUE7RUFBeUIsNEJBQUE7RUFtQnpCLDRDQUFBO0VBQ0EseUNBQUE7RUFDQSxvQ0FBQTs7QWVsUkYsWUFBWSxPQWtCWDtFZjhQQyx3QkFBQTtFQUNBLHFCQUFBO0VBQ0EsZ0JBQUE7RWU5UEEscUJBQUE7O0FBcEJGLFlBQVksT0F1Qlg7QUF2QkQsWUFBWSxPQXdCWDtFQUNDLGtCQUFBO0VBQ0EsVUFBQTs7QUExQkYsWUFBWSxPQTZCWDtFZm1QQyx3QkFBQTtFQUNBLHFCQUFBO0VBQ0EsZ0JBQUE7O0FlaFBGO0VmcXpCRSx5QkFBQTtFQUNBLHNCQUFBO0VBQ0EscUJBQUE7RUFDQSxpQkFBQTs7QWVyekJGO0VBQ0MsY0FBQTtFQUNBLG9CQUFBO0VBQ0EsZ0JBQUE7RUFDQSxnQkFBQTs7QUFHQyxRQURELE9BQU0sU0FDSjtFQUNBLGVBQUE7RUFFQSxxQkFBQTtFQUNBLGdCQUFBO0VBQ0EsVUFBQTtFQUNBLHlCQUFBOztBQUdELFFBVkQsT0FBTSxTQVVKO0VBQ0EsYUFBQTs7QUFHRCxRQWRELE9BQU0sU0FjSjtFQUNBLFdBQUE7RUFDQSxpQkFBQTs7QUFHRCxRQW5CRCxPQUFNLFNBbUJKO0VBQ0EsWUFBQTtFQUNBLGdCQUFBOztBQTNCSCxRQU1DLE9BQU0sU0F3Qkw7RUFDQyxjQUFBOztBQU1ILGdCQUFnQjtBQUNoQixnQkFBZ0I7QUFDaEIsc0JBQXNCO0VBQ3JCLGFBQUE7O0FBR0QsZ0JBQWlCO0FBQ2pCLFFBQVMsT0FBTTtBQUNmLGdCQUFpQixTQUFRLFdBQVc7RUFDbkMsYUFBQTs7QUFHRCxHQUFHO0VBQ0YsVUFBQTtFQUNBLGdCQUFBO0VBQ0EsV0FBQTtFQUNBLGtCQUFBO0VBQ0EsY0FBQTtFQUNBLHlCQUFBOztBQU5ELEdBQUcsZ0JBUUY7RUFDQyxTQUFBOztBQVRGLEdBQUcsZ0JBWUY7RUFDQyxhQUFBOztBQUdELEdBaEJFLGdCQWdCRCxjQUFlO0VBQ2Ysa0JBQUE7RWZnWUMsT0FBQTtFQUFTLHlCQUFBO0VBQ1Ysb0JBQUE7RUFDQSxpQkFBQTtFQUNBLFlBQUE7O0FlcFpGLEdBQUcsZ0JBdUJGLE9BQU87RUFDTixpQkFBQTs7QUFJRCxHQTVCRSxnQkE0QkE7RUFDRCxVQUFBO0VBQ0EsU0FBQTtFQUNBLDBCQUFBO0VBQ0EsV0FBQTs7QUFFQSxHQWxDQyxnQkE0QkEsS0FNQTtFQUNBLDJCQUFBOztBQUdELEdBdENDLGdCQTRCQSxLQVVBO0VBQ0Esd0JBQUE7O0FBWEYsR0E1QkUsZ0JBNEJBLEtBZUQ7RUFDQyxVQUFBO0VBQ0EsU0FBQTs7QUFJRCxHQWpEQyxnQkE0QkEsS0FxQkM7RUFDRCxrQkFBQTs7QUFFQSxHQXBEQSxnQkE0QkEsS0FxQkMsS0FHQTtFQUNBLGlCQUFBO0VBQ0EsaUJBQUE7RUFDQSxlQUFBOztBQUdELEdBMURBLGdCQTRCQSxLQXFCQyxLQVNBO0FBQ0QsR0EzREEsZ0JBNEJBLEtBcUJDLEtBVUE7RUFDQSw2QkFBQTs7QUFHRCxHQS9EQSxnQkE0QkEsS0FxQkMsS0FjQTtFQUNBLDBCQUFBOztBQUVBLEdBbEVELGdCQTRCQSxLQXFCQyxLQWNBLHNCQUdDO0VBQ0EsZ0JBQUE7O0FBSUYsR0F2RUEsZ0JBNEJBLEtBcUJDLEtBc0JBLG1CQUFtQjtBQUNwQixHQXhFQSxnQkE0QkEsS0FxQkMsS0F1QkEsbUJBQW1CO0FBQ3BCLEdBekVBLGdCQTRCQSxLQXFCQyxLQXdCQSx1QkFBdUI7QUFDeEIsR0ExRUEsZ0JBNEJBLEtBcUJDLEtBeUJBLHVCQUF1QjtFQUN2QixnQkFBQTtFQUNBLFVBQUE7O0FBR0QsR0EvRUEsZ0JBNEJBLEtBcUJDLEtBOEJBLG1CQUFtQjtBQUNwQixHQWhGQSxnQkE0QkEsS0FxQkMsS0ErQkEsdUJBQXVCO0FBQ3hCLEdBakZBLGdCQTRCQSxLQXFCQyxLQWdDQSxtQkFBbUIsT0FBTztBQUMzQixHQWxGQSxnQkE0QkEsS0FxQkMsS0FpQ0EsdUJBQXVCLE9BQU87RUFDOUIsbUJBQUE7O0FBR0QsR0F0RkEsZ0JBNEJBLEtBcUJDLEtBcUNBLG1CQUFtQjtBQUNwQixHQXZGQSxnQkE0QkEsS0FxQkMsS0FzQ0EsdUJBQXVCO0VBQ3ZCLG1CQUFBOztBQUdELEdBM0ZBLGdCQTRCQSxLQXFCQyxLQTBDQTtFQU1BLG1CQUFBOztBQUxBLEdBNUZELGdCQTRCQSxLQXFCQyxLQTBDQSx1QkFDQztFQUNBLFNBQVMsRUFBVDtFQUNBLFdBQUE7O0FBS0QsR0FuR0QsZ0JBNEJBLEtBcUJDLEtBMENBLHVCQVFFO0VBQ0QsZ0JBQUE7O0FBSUYsR0F4R0EsZ0JBNEJBLEtBcUJDLEtBdURDO0FBQUssR0F4R1AsZ0JBNEJBLEtBcUJDLEtBdURRO0VBQ1IsbUJBQUE7RUFDQSxzQkFBQTs7QUF6REYsR0FqREMsZ0JBNEJBLEtBcUJDLEtBNkREO0VBQ0MsaUJBQUE7RUFDQSxnQkFBQTs7QUEvREYsR0FqREMsZ0JBNEJBLEtBcUJDLEtBNkRELEVBSUM7RUFDQyxtQkFBQTtFQUNBLGVBQUE7O0FBbkVILEdBakRDLGdCQTRCQSxLQXFCQyxLQTZERCxFQUlDLEtBSUM7RUFDQyxtQkFBQTtFQUNBLGlCQUFBO0VBQ0EsZUFBQTtFQUNBLGdCQUFBO0VmMkNKLDBCQUFBO0VBQWlDLG9DQUFBO0VBQ2pDLHVCQUFBO0VBQThCLDZCQUFBO0VBQzlCLGtCQUFBO0VBQXlCLDRCQUFBO0VlM0NyQixzQkFBQTtFQUNBLGNBQUE7RUFDQSxpQkFBQTtFQUNBLFlBQUE7O0FBR0MsR0FsSUosZ0JBNEJBLEtBcUJDLEtBNkRELEVBSUMsS0FJQyxPQVdFLElBQUksV0FDSDtBQUNELEdBbklKLGdCQTRCQSxLQXFCQyxLQTZERCxFQUlDLEtBSUMsT0FXRSxJQUFJLFdBRUg7RUFDQSxXQUFBO0VBQ0EseUJBQUE7RUFDQSx5QkFBQTs7QUFJRixHQTFJSCxnQkE0QkEsS0FxQkMsS0E2REQsRUFJQyxLQUlDLE9Bb0JFLEtBQUs7RUFDTCxlQUFBO0Vmc1FKLE9BQUE7RUFBUyx5QkFBQTtFQUNWLG9CQUFBO0VBQ0EsaUJBQUE7RUFDQSxZQUFBOztBZW5XQSxHQWpEQyxnQkE0QkEsS0FxQkMsS0FrR0Q7RUFDQyx5QkFBQTtFQUNBLFVBQUE7RUFDQSxXQUFBOztBQXJHRixHQWpEQyxnQkE0QkEsS0FxQkMsS0FrR0QsR0FNQztFQUNDLGtCQUFBO0VBQ0EscUJBQUE7RUFHQSxjQUFBOztBQUVBLEdBaEtGLGdCQTRCQSxLQXFCQyxLQWtHRCxHQU1DLEdBT0U7RUFDQSwwQkFBQTs7QUFFQSxHQW5LSCxnQkE0QkEsS0FxQkMsS0FrR0QsR0FNQyxHQU9FLHNCQUdDO0VBQ0EsYUFBQTs7QUFKRixHQWhLRixnQkE0QkEsS0FxQkMsS0FrR0QsR0FNQyxHQU9FLHNCQU9BO0VmRkosMEJBQUE7RUFBaUMsb0NBQUE7RUFDakMsdUJBQUE7RUFBOEIsNkJBQUE7RUFDOUIsa0JBQUE7RUFBeUIsNEJBQUE7RWVFcEIsY0FBQTs7QUFFQSxHQTNLSixnQkE0QkEsS0FxQkMsS0FrR0QsR0FNQyxHQU9FLHNCQU9BLHFCQUlFO0VBQ0EsK0JBQUE7O0FBWkgsR0FoS0YsZ0JBNEJBLEtBcUJDLEtBa0dELEdBTUMsR0FPRSxzQkFPQSxxQkFRQztFQUNDLHNCQUFBOztBQUtILEdBckxGLGdCQTRCQSxLQXFCQyxLQWtHRCxHQU1DLEdBNEJHO0FBQUssR0FyTFQsZ0JBNEJBLEtBcUJDLEtBa0dELEdBTUMsR0E0QlU7RUFDUixtQkFBQTtFQUNBLHNCQUFBOztBQXRJSixHQWpEQyxnQkE0QkEsS0FxQkMsS0FrR0QsR0FNQyxHQWtDQztFQUNDLFVBQUE7O0FBM0lKLEdBakRDLGdCQTRCQSxLQXFCQyxLQWtHRCxHQU1DLEdBa0NDLEdBSUM7RUFDQyxVQUFBO0VBQ0EscUJBQUE7RUFDQSxlQUFBO0VBQ0EscUJBQUE7O0FBbEpMLEdBakRDLGdCQTRCQSxLQXFCQyxLQWtHRCxHQU1DLEdBa0NDLEdBSUMsR0FPQztFQUNDLGVBQUE7RUFDQSxtQkFBQTs7QUF2Sk4sR0FqREMsZ0JBNEJBLEtBcUJDLEtBa0dELEdBTUMsR0FrQ0MsR0FJQyxHQVlDO0FBMUpMLEdBakRDLGdCQTRCQSxLQXFCQyxLQWtHRCxHQU1DLEdBa0NDLEdBSUMsR0FhQztFQUNDLGVBQUE7RUFDQSxTQUFBO0VBQ0Esc0JBQUE7RUFDQSxzQkFBQTtFQ2xTUCxrQkFBQTtFQUNBLG1CQUFBO0VBRUEsb0JBQUE7RUFDQSxvQkFBQTs7QUR3U0EsR0ExTkUsZ0JBME5BO0VBQ0QsZ0JBQUE7O0FBSUQsR0EvTkUsZ0JBK05EO0VBQ0EsWUFBQTtFQUNBLFlBQUE7RUFDQSxnQkFBQTtFQUNBLGdCQUFBO0VBQ0Esa0JBQUE7O0FBTEQsR0EvTkUsZ0JBK05ELE1BT0E7RUN4VEQsa0JBQUE7RUFDQSxrQkFBQTtFQUVBLG9CQUFBO0VBQ0Esb0JBQUE7RURzVEUscUJBQUE7RUFDQSxtQkFBQTtFQUNBLDZCQUFBO0VBQ0EsYUFBQTtFQUNBLG9CQUFBOztBQWJGLEdBL05FLGdCQStORCxNQWdCQTtFQUVDLG9CQUFBO0VBQ0EsZ0JBQUE7O0FBbkJGLEdBL05FLGdCQStORCxNQWdCQSxHQUtDO0VBQ0MsaUJBQUE7RUFDQSxTQUFBO0VBQ0EscUJBQUE7O0FBR0QsR0ExUEEsZ0JBK05ELE1BZ0JBLEdBV0c7RUFDRCxrQkFBQTs7QUE1QkgsR0EvTkUsZ0JBK05ELE1BZ0JBLEdBZUM7RUFDQyxXQUFBO0VBQ0EsVUFBQTtFQUNBLFdBQUE7RUFDQSxpQkFBQTtFQUNBLDBCQUFBO0VBQ0EsbUJBQUE7RUFDQSxtQkFBQTtFZnBFRiw4QkFBQTtFQUNBLDJCQUFBO0VBQ0Esc0JBQUE7O0FlNEJELEdBL05FLGdCQStORCxNQWdCQSxHQWVDLEdBVUM7RUFDQyxnQkFBQTtFQUNBLFlBQUE7RUFDQSxzQkFBQTs7QUE1Q0osR0EvTkUsZ0JBK05ELE1BZ0JBLEdBZ0NDO0VBQ0MsaUJBQUE7RUFDQSxZQUFBO0VBQ0Esb0JBQUE7O0FBbkRILEdBL05FLGdCQStORCxNQWdCQSxHQWdDQyxHQUtDO0VBQ0Msa0JBQUE7O0FBR0QsR0F4UkQsZ0JBK05ELE1BZ0JBLEdBZ0NDLEdBU0U7RUFDQSxTQUFTLE9BQVQ7RUFDQSxjQUFBO0VBQ0EsV0FBQTtFQUNBLFlBQUE7RUFDQSxTQUFBO0VBQ0EsUUFBQTs7QUFPTDtBQUNBLGdCQUFpQixTQUFRO0FBQ3pCO0VmbElFLDBCQUFBO0VBQWlDLG9DQUFBO0VBQ2pDLHVCQUFBO0VBQThCLDZCQUFBO0VBQzlCLGtCQUFBO0VBQXlCLDRCQUFBO0Vla0kxQixzQkFBQTtFQzNYQSxrQkFBQTtFQUNBLG1CQUFBO0VBRUEsb0JBQUE7RUFDQSxvQkFBQTs7QUQyWEQsZ0JBQWlCLFNBQVE7QUFDekIsV0FBWTtBQUNaO0VDallDLGtCQUFBO0VBQ0EsbUJBQUE7RUFFQSxvQkFBQTtFQUNBLG9CQUFBO0VEK1hBLGdKQUFBOztBQUdELFdBQVk7RUFDWCxZQUFBO0VBQ0EsVUFBQTtFQUNBLFNBQUE7O0FBR0QsZ0JBQWlCLFNBQVE7RWZ6SHZCLDhCQUFBO0VBQ0EsMkJBQUE7RUFDQSxzQkFBQTtFZXlIRCxjQUFBO0VBQ0EsYUFBQTtFQUNBLFdBQUE7RUFDQSxpQkFBQTtFQUNBLFNBQUE7RUFDQSxZQUFBO0VBQ0EsYUFBQTtFQUNBLGdCQUFBO0VBQ0EsV0FBQTtFQUNBLGdCQUFBO0VBQ0EsaUJBQUE7RUFDQSxjQUFBOztBQUdELGlCQUFpQjtFQUNoQixVQUFBO0VBQ0EsY0FBQTtFQzlaQSxlQUFBO0VBQ0EsbUJBQUE7RUFFQSxtQkFBQTtFQUNBLG9CQUFBO0VEa2FBLGdKQUFBOztBQVZELGlCQUFpQixpQkFJaEI7RUFDQyxjQUFBO0VBQ0EsbUJBQUE7O0FBTUQsaUJBWmdCLGlCQVlkLEtBQUk7RUFDTCxtQkFBQTs7O0FBS0Y7RUFDQyxvQkFBQTs7QUFERCx1QkFHQyxTQUFTO0VBQ1IsbUJBQUE7RUFDQSxpQkFBQTs7QUFMRix1QkFRQztFQUVDLFlBQUE7RUFHQSxnQkFBQTs7QUFJRjtFQUNDLGVBQUE7RUFDQSxNQUFBO0VBQ0EsV0FBQTtFQUNBLFdBQUE7O0FBSkQsZ0JBTUM7RUFDQyxpQkFBQTs7QUFQRixnQkFNQyxrQkFHQztFQUNDLGdCQUFBOztBQVZILGdCQU1DLGtCQUdDLE9BR0M7RUFDQyxnQkFBQTs7QUFPSjtFQUNDLGtCQUFBO0VBQ0EsVUFBQTtFQUNBLFVBQUE7O0FBRUEsS0FBQztFQUNBLGFBQUEifQ== */ From 7e19246d3d8ec89a2d74047a045feea5b67e24e0 Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Thu, 18 Jan 2018 14:38:15 +0100 Subject: [PATCH 008/642] Add changelog entry. --- CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 337551f0701..fa1559a60cc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -28,10 +28,15 @@ Fixed Issues: * [#1470](https://github.com/ckeditor/ckeditor-dev/issues/1470): Fixed: [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) is not visible after drag and drop of a widget it is attached to. * [#1535](https://github.com/ckeditor/ckeditor-dev/issues/1535): Fixed: Improve [Widget](https://ckeditor.com/cke4/addon/widget) mouse over border contrast. + API Changes: * [#1346](https://github.com/ckeditor/ckeditor-dev/issues/1346): [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) [context manager API](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.balloontoolbar.contextManager) is now available in [pluginDefinition.init](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.pluginDefinition-method-init) method of a [requiring](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.pluginDefinition-property-requires) plugin. +Other Changes: + +* [#1337](https://github.com/ckeditor/ckeditor-dev/issues/1337): Update `samples` layout with actuall CKEditor logo and coherent color scheme. + ## CKEditor 4.8 **Important Notes:** From 215889d5b06b820a02173f8acda158eb10a6a8a4 Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Tue, 30 Jan 2018 11:26:20 +0100 Subject: [PATCH 009/642] Add svg logo and fallback to png for older browsers in sample html. --- samples/css/samples.css | 13 +++---------- samples/img/logo.png | Bin 12450 -> 5634 bytes samples/img/logo.svg | 13 +++++++++++++ samples/index.html | 2 +- samples/less/custom.less | 3 --- samples/less/samples.less | 2 +- 6 files changed, 18 insertions(+), 15 deletions(-) create mode 100644 samples/img/logo.svg diff --git a/samples/css/samples.css b/samples/css/samples.css index 118868e3a93..b52b3161aa3 100644 --- a/samples/css/samples.css +++ b/samples/css/samples.css @@ -1177,18 +1177,11 @@ header .balloon-a { display: none; } } -.header-a .header-a-logo img { +header .header-a-logo img { width: 160px; height: 60px; } -/** - * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license - */ -/** - * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license - */ + #toolbar .cke_toolbar { pointer-events: none; -webkit-user-select: none; @@ -1641,4 +1634,4 @@ div.toolbarModifier-hints dl dd:after { #help-content { display: none; } -/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2dsb2JhbC9nbG9iYWwubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2NvcmUvY29yZS5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvZ3JpZC9ncmlkLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvbGVzc2hhdC9idWlsZC9sZXNzaGF0Lmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9oZWFkZXItYS9oZWFkZXItYS5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvbmF2aWdhdGlvbi1hL25hdmlnYXRpb24tYS5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvbmF2aWdhdGlvbi1iL25hdmlnYXRpb24tYi5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvZm9vdGVyLWEvZm9vdGVyLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2NvbnRlbnQvY29udGVudC5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvYnV0dG9uLWEvYnV0dG9uLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2JhbGxvb24tYS9iYWxsb29uLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2ljb24vaWNvbi5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvc3dpdGNoL3N3aXRjaC5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvdG9nZ2xlci90b2dnbGVyLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9tb2RhbC9tb2RhbC5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvYmFzaWNzYW1wbGUvY29yZS5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvYmFzaWNzYW1wbGUvYWRqb2luZWQubGVzcyIsIi4uLy4uL3NhbXBsZXMvbGVzcy9jdXN0b20ubGVzcyIsIi4uLy4uL3NhbXBsZXMvdG9vbGJhcmNvbmZpZ3VyYXRvci9sZXNzL3Rvb2xiYXJtb2RpZmllci5sZXNzIiwiLi4vLi4vc2FtcGxlcy90b29sYmFyY29uZmlndXJhdG9yL2xlc3MvYmFzZS5sZXNzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFtREMsUUFBZ0M7RUF5Q2hDO0lBQ0Msd0JBQUE7OztBQzFGRjtBQUFTO0FBQU87QUFBUztBQUFZO0FBQVE7QUFBUTtBQUFRO0FBQVE7QUFBTTtBQUFNO0FBQUs7RUFDckYsY0FBQTs7QUFHRDtBQUFNO0VBQ0wsU0FBQTtFQUNBLFVBQUE7RUFDQSx3QkROK0IsdUNDTS9CO0VBQ0EsZ0JBQUE7RUFDQSxjQUFBOztBQ0hBLFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxVQUFBOztBQURELFlBQVk7RUFDWCxVQUFBOztBQURE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 */ +/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2dsb2JhbC9nbG9iYWwubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2NvcmUvY29yZS5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvZ3JpZC9ncmlkLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvbm9kZV9tb2R1bGVzL2xlc3NoYXQvYnVpbGQvbGVzc2hhdC5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvaGVhZGVyLWEvaGVhZGVyLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL25hdmlnYXRpb24tYS9uYXZpZ2F0aW9uLWEubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL25hdmlnYXRpb24tYi9uYXZpZ2F0aW9uLWIubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2Zvb3Rlci1hL2Zvb3Rlci1hLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9jb250ZW50L2NvbnRlbnQubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2J1dHRvbi1hL2J1dHRvbi1hLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9iYWxsb29uLWEvYmFsbG9vbi1hLmxlc3MiLCIuLi8uLi9ub2RlX21vZHVsZXMvY2tzb3VyY2Utc2FtcGxlcy1mcmFtZXdvcmsvY29tcG9uZW50cy9pY29uL2ljb24ubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL3N3aXRjaC9zd2l0Y2gubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL3RvZ2dsZXIvdG9nZ2xlci5sZXNzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2Nrc291cmNlLXNhbXBsZXMtZnJhbWV3b3JrL2NvbXBvbmVudHMvbW9kYWwvbW9kYWwubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2Jhc2ljc2FtcGxlL2NvcmUubGVzcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9ja3NvdXJjZS1zYW1wbGVzLWZyYW1ld29yay9jb21wb25lbnRzL2Jhc2ljc2FtcGxlL2Fkam9pbmVkLmxlc3MiLCIuLi8uLi9zYW1wbGVzL2xlc3MvY3VzdG9tLmxlc3MiLCIuLi8uLi9zYW1wbGVzL3Rvb2xiYXJjb25maWd1cmF0b3IvbGVzcy90b29sYmFybW9kaWZpZXIubGVzcyIsIi4uLy4uL3NhbXBsZXMvdG9vbGJhcmNvbmZpZ3VyYXRvci9sZXNzL2Jhc2UubGVzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBbURDLFFBQWdDO0VBeUNoQztJQUNDLHdCQUFBOzs7QUMxRkY7QUFBUztBQUFPO0FBQVM7QUFBWTtBQUFRO0FBQVE7QUFBUTtBQUFRO0FBQU07QUFBTTtBQUFLO0VBQ3JGLGNBQUE7O0FBR0Q7QUFBTTtFQUNMLFNBQUE7RUFDQSxVQUFBO0VBQ0Esd0JETitCLHVDQ00vQjtFQUNBLGdCQUFBO0VBQ0EsY0FBQTs7QUNIQSxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZQUFZO0VBQ1gsVUFBQTs7QUFERCxZ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 */ diff --git a/samples/img/logo.png b/samples/img/logo.png index c62de21d7ba308ea656ca64d329b85bfd6d25574..f3d43915e4e37e58e859d060a699ab5b727b627e 100644 GIT binary patch literal 5634 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 literal 12450 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 + + + Group + Created with Sketch. + + + + + + + + diff --git a/samples/index.html b/samples/index.html index e4b7ef121ed..3c324b34136 100644 --- a/samples/index.html +++ b/samples/index.html @@ -30,7 +30,7 @@

- CKEditor Sample + CKEditor Sample

From 4c13e15e8493ab8fbccd8e70bfb79a3048083863 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 11 Oct 2017 10:57:45 +0200 Subject: [PATCH 105/642] Update sample. --- plugins/easyimage/samples/easyimage.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/samples/easyimage.html b/plugins/easyimage/samples/easyimage.html index 772a3588cd7..fdd58fbdfdf 100644 --- a/plugins/easyimage/samples/easyimage.html +++ b/plugins/easyimage/samples/easyimage.html @@ -110,7 +110,7 @@

Apollo 11

getToken( function( token ) { CKEDITOR.replace( 'editor', { extraPlugins: 'easyimage', - imageUploadUrl: 'https://files.cke-cs.com/upload/', + easyimageUploadUrl: 'https://files.cke-cs.com/upload/', easyimage_token: token, height: 500 } ); From bf238aa5328d573937be5756a660cce4a9b86bff Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 11 Oct 2017 12:52:12 +0200 Subject: [PATCH 106/642] Add initial version of upload widget. --- plugins/easyimage/plugin.js | 65 ++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 7d095466a11..9f36c9fe271 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -8,6 +8,11 @@ var stylesLoaded = false; + // jscs:disable maximumLineLength + // Black rectangle which is shown before image is loaded. + var loadingImage = 'data:image/gif;base64,R0lGODlhDgAOAIAAAAAAAP///yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs='; + // jscs:enable maximumLineLength + function addCommands( editor ) { function isSideImage( widget ) { return widget.element.hasClass( editor.config.easyimage_sideClass ); @@ -132,42 +137,70 @@ } function registerUploadWidget( editor ) { - editor.on( 'widgetDefinition', function( evt ) { - if ( evt.data.name !== 'uploadimage' ) { - return; - } + var uploadUrl = CKEDITOR.fileTools.getUploadUrl( editor.config, 'easyimage' ); - evt.data.onUploaded = function( upload ) { - var $img = this.parts.img.$, - width = $img.naturalWidth, - height = $img.naturalHeight; + CKEDITOR.fileTools.addUploadWidget( editor, 'uploadeasyimage', { + supportedTypes: /image\/(jpeg|png|gif|bmp)/, - // Set width and height to prevent blinking. - this.replaceWith( '' ); - }; + uploadUrl: uploadUrl, + + loadMethod: 'loadAndUpload', + + additionalRequestParameters: { + isEasyImage: true + }, + + fileToElement: function() { + var img = new CKEDITOR.dom.element( 'img' ); + img.setAttribute( 'src', loadingImage ); + return img; + }, + + parts: { + img: 'img' + }, + + onUploading: function( upload ) { + // Show the image during the upload. + this.parts.img.setAttribute( 'src', URL.createObjectURL( upload.file ) ); + }, + + onUploaded: function( upload ) { + this.replaceWith( '' ); + } } ); editor.on( 'fileUploadRequest', function( evt ) { + var requestData = evt.data.requestData; + + if ( !requestData.isEasyImage ) { + return; + } + evt.data.requestData.file = evt.data.requestData.upload; delete evt.data.requestData.upload; + // This property is used by fileUploadResponse callback to identify EI requests. + evt.data.fileLoader.isEasyImage = true; + evt.data.fileLoader.xhr.setRequestHeader( 'Authorization', editor.config.easyimage_token ); } ); editor.on( 'fileUploadResponse', function( evt ) { var fileLoader = evt.data.fileLoader, xhr = fileLoader.xhr, - data = evt.data, response; + if ( !fileLoader.isEasyImage ) { + return; + } + evt.stop(); try { response = JSON.parse( xhr.responseText ); - data.url = response; + evt.data.response = response; } catch ( e ) { CKEDITOR.warn( 'filetools-response-error', { responseText: xhr.responseText } ); } @@ -186,7 +219,7 @@ } CKEDITOR.plugins.add( 'easyimage', { - requires: 'imagebase,uploadimage,contextmenu,dialog', + requires: 'imagebase,uploadwidget,contextmenu,dialog', lang: 'en', onLoad: function() { From 6b0239ea11b7b3e54f7377dfdaa9d37705ffc179 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 11 Oct 2017 14:06:51 +0200 Subject: [PATCH 107/642] Add API docs. --- plugins/easyimage/plugin.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 9f36c9fe271..e038a281f78 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -261,4 +261,20 @@ * @member CKEDITOR.config */ CKEDITOR.config.easyimage_sideClass = 'easyimage-side'; + + /** + * The URL where images inserted by Easy Image plugin should be uploaded. + * + * @since 4.8.0 + * @cfg {String} [easyimageUploadUrl='' (empty string = disabled)] + * @member CKEDITOR.config + */ + + /** + * Token used for authorization while uploading images via Easy Image plugin. + * + * @since 4.8.0 + * @cfg {String} [easyimage_token='' (empty string = disabled)] + * @member CKEDITOR.config + */ }() ); From ef60d4bcacb778354852e95f5be10f01c6e79a69 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 11 Oct 2017 17:58:03 +0200 Subject: [PATCH 108/642] Add CKEDITOR.plugins.easyimage._parseSrcSet. --- plugins/easyimage/plugin.js | 41 ++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index e038a281f78..47e14199ef0 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -105,6 +105,10 @@ allowedContent: { figure: { classes: config.easyimage_sideClass + }, + + img: { + attributes: '!src,srcset,alt,width,height' } }, @@ -166,7 +170,10 @@ }, onUploaded: function( upload ) { - this.replaceWith( '' ); + var srcset = CKEDITOR.plugins.easyimage._parseSrcSet( upload.responseData.response ); + + this.replaceWith( '' ); } } ); @@ -218,6 +225,38 @@ } } + /** + * Namespace providing a set of helper functions for Easy Image plugin. + * + * @since 4.8.0 + * @singleton + * @class CKEDITOR.plugins.easyimage + */ + CKEDITOR.plugins.easyimage = { + /** + * Converts response from the server into proper `[srcset]` attribute. + * + * @since 4.8.0 + * @private + * @param {Object} srcs Sources list to be parsed. + * @returns {String} `img[srcset]` attribute. + */ + _parseSrcSet: function( srcs ) { + var srcset = [], + src; + + for ( src in srcs ) { + if ( src === 'default' ) { + continue; + } + + srcset.push( srcs[ src ] + ' ' + src + 'w' ); + } + + return srcset.join( ', ' ); + } + }; + CKEDITOR.plugins.add( 'easyimage', { requires: 'imagebase,uploadwidget,contextmenu,dialog', lang: 'en', From d1646bffa5d3c9318810c403f890173297e258de Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 11 Oct 2017 17:59:01 +0200 Subject: [PATCH 109/642] Add unit test. --- tests/plugins/easyimage/tools.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/plugins/easyimage/tools.js diff --git a/tests/plugins/easyimage/tools.js b/tests/plugins/easyimage/tools.js new file mode 100644 index 00000000000..4fa4dc01e28 --- /dev/null +++ b/tests/plugins/easyimage/tools.js @@ -0,0 +1,30 @@ +/* bender-tags: editor,widget */ +/* bender-ckeditor-plugins: easyimage,toolbar */ + +( function() { + 'use strict'; + + bender.editor = true; + + var tools; + + bender.test( { + setUp: function() { + tools = CKEDITOR.plugins.easyimage; + }, + + 'test _parseSrcSet function': function() { + var srcs = { + 100: 'https://test/100', + 243: 'https://tests/243', + 404: 'http://tests/404', + 600: 'http://tests/600' + }, + srcset = 'https://test/100 100w, https://tests/243 243w, http://tests/404 404w, http://tests/600 600w'; + + srcs[ 'default' ] = 'http://test/default'; + + assert.areSame( srcset, tools._parseSrcSet( srcs ) ); + } + } ); +} )(); From 7f34f07942dc9402e58527d0d05c6db1828ea198 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 13 Oct 2017 17:08:47 +0200 Subject: [PATCH 110/642] Add unit tests. --- tests/plugins/easyimage/uploadwidget.js | 446 ++++++++++++++++++++++++ 1 file changed, 446 insertions(+) create mode 100644 tests/plugins/easyimage/uploadwidget.js diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js new file mode 100644 index 00000000000..9db497056e9 --- /dev/null +++ b/tests/plugins/easyimage/uploadwidget.js @@ -0,0 +1,446 @@ +/* bender-tags: editor,clipboard,widget */ +/* bender-ckeditor-plugins: easyimage,toolbar, */ +/* bender-include: %BASE_PATH%/plugins/clipboard/_helpers/pasting.js */ +/* bender-include: %BASE_PATH%/plugins/uploadfile/_helpers/waitForImage.js */ +/* global pasteFiles, waitForImage */ + +'use strict'; + +( function() { + var uploadCount, loadAndUploadCount, lastUploadUrl, resumeAfter, tests, + IMG_URL = '%BASE_PATH%_assets/logo.png', + DATA_IMG = 'data:', + BLOB_IMG = 'blob:'; + + bender.editors = { + classic: { + name: 'classic', + config: { + easyimageUploadUrl: 'http://foo/upload', + // Disable pasteFilter on Webkits (pasteFilter defaults semantic-text on Webkits). + pasteFilter: null + } + }, + + divarea: { + name: 'divarea', + config: { + extraPlugins: 'divarea', + easyimageUploadUrl: 'http://foo/upload', + // Disable pasteFilter on Webkits (pasteFilter defaults semantic-text on Webkits). + pasteFilter: null + } + }, + + inline: { + name: 'inline', + creator: 'inline', + config: { + easyimageUploadUrl: 'http://foo/upload', + // Disable pasteFilter on Webkits (pasteFilter defaults semantic-text on Webkits). + pasteFilter: null + } + } + }; + + function assertUploadingWidgets( editor, expectedSrc ) { + var widgets = editor.editable().find( 'img[data-widget="uploadeasyimage"]' ), + widget, i; + + assert.areSame( 1, widgets.count(), 'Expected widgets count should be 1' ); + + for ( i = 0; i < widgets.count(); i++ ) { + widget = widgets.getItem( i ); + assert.areSame( '0', widget.getAttribute( 'data-cke-upload-id' ) ); + assert.areSame( expectedSrc, widget.getAttribute( 'src' ).substring( 0, 5 ) ); + } + } + + tests = { + init: function() { + var responseData = { + response: { + 100: IMG_URL, + 200: IMG_URL + } + }; + + responseData[ 'default' ] = IMG_URL; + resumeAfter = bender.tools.resumeAfter; + + CKEDITOR.fileTools.fileLoader.prototype.loadAndUpload = function( url ) { + loadAndUploadCount++; + lastUploadUrl = url; + + this.responseData = CKEDITOR.tools.clone( responseData ); + }; + + CKEDITOR.fileTools.fileLoader.prototype.load = function() {}; + + CKEDITOR.fileTools.fileLoader.prototype.upload = function( url ) { + uploadCount++; + lastUploadUrl = url; + + this.responseData = CKEDITOR.tools.clone( responseData ); + }; + }, + + setUp: function() { + if ( !CKEDITOR.plugins.clipboard.isFileApiSupported ) { + assert.ignore(); + } + + var editorName; + + uploadCount = 0; + loadAndUploadCount = 0; + + for ( editorName in this.editors ) { + // Clear upload repository. + this.editors[ editorName ].uploadRepository.loaders = []; + } + + if ( CKEDITOR.fileTools.bindNotifications.reset ) { + CKEDITOR.fileTools.bindNotifications.reset(); + } + }, + + 'test classic with easyimage (integration test)': function( editor ) { + pasteFiles( editor, [ bender.tools.getTestPngFile() ] ); + + assertUploadingWidgets( editor, DATA_IMG ); + assert.areSame( '', editor.getData(), 'getData on loading.' ); + + var loader = editor.uploadRepository.loaders[ 0 ]; + + loader.data = bender.tools.pngBase64; + loader.uploadTotal = 10; + loader.changeStatus( 'uploading' ); + + assertUploadingWidgets( editor, BLOB_IMG ); + assert.areSame( '', editor.getData(), 'getData on uploading.' ); + + var image = editor.editable().find( 'img[data-widget="uploadeasyimage"]' ).getItem( 0 ); + + waitForImage( image, function() { + loader.url = IMG_URL; + loader.changeStatus( 'uploaded' ); + + assert.sameData( '

', editor.getData() ); + assert.areSame( 1, editor.editable().find( 'img[data-widget="image"]' ).count() ); + + assert.areSame( 1, loadAndUploadCount ); + assert.areSame( 0, uploadCount ); + assert.areSame( 'http://foo/upload', lastUploadUrl ); + } ); + }, + + 'test paste img as html (integration test)': function( editor, bot ) { + bot.setData( '', function() { + pasteFiles( editor, [], '

xx

' ); + + assertUploadingWidgets( editor, DATA_IMG ); + assert.areSame( '

xx

', editor.getData(), 'getData on loading.' ); + + var loader = editor.uploadRepository.loaders[ 0 ]; + + loader.data = bender.tools.pngBase64; + loader.changeStatus( 'uploading' ); + + assertUploadingWidgets( editor, BLOB_IMG ); + assert.areSame( '

xx

', editor.getData(), 'getData on uploading.' ); + + var image = editor.editable().find( 'img[data-widget="uploadeasyimage"]' ).getItem( 0 ); + + waitForImage( image, function() { + loader.url = IMG_URL; + loader.changeStatus( 'uploaded' ); + + assert.sameData( '

xx

', editor.getData() ); + assert.areSame( 1, editor.editable().find( 'img[data-widget="image"]' ).count() ); + + assert.areSame( 0, loadAndUploadCount ); + assert.areSame( 1, uploadCount ); + assert.areSame( 'http://foo/upload', lastUploadUrl ); + } ); + } ); + }, + + 'test supportedTypes png': function( editor, bot ) { + bot.setData( '', function() { + resumeAfter( editor, 'paste', function() { + assertUploadingWidgets( editor, DATA_IMG ); + } ); + + pasteFiles( editor, [ { name: 'test.png', type: 'image/png' } ] ); + + wait(); + } ); + }, + + 'test supportedTypes jpg': function( editor, bot ) { + bot.setData( '', function() { + resumeAfter( editor, 'paste', function() { + assertUploadingWidgets( editor, DATA_IMG ); + } ); + + pasteFiles( editor, [ { name: 'test.jpg', type: 'image/jpeg' } ] ); + + wait(); + } ); + }, + + 'test supportedTypes gif': function( editor, bot ) { + bot.setData( '', function() { + resumeAfter( editor, 'paste', function() { + assertUploadingWidgets( editor, DATA_IMG ); + } ); + + pasteFiles( editor, [ { name: 'test.gif', type: 'image/gif' } ] ); + + wait(); + } ); + }, + + 'test supportedTypes bmp': function( editor, bot ) { + bot.setData( '', function() { + resumeAfter( editor, 'paste', function() { + assertUploadingWidgets( editor, DATA_IMG ); + } ); + + pasteFiles( editor, [ { name: 'test.bmp', type: 'image/bmp' } ] ); + + wait(); + } ); + }, + + 'test not supportedTypes tiff': function( editor, bot ) { + bot.setData( '', function() { + resumeAfter( editor, 'paste', function() { + assert.areSame( 0, editor.editable().find( 'img[data-widget="uploadeasyimage"]' ).count() ); + } ); + + pasteFiles( editor, [ { name: 'test.tiff', type: 'image/tiff' } ] ); + + wait(); + } ); + }, + + 'test paste single image': function( editor ) { + resumeAfter( editor, 'paste', function( evt ) { + var img = CKEDITOR.dom.element.createFromHtml( evt.data.dataValue ); + + assert.areSame( '0', img.getAttribute( 'data-cke-upload-id' ) ); + assert.areSame( 'uploadeasyimage', img.getAttribute( 'data-widget' ) ); + + assert.areSame( 0, loadAndUploadCount ); + assert.areSame( 1, uploadCount ); + } ); + + editor.fire( 'paste', { + dataValue: '' + } ); + + wait(); + }, + + 'test paste nested image': function( editor ) { + resumeAfter( editor, 'paste', function( evt ) { + var imgs = CKEDITOR.dom.element.createFromHtml( evt.data.dataValue ).find( 'img[data-widget="uploadeasyimage"]' ), + img, i; + + assert.areSame( 2, imgs.count(), 'Expected imgs count should be 2' ); + + for ( i = 0; i < imgs.count(); i++ ) { + img = imgs.getItem( i ); + assert.areSame( i + '', img.getAttribute( 'data-cke-upload-id' ) ); + } + + assert.areSame( 0, loadAndUploadCount ); + assert.areSame( 2, uploadCount ); + } ); + + editor.fire( 'paste', { + dataValue: '
xx' + + '

xx

' + } ); + + wait(); + }, + + 'test paste no image': function( editor ) { + resumeAfter( editor, 'paste', function( evt ) { + assert.areSame( 'foo', evt.data.dataValue ); + + assert.areSame( 0, loadAndUploadCount ); + assert.areSame( 0, uploadCount ); + } ); + + editor.fire( 'paste', { + dataValue: 'foo' + } ); + + wait(); + }, + + 'test paste no data in image': function( editor ) { + resumeAfter( editor, 'paste', function( evt ) { + var img = CKEDITOR.dom.element.createFromHtml( evt.data.dataValue ); + + assert.isNull( img.getAttribute( 'data-cke-upload-id' ) ); + assert.isNull( img.getAttribute( 'data-widget' ) ); + + assert.areSame( 0, loadAndUploadCount ); + assert.areSame( 0, uploadCount ); + } ); + + editor.fire( 'paste', { + dataValue: '' + } ); + + wait(); + }, + + 'test paste image already marked': function( editor ) { + var uploads = editor.uploadRepository; + + resumeAfter( editor, 'paste', function( evt ) { + var img = CKEDITOR.dom.element.createFromHtml( evt.data.dataValue ); + + assert.areSame( '0', img.getAttribute( 'data-cke-upload-id' ) ); + assert.areSame( 'uploadeasyimage', img.getAttribute( 'data-widget' ) ); + + assert.areSame( 0, loadAndUploadCount ); + assert.areSame( 0, uploadCount ); + } ); + + // Fill upload repository. + uploads.create( bender.tools.getTestPngFile() ); + + editor.fire( 'paste', { + dataValue: '' + } ); + + wait(); + }, + + 'test omit images in non contentEditable': function( editor ) { + resumeAfter( editor, 'paste', function( evt ) { + var img = CKEDITOR.dom.element.createFromHtml( evt.data.dataValue ).findOne( 'img' ); + + assert.isNull( img.getAttribute( 'data-cke-upload-id' ) ); + assert.isNull( img.getAttribute( 'data-widget' ) ); + + assert.areSame( 0, loadAndUploadCount ); + assert.areSame( 0, uploadCount ); + } ); + + editor.fire( 'paste', { + dataValue: + '
' + + '' + + '
' + } ); + + wait(); + }, + + 'test handle images in nested editable': function( editor ) { + resumeAfter( editor, 'paste', function( evt ) { + var img = CKEDITOR.dom.element.createFromHtml( evt.data.dataValue ).findOne( 'img' ); + + assert.areSame( '0', img.getAttribute( 'data-cke-upload-id' ) ); + assert.areSame( 'uploadeasyimage', img.getAttribute( 'data-widget' ) ); + + assert.areSame( 0, loadAndUploadCount ); + assert.areSame( 1, uploadCount ); + } ); + + editor.fire( 'paste', { + dataValue: + '
' + + '
' + + '' + + '
' + + '
' + } ); + + wait(); + }, + + 'test handle images in nested editable using cke-editable': function( editor ) { + resumeAfter( editor, 'paste', function( evt ) { + var img = CKEDITOR.dom.element.createFromHtml( evt.data.dataValue ).findOne( 'img' ); + + assert.areSame( '0', img.getAttribute( 'data-cke-upload-id' ) ); + assert.areSame( 'uploadeasyimage', img.getAttribute( 'data-widget' ) ); + + assert.areSame( 0, loadAndUploadCount ); + assert.areSame( 1, uploadCount ); + } ); + + editor.fire( 'paste', { + dataValue: + '
' + + '
' + + '' + + '
' + + '
' + } ); + + wait(); + }, + + 'test bindNotifications when paste image': function( editor ) { + CKEDITOR.fileTools.bindNotifications = sinon.spy(); + + resumeAfter( editor, 'paste', function() { + var spy = CKEDITOR.fileTools.bindNotifications; + assert.areSame( 1, spy.callCount ); + assert.isTrue( spy.calledWith( editor ) ); + assert.areSame( bender.tools.pngBase64, spy.firstCall.args[ 1 ].data ); + } ); + + editor.fire( 'paste', { + dataValue: '' + } ); + + wait(); + }, + + 'test XSS attack': function( editor ) { + window.attacked = sinon.spy(); + + editor.fire( 'paste', { + dataValue: '' + bender.tools.pngBase64 + } ); + + editor.once( 'afterPaste', function() { + resume( function() { + assert.areSame( 0, window.attacked.callCount ); + } ); + } ); + + wait(); + }, + + 'test prevent upload fake elements (http://dev.ckeditor.com/ticket/13003)': function( editor ) { + var createspy = sinon.spy( editor.uploadRepository, 'create' ); + + editor.fire( 'paste', { + dataValue: 'nothing' + } ); + + editor.once( 'afterPaste', function() { + resume( function() { + assert.isTrue( createspy.notCalled ); + } ); + } ); + + wait(); + } + }; + + tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); + bender.test( tests ); +} )(); From 4d7749dcc99a3d61072f1d516dc2c975a1155ad5 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 13 Oct 2017 17:09:03 +0200 Subject: [PATCH 111/642] Add support for pasting images. --- plugins/easyimage/plugin.js | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 47e14199ef0..e695081c5bb 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -212,6 +212,50 @@ CKEDITOR.warn( 'filetools-response-error', { responseText: xhr.responseText } ); } } ); + + // Handle images which are not available in the dataTransfer. + // This means that we need to read them from the elements. + editor.on( 'paste', function( evt ) { + var fileTools = CKEDITOR.fileTools; + + // For performance reason do not parse data if it does not contain img tag and data attribute. + if ( !evt.data.dataValue.match( / Date: Mon, 16 Oct 2017 13:58:18 +0200 Subject: [PATCH 112/642] An example implementation for adding new FileLoader subclasses. --- plugins/cloudservices/plugin.js | 70 +++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 plugins/cloudservices/plugin.js diff --git a/plugins/cloudservices/plugin.js b/plugins/cloudservices/plugin.js new file mode 100644 index 00000000000..3203aa60207 --- /dev/null +++ b/plugins/cloudservices/plugin.js @@ -0,0 +1,70 @@ +( function() { + 'use strict'; + + CKEDITOR.plugins.add( 'cloudservices', { + requires: 'filetools', + onLoad: function() { + var FileLoader = CKEDITOR.fileTools.fileLoader; + + /** + * Dedicated uploader for [Cloud Services](https://ckeditor.com/ckeditor-cloud-services/). + * + * @since 4.8.0 + * @class CKEDITOR.plugins.cloudservices.fileLoader + * @extends CKEDITOR.fileTools.fileLoader + */ + function CloudSericesLoader( editor, fileOrData, fileName ) { + FileLoader.call( this, editor, fileOrData, fileName ); + } + + CloudSericesLoader.prototype = CKEDITOR.tools.extend( {}, FileLoader.prototype ); + + // CloudSericesLoader.prototype.attachRequestListeners = function() { + // FileLoader.prototype.attachRequestListeners.call( this ); + + // this.xhr.setRequestHeader( 'Authorization', this.editor.config.easyimage_token ); + // }; + + CKEDITOR.plugins.cloudservices.fileLoader = CloudSericesLoader; + }, + + beforeInit: function( editor ) { + editor.on( 'fileUploadRequest', function( evt ) { + var fileLoader = evt.data.fileLoader, + reqData = evt.data.requestData; + + if ( fileLoader instanceof CKEDITOR.plugins.cloudservices.fileLoader ) { + // Cloud Services expect file to be put as a "file" property. + reqData.file = reqData.upload; + delete reqData.upload; + + // Add authorization token. + evt.data.fileLoader.xhr.setRequestHeader( 'Authorization', editor.config.easyimage_token ); + } + }, null, null, 6 ); + + editor.on( 'fileUploadResponse', function( evt ) { + var fileLoader = evt.data.fileLoader, + xhr = fileLoader.xhr, + response; + + if ( fileLoader instanceof CKEDITOR.plugins.cloudservices.fileLoader ) { + evt.stop(); + + try { + response = JSON.parse( xhr.responseText ); + + evt.data.response = response; + } catch ( e ) { + CKEDITOR.warn( 'filetools-response-error', { responseText: xhr.responseText } ); + } + } + } ); + } + } ); + + CKEDITOR.plugins.cloudservices = { + // Note this type is loaded on runtime. + fileLoader: null + }; +} )(); \ No newline at end of file From 337d233ed12a6cf7ee692fcf0a03780aac9618ac Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 17 Oct 2017 14:28:35 +0200 Subject: [PATCH 113/642] Improved Cloud Service integration docs, added unit tests. --- plugins/cloudservices/plugin.js | 60 +++++++++++++++++++----- tests/plugins/cloudservices/unit.js | 73 +++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 tests/plugins/cloudservices/unit.js diff --git a/plugins/cloudservices/plugin.js b/plugins/cloudservices/plugin.js index 3203aa60207..85a15bcfa34 100644 --- a/plugins/cloudservices/plugin.js +++ b/plugins/cloudservices/plugin.js @@ -7,25 +7,43 @@ var FileLoader = CKEDITOR.fileTools.fileLoader; /** - * Dedicated uploader for [Cloud Services](https://ckeditor.com/ckeditor-cloud-services/). + * Dedicated uploader type for [Cloud Services](https://ckeditor.com/ckeditor-cloud-services/). + * + * Note that this type is defined in {@link CKEDITOR.pluginDefinition#onLoad plugin.onLoad} method, thus is + * guaranteed to be available in dependent plugin's {@link CKEDITOR.pluginDefinition#beforeInit beforeInit}, + * {@link CKEDITOR.pluginDefinition#init init} and {@link CKEDITOR.pluginDefinition#afterInit} methods. * * @since 4.8.0 - * @class CKEDITOR.plugins.cloudservices.fileLoader + * @class CKEDITOR.plugins.cloudservices.cloudServicesLoader * @extends CKEDITOR.fileTools.fileLoader */ - function CloudSericesLoader( editor, fileOrData, fileName ) { + function cloudServicesLoader( editor, fileOrData, fileName ) { FileLoader.call( this, editor, fileOrData, fileName ); } - CloudSericesLoader.prototype = CKEDITOR.tools.extend( {}, FileLoader.prototype ); + cloudServicesLoader.prototype = CKEDITOR.tools.extend( {}, FileLoader.prototype ); - // CloudSericesLoader.prototype.attachRequestListeners = function() { - // FileLoader.prototype.attachRequestListeners.call( this ); + /** + * @inheritdoc + * @param {String} [url] The upload URL. If not provided {@link CKEDITOR.config#cloudServices_url} will be used. + * @param {Object} [additionalRequestParameters] Additional data that would be passed to the + * {@link CKEDITOR.editor#fileUploadRequest} event. + */ + cloudServicesLoader.prototype.upload = function( url, additionalRequestParameters ) { + url = url || this.editor.config.cloudServices_url; - // this.xhr.setRequestHeader( 'Authorization', this.editor.config.easyimage_token ); - // }; + FileLoader.prototype.upload.call( this, url, additionalRequestParameters ); + }; - CKEDITOR.plugins.cloudservices.fileLoader = CloudSericesLoader; + /** + * @method loadAndUpload + * @inheritdoc + * @param {String} [url] The upload URL. If not provided {@link CKEDITOR.config#cloudServices_url} will be used. + * @param {Object} [additionalRequestParameters] Additional parameters that would be passed to + * the {@link CKEDITOR.editor#fileUploadRequest} event. + */ + + CKEDITOR.plugins.cloudservices.cloudServicesLoader = cloudServicesLoader; }, beforeInit: function( editor ) { @@ -33,13 +51,13 @@ var fileLoader = evt.data.fileLoader, reqData = evt.data.requestData; - if ( fileLoader instanceof CKEDITOR.plugins.cloudservices.fileLoader ) { + if ( fileLoader instanceof CKEDITOR.plugins.cloudservices.cloudServicesLoader ) { // Cloud Services expect file to be put as a "file" property. reqData.file = reqData.upload; delete reqData.upload; // Add authorization token. - evt.data.fileLoader.xhr.setRequestHeader( 'Authorization', editor.config.easyimage_token ); + evt.data.fileLoader.xhr.setRequestHeader( 'Authorization', editor.config.cloudServices_token ); } }, null, null, 6 ); @@ -48,7 +66,7 @@ xhr = fileLoader.xhr, response; - if ( fileLoader instanceof CKEDITOR.plugins.cloudservices.fileLoader ) { + if ( fileLoader instanceof CKEDITOR.plugins.cloudservices.cloudServicesLoader ) { evt.stop(); try { @@ -65,6 +83,22 @@ CKEDITOR.plugins.cloudservices = { // Note this type is loaded on runtime. - fileLoader: null + cloudServicesLoader: null }; + + /** + * Endpoint URL for [Cloud Services](https://ckeditor.com/ckeditor-cloud-services) uploads. + * + * @since 4.8.0 + * @cfg {String} [cloudServices_url=''] + * @member CKEDITOR.config + */ + + /** + * Token used for [Cloud Services](https://ckeditor.com/ckeditor-cloud-services) authentication. + * + * @since 4.8.0 + * @cfg {String} [cloudServices_token=''] + * @member CKEDITOR.config + */ } )(); \ No newline at end of file diff --git a/tests/plugins/cloudservices/unit.js b/tests/plugins/cloudservices/unit.js new file mode 100644 index 00000000000..f70076bcf52 --- /dev/null +++ b/tests/plugins/cloudservices/unit.js @@ -0,0 +1,73 @@ +/* @bender-ckeditor-plugins: cloudservices */ + +bender.editor = { + config: { + cloudServices_url: 'cs_url', + cloudServices_token: 'cs_token' + } +}; + +var mockBase64 = 'data:image/gif;base64,R0lGODlhDgAOAIAAAAAAAP///yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs='; + +bender.test( { + setUp: function() { + this.cloudservices = CKEDITOR.plugins.cloudservices; + }, + + 'test plugin exposes loader': function() { + assert.isInstanceOf( Function, this.cloudservices.cloudSericesLoader, 'cloudServicesLoader property type' ); + }, + + 'test loader uses config url/token': function() { + var instance = new this.cloudservices.cloudSericesLoader( this.editor, mockBase64 ), + // Stub loader.xhr methods before it's actually called. + listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); + + try { + instance.upload(); + + // Make sure that configured URL has been requested. + sinon.assert.calledWithExactly( instance.xhr.open, 'POST', 'cs_url', true ); + + // Make sure that proper header has been added. + sinon.assert.calledWithExactly( instance.xhr.setRequestHeader, 'Authorization', 'cs_token' ); + + assert.areSame( 1, instance.xhr.send.callCount, 'Call count' ); + } catch ( e ) { + // Propagate. + throw e; + } finally { + // Always remove listener. + listener.removeListener(); + } + }, + + 'test loader allows url overriding': function() { + var instance = new this.cloudservices.cloudSericesLoader( this.editor, mockBase64 ), + // Stub loader.xhr methods before it's actually called. + listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); + + try { + instance.upload( 'my_custom_url' ); + + sinon.assert.calledWithExactly( instance.xhr.open, 'POST', 'my_custom_url', true ); + + assert.areSame( 1, instance.xhr.send.callCount, 'Call count' ); + } catch ( e ) { + // Propagate. + throw e; + } finally { + // Always remove listener. + listener.removeListener(); + } + }, + + // Common fileUploadRequest listener reused by tests. + commonRequestListener: function( evt ) { + var loader = evt.data.fileLoader; + + sinon.stub( loader.xhr, 'open' ); + sinon.stub( loader.xhr, 'send' ); + sinon.stub( loader.xhr, 'setRequestHeader' ); + } +} ); \ No newline at end of file From fd91cb305e88a177c2a0ce992bbe87237f79ef6c Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 17 Oct 2017 14:30:30 +0200 Subject: [PATCH 114/642] Added a copyright note. --- plugins/cloudservices/plugin.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/cloudservices/plugin.js b/plugins/cloudservices/plugin.js index 85a15bcfa34..dcf50d5e90a 100644 --- a/plugins/cloudservices/plugin.js +++ b/plugins/cloudservices/plugin.js @@ -1,3 +1,8 @@ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + ( function() { 'use strict'; From bb107c56f6e6155037e28d02f2e9845d1d1d87cc Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 17 Oct 2017 14:42:31 +0200 Subject: [PATCH 115/642] Test: fixed cloud services API typo. --- tests/plugins/cloudservices/unit.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/plugins/cloudservices/unit.js b/tests/plugins/cloudservices/unit.js index f70076bcf52..f787f75d859 100644 --- a/tests/plugins/cloudservices/unit.js +++ b/tests/plugins/cloudservices/unit.js @@ -15,11 +15,11 @@ bender.test( { }, 'test plugin exposes loader': function() { - assert.isInstanceOf( Function, this.cloudservices.cloudSericesLoader, 'cloudServicesLoader property type' ); + assert.isInstanceOf( Function, this.cloudservices.cloudServicesLoader, 'cloudServicesLoader property type' ); }, 'test loader uses config url/token': function() { - var instance = new this.cloudservices.cloudSericesLoader( this.editor, mockBase64 ), + var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), // Stub loader.xhr methods before it's actually called. listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); @@ -43,7 +43,7 @@ bender.test( { }, 'test loader allows url overriding': function() { - var instance = new this.cloudservices.cloudSericesLoader( this.editor, mockBase64 ), + var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), // Stub loader.xhr methods before it's actually called. listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); From c6738f307c45a133aed37f3a9940ed852d944ee7 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 18 Oct 2017 13:31:03 +0200 Subject: [PATCH 116/642] Code style: type variable identifier should be upper cased. --- plugins/cloudservices/plugin.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/cloudservices/plugin.js b/plugins/cloudservices/plugin.js index dcf50d5e90a..e41365b8c47 100644 --- a/plugins/cloudservices/plugin.js +++ b/plugins/cloudservices/plugin.js @@ -22,11 +22,11 @@ * @class CKEDITOR.plugins.cloudservices.cloudServicesLoader * @extends CKEDITOR.fileTools.fileLoader */ - function cloudServicesLoader( editor, fileOrData, fileName ) { + function CloudServicesLoader( editor, fileOrData, fileName ) { FileLoader.call( this, editor, fileOrData, fileName ); } - cloudServicesLoader.prototype = CKEDITOR.tools.extend( {}, FileLoader.prototype ); + CloudServicesLoader.prototype = CKEDITOR.tools.extend( {}, FileLoader.prototype ); /** * @inheritdoc @@ -34,7 +34,7 @@ * @param {Object} [additionalRequestParameters] Additional data that would be passed to the * {@link CKEDITOR.editor#fileUploadRequest} event. */ - cloudServicesLoader.prototype.upload = function( url, additionalRequestParameters ) { + CloudServicesLoader.prototype.upload = function( url, additionalRequestParameters ) { url = url || this.editor.config.cloudServices_url; FileLoader.prototype.upload.call( this, url, additionalRequestParameters ); @@ -48,7 +48,7 @@ * the {@link CKEDITOR.editor#fileUploadRequest} event. */ - CKEDITOR.plugins.cloudservices.cloudServicesLoader = cloudServicesLoader; + CKEDITOR.plugins.cloudservices.cloudServicesLoader = CloudServicesLoader; }, beforeInit: function( editor ) { From 3147eb2fa5949746bb446489ad637551a88c116e Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 18 Oct 2017 14:28:44 +0200 Subject: [PATCH 117/642] Added a possibility to customize Cloud Service token. --- plugins/cloudservices/plugin.js | 22 ++++++++++++++++++++-- tests/plugins/cloudservices/unit.js | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/plugins/cloudservices/plugin.js b/plugins/cloudservices/plugin.js index e41365b8c47..dcd10255006 100644 --- a/plugins/cloudservices/plugin.js +++ b/plugins/cloudservices/plugin.js @@ -21,9 +21,27 @@ * @since 4.8.0 * @class CKEDITOR.plugins.cloudservices.cloudServicesLoader * @extends CKEDITOR.fileTools.fileLoader + * @constructor + * @inheritdoc + * @param {CKEDITOR.editor} editor The editor instance. Used only to get language data. + * @param {Blob/String} fileOrData A [blob object](https://developer.mozilla.org/en/docs/Web/API/Blob) or a data + * string encoded with Base64. + * @param {String} [fileName] The file name. If not set and the second parameter is a file, then its name will be used. + * If not set and the second parameter is a Base64 data string, then the file name will be created based on + * the {@link CKEDITOR.config#fileTools_defaultFileName} option. + * @param {String} [token] A token used for [Cloud Service](https://ckeditor.com/ckeditor-cloud-services/) request. If + * skipped {@link CKEDITOR.config#cloudServices_token} will be used. */ - function CloudServicesLoader( editor, fileOrData, fileName ) { + function CloudServicesLoader( editor, fileOrData, fileName, token ) { FileLoader.call( this, editor, fileOrData, fileName ); + + /** + * Custom [Cloud Service](https://ckeditor.com/ckeditor-cloud-services/) token. + * + * @property {String} custom_token + * @member CKEDITOR.plugins.cloudservices.cloudServicesLoader + */ + this.customToken = token; } CloudServicesLoader.prototype = CKEDITOR.tools.extend( {}, FileLoader.prototype ); @@ -62,7 +80,7 @@ delete reqData.upload; // Add authorization token. - evt.data.fileLoader.xhr.setRequestHeader( 'Authorization', editor.config.cloudServices_token ); + evt.data.fileLoader.xhr.setRequestHeader( 'Authorization', fileLoader.customToken || editor.config.cloudServices_token ); } }, null, null, 6 ); diff --git a/tests/plugins/cloudservices/unit.js b/tests/plugins/cloudservices/unit.js index f787f75d859..68e3cc25503 100644 --- a/tests/plugins/cloudservices/unit.js +++ b/tests/plugins/cloudservices/unit.js @@ -62,6 +62,26 @@ bender.test( { } }, + 'test loader allows token overriding': function() { + var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64, null, 'different_token' ), + // Stub loader.xhr methods before it's actually called. + listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); + + try { + instance.upload(); + + sinon.assert.calledWithExactly( instance.xhr.setRequestHeader, 'Authorization', 'different_token' ); + + assert.areSame( 1, instance.xhr.send.callCount, 'Call count' ); + } catch ( e ) { + // Propagate. + throw e; + } finally { + // Always remove listener. + listener.removeListener(); + } + }, + // Common fileUploadRequest listener reused by tests. commonRequestListener: function( evt ) { var loader = evt.data.fileLoader; From dc73325a67510f9fcd4afe0c2148416b78a8be34 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 18 Oct 2017 16:16:29 +0200 Subject: [PATCH 118/642] Docs: corrected property name. --- plugins/cloudservices/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cloudservices/plugin.js b/plugins/cloudservices/plugin.js index dcd10255006..0eeec9831e8 100644 --- a/plugins/cloudservices/plugin.js +++ b/plugins/cloudservices/plugin.js @@ -38,7 +38,7 @@ /** * Custom [Cloud Service](https://ckeditor.com/ckeditor-cloud-services/) token. * - * @property {String} custom_token + * @property {String} customToken * @member CKEDITOR.plugins.cloudservices.cloudServicesLoader */ this.customToken = token; From 31104eb81202bb8716939746d4453c289434573c Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 18 Oct 2017 15:03:10 +0200 Subject: [PATCH 119/642] Reuse Cloud Services loader for Easy Image. --- plugins/easyimage/plugin.js | 84 ++----------------------------------- 1 file changed, 3 insertions(+), 81 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index e695081c5bb..5495773bb6a 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -150,6 +150,8 @@ loadMethod: 'loadAndUpload', + loaderType: CKEDITOR.plugins.cloudservices.fileLoader, + additionalRequestParameters: { isEasyImage: true }, @@ -176,86 +178,6 @@ srcset + '" sizes="100vw">' ); } } ); - - editor.on( 'fileUploadRequest', function( evt ) { - var requestData = evt.data.requestData; - - if ( !requestData.isEasyImage ) { - return; - } - - evt.data.requestData.file = evt.data.requestData.upload; - delete evt.data.requestData.upload; - - // This property is used by fileUploadResponse callback to identify EI requests. - evt.data.fileLoader.isEasyImage = true; - - evt.data.fileLoader.xhr.setRequestHeader( 'Authorization', editor.config.easyimage_token ); - } ); - - editor.on( 'fileUploadResponse', function( evt ) { - var fileLoader = evt.data.fileLoader, - xhr = fileLoader.xhr, - response; - - if ( !fileLoader.isEasyImage ) { - return; - } - - evt.stop(); - - try { - response = JSON.parse( xhr.responseText ); - - evt.data.response = response; - } catch ( e ) { - CKEDITOR.warn( 'filetools-response-error', { responseText: xhr.responseText } ); - } - } ); - - // Handle images which are not available in the dataTransfer. - // This means that we need to read them from the elements. - editor.on( 'paste', function( evt ) { - var fileTools = CKEDITOR.fileTools; - - // For performance reason do not parse data if it does not contain img tag and data attribute. - if ( !evt.data.dataValue.match( / Date: Wed, 18 Oct 2017 17:03:09 +0200 Subject: [PATCH 120/642] Corrected Cloud Services loader type name after recent refactoring. --- plugins/easyimage/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 5495773bb6a..6c92f3b67e6 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -150,7 +150,7 @@ loadMethod: 'loadAndUpload', - loaderType: CKEDITOR.plugins.cloudservices.fileLoader, + loaderType: CKEDITOR.plugins.cloudservices.cloudServicesLoader, additionalRequestParameters: { isEasyImage: true From 359ead745c0b33aa597379cae423d4b63ea4a7fb Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 18 Oct 2017 17:16:58 +0200 Subject: [PATCH 121/642] Further simplify widget definition, update sample. --- plugins/easyimage/plugin.js | 8 -------- plugins/easyimage/samples/easyimage.html | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 6c92f3b67e6..0d125b570c9 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -141,21 +141,13 @@ } function registerUploadWidget( editor ) { - var uploadUrl = CKEDITOR.fileTools.getUploadUrl( editor.config, 'easyimage' ); - CKEDITOR.fileTools.addUploadWidget( editor, 'uploadeasyimage', { supportedTypes: /image\/(jpeg|png|gif|bmp)/, - uploadUrl: uploadUrl, - loadMethod: 'loadAndUpload', loaderType: CKEDITOR.plugins.cloudservices.cloudServicesLoader, - additionalRequestParameters: { - isEasyImage: true - }, - fileToElement: function() { var img = new CKEDITOR.dom.element( 'img' ); img.setAttribute( 'src', loadingImage ); diff --git a/plugins/easyimage/samples/easyimage.html b/plugins/easyimage/samples/easyimage.html index fdd58fbdfdf..19c9ab6f769 100644 --- a/plugins/easyimage/samples/easyimage.html +++ b/plugins/easyimage/samples/easyimage.html @@ -110,8 +110,8 @@

Apollo 11

getToken( function( token ) { CKEDITOR.replace( 'editor', { extraPlugins: 'easyimage', - easyimageUploadUrl: 'https://files.cke-cs.com/upload/', - easyimage_token: token, + cloudServices_url: 'https://files.cke-cs.com/upload/', + cloudServices_token: token, height: 500 } ); } ); From c49f4dc0b7e9fcefe745961c5b69f183bdfe99e9 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 16 Oct 2017 13:58:18 +0200 Subject: [PATCH 122/642] Allow to specify a different fileLoader type. --- plugins/filetools/plugin.js | 6 ++++-- plugins/uploadwidget/plugin.js | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/filetools/plugin.js b/plugins/filetools/plugin.js index 7fc3d173307..97cca07d3fd 100644 --- a/plugins/filetools/plugin.js +++ b/plugins/filetools/plugin.js @@ -156,9 +156,11 @@ * @param {String} fileName See {@link CKEDITOR.fileTools.fileLoader}. * @returns {CKEDITOR.fileTools.fileLoader} The created file loader instance. */ - create: function( fileOrData, fileName ) { + create: function( fileOrData, fileName, loaderType ) { + loaderType = loaderType || FileLoader; + var id = this.loaders.length, - loader = new FileLoader( this.editor, fileOrData, fileName ); + loader = new loaderType( this.editor, fileOrData, fileName ); loader.id = id; this.loaders[ id ] = loader; diff --git a/plugins/uploadwidget/plugin.js b/plugins/uploadwidget/plugin.js index dd5209eafc9..faa13b06ebc 100644 --- a/plugins/uploadwidget/plugin.js +++ b/plugins/uploadwidget/plugin.js @@ -190,7 +190,7 @@ // No def.supportedTypes means all types are supported. if ( !def.supportedTypes || fileTools.isTypeSupported( file, def.supportedTypes ) ) { var el = def.fileToElement( file ), - loader = uploads.create( file ); + loader = uploads.create( file, undefined, def.loaderType ); if ( el ) { loader[ loadMethod ]( def.uploadUrl, def.additionalRequestParameters ); From 1fa2c1a2615cfb065117a7b1ff42047b9eca48e7 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 18 Oct 2017 15:08:42 +0200 Subject: [PATCH 123/642] Docs: added API docs for loader type customization. --- plugins/filetools/plugin.js | 2 ++ plugins/uploadwidget/plugin.js | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/plugins/filetools/plugin.js b/plugins/filetools/plugin.js index 97cca07d3fd..8f2eb0492ac 100644 --- a/plugins/filetools/plugin.js +++ b/plugins/filetools/plugin.js @@ -154,6 +154,8 @@ * * @param {Blob/String} fileOrData See {@link CKEDITOR.fileTools.fileLoader}. * @param {String} fileName See {@link CKEDITOR.fileTools.fileLoader}. + * @param {Function} [loaderType] Loader type to be created. If skipped the default {@link CKEDITOR.fileTools.fileLoader} + * type will be used. * @returns {CKEDITOR.fileTools.fileLoader} The created file loader instance. */ create: function( fileOrData, fileName, loaderType ) { diff --git a/plugins/uploadwidget/plugin.js b/plugins/uploadwidget/plugin.js index faa13b06ebc..af580653674 100644 --- a/plugins/uploadwidget/plugin.js +++ b/plugins/uploadwidget/plugin.js @@ -365,6 +365,12 @@ * @property {String} [uploadUrl] */ + /** + * Loader type that should be used for creating fileTools requests. + * + * @property {Function} [loaderType] + */ + /** * An object containing additional data that should be passed to the function defined by {@link #loadMethod}. * From 37c920a4ed54293bc875e254482609909a54c21e Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 18 Oct 2017 16:33:49 +0200 Subject: [PATCH 124/642] Tests: added tests for customizing loader type. --- tests/plugins/filetools/filetools.js | 9 +++++++++ tests/plugins/uploadwidget/uploadwidget.js | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/tests/plugins/filetools/filetools.js b/tests/plugins/filetools/filetools.js index 43ae33dfdcb..adcbb8771b7 100644 --- a/tests/plugins/filetools/filetools.js +++ b/tests/plugins/filetools/filetools.js @@ -133,6 +133,15 @@ assert.isUndefined( repository.loaders[ 2 ] ); }, + 'test UploadRepository.create allows changing fileLoader type': function() { + function CustomType() { + } + + var repository = this.editor.uploadRepository, + loader = repository.create( { name: 'name' }, undefined, CustomType ); + + assert.isInstanceOf( CustomType, loader, 'Returned loader type' ); + }, 'test UploadRepository instanceCreated event': function() { var repository = this.editor.uploadRepository, diff --git a/tests/plugins/uploadwidget/uploadwidget.js b/tests/plugins/uploadwidget/uploadwidget.js index c7e7c581846..82a748d86e7 100644 --- a/tests/plugins/uploadwidget/uploadwidget.js +++ b/tests/plugins/uploadwidget/uploadwidget.js @@ -537,6 +537,28 @@ wait(); }, + 'test custom def.loaderType': function() { + var editor = mockEditorForPaste(), + uploadStub = sinon.stub(); + + function CustomLoaderType() { + this.upload = uploadStub; + } + + addTestUploadWidget( editor, 'loadMethodLoad', { + loaderType: CustomLoaderType, + loadMethod: 'upload' + } ); + + resumeAfter( editor, 'paste', function() { + assert.areSame( 1, uploadStub.callCount, 'CustomLoaderType.upload call count' ); + } ); + + pasteFiles( editor, [ bender.tools.getTestPngFile( 'test1.png' ) ] ); + + wait(); + }, + 'test paste multiple files': function() { var editor = mockEditorForPaste(); From 1b59a000fc24fd97851e364eccf36419327bdb46 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 18 Oct 2017 19:46:52 +0200 Subject: [PATCH 125/642] Update widget name in test. --- tests/plugins/uploadwidget/uploadwidget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/uploadwidget/uploadwidget.js b/tests/plugins/uploadwidget/uploadwidget.js index 82a748d86e7..f11b69a1f57 100644 --- a/tests/plugins/uploadwidget/uploadwidget.js +++ b/tests/plugins/uploadwidget/uploadwidget.js @@ -545,7 +545,7 @@ this.upload = uploadStub; } - addTestUploadWidget( editor, 'loadMethodLoad', { + addTestUploadWidget( editor, 'customLoaderType', { loaderType: CustomLoaderType, loadMethod: 'upload' } ); From d68cfea3b93b69fba44aeaad1579f07eccd5ebf4 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 19 Oct 2017 15:14:55 +0200 Subject: [PATCH 126/642] Updated API to recent test suite changes. Restored paste handler for base64 encoded images. --- plugins/easyimage/plugin.js | 44 +++++++++++++++++++++++++ tests/plugins/easyimage/uploadwidget.js | 21 +++++++++--- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 0d125b570c9..1971c2f3a19 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -170,6 +170,50 @@ srcset + '" sizes="100vw">' ); } } ); + + // Handle images which are not available in the dataTransfer. + // This means that we need to read them from the elements. + editor.on( 'paste', function( evt ) { + var fileTools = CKEDITOR.fileTools; + + // For performance reason do not parse data if it does not contain img tag and data attribute. + if ( !evt.data.dataValue.match( / Date: Thu, 19 Oct 2017 15:16:51 +0200 Subject: [PATCH 127/642] We no longer need to check for upload url, as Cloud Services will automatically use the one from the config. --- tests/plugins/easyimage/uploadwidget.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index 7a9f0dbc4ac..fb6022d0cc2 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -7,7 +7,7 @@ 'use strict'; ( function() { - var uploadCount, loadAndUploadCount, lastUploadUrl, resumeAfter, tests, + var uploadCount, loadAndUploadCount, resumeAfter, tests, IMG_URL = '%BASE_PATH%_assets/logo.png', DATA_IMG = 'data:', BLOB_IMG = 'blob:'; @@ -74,18 +74,16 @@ resumeAfter = bender.tools.resumeAfter; - CKEDITOR.fileTools.fileLoader.prototype.loadAndUpload = function( url ) { + CKEDITOR.fileTools.fileLoader.prototype.loadAndUpload = function() { loadAndUploadCount++; - lastUploadUrl = url; this.responseData = CKEDITOR.tools.clone( responseData ); }; CKEDITOR.fileTools.fileLoader.prototype.load = function() {}; - CKEDITOR.fileTools.fileLoader.prototype.upload = function( url ) { + CKEDITOR.fileTools.fileLoader.prototype.upload = function() { uploadCount++; - lastUploadUrl = url; this.responseData = CKEDITOR.tools.clone( responseData ); }; @@ -142,7 +140,6 @@ assert.areSame( 1, loadAndUploadCount ); assert.areSame( 0, uploadCount ); - assert.areSame( 'http://foo/upload', lastUploadUrl ); } ); }, @@ -172,7 +169,6 @@ assert.areSame( 0, loadAndUploadCount ); assert.areSame( 1, uploadCount ); - assert.areSame( 'http://foo/upload', lastUploadUrl ); } ); } ); }, From 07c1f4b021fb04d53bad0fcf69e33a2a1108d63d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 23 Oct 2017 12:37:24 +0200 Subject: [PATCH 128/642] Extracted common config. --- tests/plugins/easyimage/uploadwidget.js | 26 +++++++++---------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index fb6022d0cc2..be0bc96a98b 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -10,36 +10,28 @@ var uploadCount, loadAndUploadCount, resumeAfter, tests, IMG_URL = '%BASE_PATH%_assets/logo.png', DATA_IMG = 'data:', - BLOB_IMG = 'blob:'; + BLOB_IMG = 'blob:', + commonConfig = { + cloudServices_url: 'http://foo/upload', + // Disable pasteFilter on Webkits (pasteFilter defaults semantic-text on Webkits). + pasteFilter: null + }; bender.editors = { classic: { name: 'classic', - config: { - cloudServices_url: 'http://foo/upload', - // Disable pasteFilter on Webkits (pasteFilter defaults semantic-text on Webkits). - pasteFilter: null - } + config: commonConfig }, divarea: { name: 'divarea', - config: { - extraPlugins: 'divarea', - cloudServices_url: 'http://foo/upload', - // Disable pasteFilter on Webkits (pasteFilter defaults semantic-text on Webkits). - pasteFilter: null - } + config: CKEDITOR.tools.extend( { extraPlugins: 'divarea' }, commonConfig ) }, inline: { name: 'inline', creator: 'inline', - config: { - cloudServices_url: 'http://foo/upload', - // Disable pasteFilter on Webkits (pasteFilter defaults semantic-text on Webkits). - pasteFilter: null - } + config: commonConfig } }; From 16e02e03f1c2f22fe3bff78e254ffb6ae077f8f4 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 23 Oct 2017 14:03:25 +0200 Subject: [PATCH 129/642] Added some comments about easy image uploading unit tests. --- tests/plugins/easyimage/uploadwidget.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index be0bc96a98b..c0e2e5e0ba6 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -4,9 +4,9 @@ /* bender-include: %BASE_PATH%/plugins/uploadfile/_helpers/waitForImage.js */ /* global pasteFiles, waitForImage */ -'use strict'; - ( function() { + 'use strict'; + var uploadCount, loadAndUploadCount, resumeAfter, tests, IMG_URL = '%BASE_PATH%_assets/logo.png', DATA_IMG = 'data:', @@ -50,6 +50,8 @@ CKEDITOR.on( 'instanceCreated', function() { if ( !CKEDITOR.plugins.cloudservices.cloudServicesLoader.restore ) { + // Because of #1068 we can't provide loaderType directly. Instead we just replace cloudServicesLoader + // with our loader stub that is going to be customized in init method. sinon.stub( CKEDITOR.plugins.cloudservices, 'cloudServicesLoader', CKEDITOR.fileTools.fileLoader ); } } ); @@ -66,6 +68,8 @@ resumeAfter = bender.tools.resumeAfter; + // This tests suite could be made much prettier, it would require #1068 to be resolved. Then you + // could just use LoaderStub type with stubbed methods, rather than overwrite base FileLoader type. CKEDITOR.fileTools.fileLoader.prototype.loadAndUpload = function() { loadAndUploadCount++; @@ -80,7 +84,8 @@ this.responseData = CKEDITOR.tools.clone( responseData ); }; - // Further hacking, now stub can be safely removed, as it's used only in plugin.init, which has already been called. + // Now stub can be safely removed, as it's used only in plugin.init, which has already been called, + // this workaround could be removed once #1068 is fixed. if ( CKEDITOR.plugins.cloudservices.cloudServicesLoader.restore ) { CKEDITOR.plugins.cloudservices.cloudServicesLoader.restore(); } From 2a63216cf408660cbac23e97b8ad3db64d97d8a1 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 23 Oct 2017 14:17:37 +0200 Subject: [PATCH 130/642] Simplified tests, by fixing #1068 issue in listener for easyimage (only). --- plugins/easyimage/plugin.js | 3 ++- tests/plugins/easyimage/uploadwidget.js | 23 ++++------------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 1971c2f3a19..8c215012a1c 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -184,6 +184,7 @@ var data = evt.data, // Prevent XSS attacks. tempDoc = document.implementation.createHTMLDocument( '' ), + widgetDef = editor.widgets.registered.uploadeasyimage, temp = new CKEDITOR.dom.element( tempDoc.body ), imgs, img, i; @@ -203,7 +204,7 @@ // We are not uploading images in non-editable blocs and fake objects (http://dev.ckeditor.com/ticket/13003). if ( isDataInSrc && isRealObject && !img.data( 'cke-upload-id' ) && !img.isReadOnly( 1 ) ) { - var loader = editor.uploadRepository.create( img.getAttribute( 'src' ) ); + var loader = editor.uploadRepository.create( img.getAttribute( 'src' ), undefined, widgetDef.loaderType ); loader.upload(); fileTools.markElement( img, 'uploadeasyimage', loader.id ); diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index c0e2e5e0ba6..4a04d17b027 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -48,14 +48,6 @@ } } - CKEDITOR.on( 'instanceCreated', function() { - if ( !CKEDITOR.plugins.cloudservices.cloudServicesLoader.restore ) { - // Because of #1068 we can't provide loaderType directly. Instead we just replace cloudServicesLoader - // with our loader stub that is going to be customized in init method. - sinon.stub( CKEDITOR.plugins.cloudservices, 'cloudServicesLoader', CKEDITOR.fileTools.fileLoader ); - } - } ); - tests = { init: function() { var responseData = { @@ -68,27 +60,20 @@ resumeAfter = bender.tools.resumeAfter; - // This tests suite could be made much prettier, it would require #1068 to be resolved. Then you - // could just use LoaderStub type with stubbed methods, rather than overwrite base FileLoader type. - CKEDITOR.fileTools.fileLoader.prototype.loadAndUpload = function() { + // Approach taken from tests/plugins/uploadwidget/uploadwidget.js test. + CKEDITOR.plugins.cloudservices.cloudServicesLoader.prototype.loadAndUpload = function() { loadAndUploadCount++; this.responseData = CKEDITOR.tools.clone( responseData ); }; - CKEDITOR.fileTools.fileLoader.prototype.load = function() {}; + CKEDITOR.plugins.cloudservices.cloudServicesLoader.prototype.load = function() {}; - CKEDITOR.fileTools.fileLoader.prototype.upload = function() { + CKEDITOR.plugins.cloudservices.cloudServicesLoader.prototype.upload = function() { uploadCount++; this.responseData = CKEDITOR.tools.clone( responseData ); }; - - // Now stub can be safely removed, as it's used only in plugin.init, which has already been called, - // this workaround could be removed once #1068 is fixed. - if ( CKEDITOR.plugins.cloudservices.cloudServicesLoader.restore ) { - CKEDITOR.plugins.cloudservices.cloudServicesLoader.restore(); - } }, setUp: function() { From 6141f99450f1d44f43b51d648e973c35514d2085 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 23 Oct 2017 14:36:01 +0200 Subject: [PATCH 131/642] Changed easyimage not to call load method (as it does it handles it manually better than default FileLoader type). --- plugins/easyimage/plugin.js | 3 ++- tests/plugins/easyimage/uploadwidget.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 8c215012a1c..88867f28151 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -144,7 +144,8 @@ CKEDITOR.fileTools.addUploadWidget( editor, 'uploadeasyimage', { supportedTypes: /image\/(jpeg|png|gif|bmp)/, - loadMethod: 'loadAndUpload', + // Easy image uses only upload method, as is manually handled in onUploading function. + loadMethod: 'upload', loaderType: CKEDITOR.plugins.cloudservices.cloudServicesLoader, diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index 4a04d17b027..7c21c2e6fb7 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -120,8 +120,8 @@ assert.sameData( '

', editor.getData() ); assert.areSame( 1, editor.editable().find( 'img[data-widget="image"]' ).count() ); - assert.areSame( 1, loadAndUploadCount ); - assert.areSame( 0, uploadCount ); + assert.areSame( 0, loadAndUploadCount ); + assert.areSame( 1, uploadCount ); } ); }, From 8d54a054001cafdf92ab663ced6b9a39fe650729 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 23 Oct 2017 18:08:23 +0200 Subject: [PATCH 132/642] Allow upload URL to be configurable. Now it can be configured using widgetDefinition.uploadUrl (on uploadeasyimage widget). So one can use simply `widgetDefinition` event on editor to customize the upload URL if there's a need to. --- plugins/easyimage/plugin.js | 2 +- tests/plugins/easyimage/uploadwidget.js | 33 ++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 88867f28151..4e1745a7b36 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -206,7 +206,7 @@ // We are not uploading images in non-editable blocs and fake objects (http://dev.ckeditor.com/ticket/13003). if ( isDataInSrc && isRealObject && !img.data( 'cke-upload-id' ) && !img.isReadOnly( 1 ) ) { var loader = editor.uploadRepository.create( img.getAttribute( 'src' ), undefined, widgetDef.loaderType ); - loader.upload(); + loader.upload( widgetDef.uploadUrl, widgetDef.additionalRequestParameters ); fileTools.markElement( img, 'uploadeasyimage', loader.id ); diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index 7c21c2e6fb7..0d34a21f56f 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -69,11 +69,10 @@ CKEDITOR.plugins.cloudservices.cloudServicesLoader.prototype.load = function() {}; - CKEDITOR.plugins.cloudservices.cloudServicesLoader.prototype.upload = function() { + sinon.stub( CKEDITOR.plugins.cloudservices.cloudServicesLoader.prototype, 'upload', function() { uploadCount++; - this.responseData = CKEDITOR.tools.clone( responseData ); - }; + } ); }, setUp: function() { @@ -94,6 +93,10 @@ if ( CKEDITOR.fileTools.bindNotifications.reset ) { CKEDITOR.fileTools.bindNotifications.reset(); } + + if ( CKEDITOR.plugins.cloudservices.cloudServicesLoader.prototype.upload.reset ) { + CKEDITOR.plugins.cloudservices.cloudServicesLoader.prototype.upload.reset(); + } }, 'test classic with easyimage (integration test)': function( editor ) { @@ -426,6 +429,30 @@ } ); } ); + wait(); + }, + + 'test cloudservices URL can be customized': function( editor ) { + var originalUploadUrl = editor.widgets.registered.uploadeasyimage.uploadUrl, + loader; + + // Upload widget might have an uploadUrl changed in definition, allowing for upload URL customization. + editor.widgets.registered.uploadeasyimage.uploadUrl = 'https://customDomain.localhost/endpoint'; + + resumeAfter( editor, 'paste', function() { + // Restore original value. + editor.widgets.registered.uploadeasyimage.uploadUrl = originalUploadUrl; + + loader = editor.uploadRepository.loaders[ 0 ]; + + sinon.assert.calledWith( loader.upload, 'https://customDomain.localhost/endpoint' ); + assert.isTrue( true ); + } ); + + editor.fire( 'paste', { + dataValue: '' + } ); + wait(); } }; From 05d47e172ff3d1df8c43d6c08c934775237f238c Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 24 Oct 2017 11:13:58 +0200 Subject: [PATCH 133/642] Fix codestyle issue. --- tests/plugins/easyimage/uploadwidget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index 0d34a21f56f..c11bcad431a 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -53,11 +53,11 @@ var responseData = { response: { 100: IMG_URL, - 200: IMG_URL, - default: IMG_URL + 200: IMG_URL } }; + responseData.response[ 'default' ] = IMG_URL; resumeAfter = bender.tools.resumeAfter; // Approach taken from tests/plugins/uploadwidget/uploadwidget.js test. From d481384e5b247c1d422fd16a8c8c722ccaa89103 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 24 Oct 2017 17:27:05 +0200 Subject: [PATCH 134/642] Fixed an issue where Firefox would cause multiple img load events for a single image. --- tests/plugins/uploadfile/_helpers/waitForImage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/uploadfile/_helpers/waitForImage.js b/tests/plugins/uploadfile/_helpers/waitForImage.js index e6b566222b6..1a8dbc55c6a 100644 --- a/tests/plugins/uploadfile/_helpers/waitForImage.js +++ b/tests/plugins/uploadfile/_helpers/waitForImage.js @@ -5,7 +5,7 @@ function waitForImage( image, callback ) { if ( CKEDITOR.env.ie ) { wait( callback, 100 ); } else { - image.on( 'load', function() { + image.once( 'load', function() { resume( callback ); } ); wait(); From 026f09e2b23877dd36ebb79a3cbe19f6ec41f9f4 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 24 Oct 2017 17:37:03 +0200 Subject: [PATCH 135/642] Added test cases for Easy Image loader / HTTP request params customization. --- tests/plugins/easyimage/uploadwidget.js | 45 ++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index c11bcad431a..f3034d38e1f 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -432,20 +432,24 @@ wait(); }, - 'test cloudservices URL can be customized': function( editor ) { - var originalUploadUrl = editor.widgets.registered.uploadeasyimage.uploadUrl, + 'test cloudservices URL/request params can be customized': function( editor ) { + var uploadEasyImageDef = editor.widgets.registered.uploadeasyimage, + originalUploadUrl = uploadEasyImageDef.uploadUrl, + originalAdditionalParams = uploadEasyImageDef.additionalRequestParameters, loader; // Upload widget might have an uploadUrl changed in definition, allowing for upload URL customization. - editor.widgets.registered.uploadeasyimage.uploadUrl = 'https://customDomain.localhost/endpoint'; + uploadEasyImageDef.uploadUrl = 'https://customDomain.localhost/endpoint'; + uploadEasyImageDef.additionalRequestParameters = { a: 1 }; resumeAfter( editor, 'paste', function() { // Restore original value. - editor.widgets.registered.uploadeasyimage.uploadUrl = originalUploadUrl; + uploadEasyImageDef.uploadUrl = originalUploadUrl; + uploadEasyImageDef.additionalRequestParameters = originalAdditionalParams; loader = editor.uploadRepository.loaders[ 0 ]; - sinon.assert.calledWith( loader.upload, 'https://customDomain.localhost/endpoint' ); + sinon.assert.calledWith( loader.upload, 'https://customDomain.localhost/endpoint', { a: 1 } ); assert.isTrue( true ); } ); @@ -453,6 +457,37 @@ dataValue: '' } ); + wait(); + }, + + 'test loader type can be customized': function( editor ) { + var uploadEasyImageDef = editor.widgets.registered.uploadeasyimage, + originalType = uploadEasyImageDef.loaderType, + CloudServicesLoader = CKEDITOR.plugins.cloudservices.cloudServicesLoader, + loader; + + function LoaderSubclass( editor, fileOrData, fileName, token ) { + CloudServicesLoader.call( this, editor, fileOrData, fileName, token ); + } + + LoaderSubclass.prototype = CKEDITOR.tools.extend( {}, CloudServicesLoader.prototype ); + + // Upload widget might have an uploadUrl changed in definition, allowing for upload URL customization. + uploadEasyImageDef.loaderType = LoaderSubclass; + + resumeAfter( editor, 'paste', function() { + // Restore original value. + uploadEasyImageDef.loaderType = originalType; + + loader = editor.uploadRepository.loaders[ 0 ]; + + assert.isInstanceOf( LoaderSubclass, loader, 'Loader type' ); + } ); + + editor.fire( 'paste', { + dataValue: '' + } ); + wait(); } }; From e0b0e29d261a262ef5a50ccacf1067b860139952 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 25 Oct 2017 11:18:37 +0200 Subject: [PATCH 136/642] Fix incorrect comment. --- tests/plugins/easyimage/uploadwidget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index f3034d38e1f..90de5cfa138 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -472,7 +472,7 @@ LoaderSubclass.prototype = CKEDITOR.tools.extend( {}, CloudServicesLoader.prototype ); - // Upload widget might have an uploadUrl changed in definition, allowing for upload URL customization. + // Upload widget might have a loaderType changed in definition, allowing for loader type customization. uploadEasyImageDef.loaderType = LoaderSubclass; resumeAfter( editor, 'paste', function() { From 1e511aa81f9ef86a10dbe73bca0d958ab69a56f8 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 6 Nov 2017 14:56:42 +0100 Subject: [PATCH 137/642] Add upcast method for img[srcset]. --- plugins/easyimage/plugin.js | 17 +++++++++++++++++ tests/plugins/easyimage/widget.html | 5 +++++ tests/plugins/easyimage/widget.js | 23 ++++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 4e1745a7b36..aa836dbe8ed 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -120,6 +120,23 @@ element.find( 'img' ).length === 1 ) { return element; } + }, + + // Upload widget creates bare img[srcset] elements, so we should also upcast them. + img: function( element ) { + if ( element.attributes.srcset ) { + var figure = new CKEDITOR.htmlParser.element( 'figure' ); + + if ( figureClass ) { + figure.attributes[ 'class' ] = figureClass; + } + + element.wrapWith( figure ); + + return figure; + } + + return false; } }, diff --git a/tests/plugins/easyimage/widget.html b/tests/plugins/easyimage/widget.html index 4af404f4fc9..4336d593b03 100644 --- a/tests/plugins/easyimage/widget.html +++ b/tests/plugins/easyimage/widget.html @@ -11,3 +11,8 @@
Figure without image
+ +
+ fig1 + fig1 +
diff --git a/tests/plugins/easyimage/widget.js b/tests/plugins/easyimage/widget.js index 8cf24dcc733..5a2c810e94d 100644 --- a/tests/plugins/easyimage/widget.js +++ b/tests/plugins/easyimage/widget.js @@ -28,7 +28,7 @@ }; var tests = { - 'test upcasting image widget': function( editor, bot ) { + 'test upcasting image widget (figure)': function( editor, bot ) { widgetTestsTools.assertWidget( { count: editor.name === 'classicAllFigures' ? 2 : 1, widgetOffset: 0, @@ -36,6 +36,27 @@ html: CKEDITOR.document.getById( 'mixedFigures' ).getHtml(), bot: bot } ); + }, + + 'test upcasting image widget (img)': function( editor, bot ) { + widgetTestsTools.assertWidget( { + count: 1, + widgetOffset: 0, + nameCreated: 'easyimage', + html: CKEDITOR.document.getById( 'mixedImgs' ).getHtml(), + bot: bot, + assertCreated: function( widget ) { + var element = widget.element; + + assert.areSame( 'figure', element.getName(), 'img is wrapped in figure' ); + + if ( editor.name !== 'classicAllFigures' ) { + assert.isTrue( element.hasClass( 'easyimage' ), 'figure has appropriate class' ); + } else { + assert.isFalse( element.hasClass( 'easyimage' ), 'figure does not have class' ); + } + } + } ); } }; From 862fb4b0c49c1b555985004e878cdb873e19d074 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 6 Nov 2017 15:02:02 +0100 Subject: [PATCH 138/642] Update uploadwidget tests. --- tests/plugins/easyimage/uploadwidget.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index 90de5cfa138..9536e787384 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -11,6 +11,9 @@ IMG_URL = '%BASE_PATH%_assets/logo.png', DATA_IMG = 'data:', BLOB_IMG = 'blob:', + WIDGET_HTML = '
' + + '' + + '
', commonConfig = { cloudServices_url: 'http://foo/upload', // Disable pasteFilter on Webkits (pasteFilter defaults semantic-text on Webkits). @@ -120,8 +123,8 @@ loader.url = IMG_URL; loader.changeStatus( 'uploaded' ); - assert.sameData( '

', editor.getData() ); - assert.areSame( 1, editor.editable().find( 'img[data-widget="image"]' ).count() ); + assert.sameData( WIDGET_HTML, editor.getData() ); + assert.areSame( 1, editor.editable().find( '[data-widget="easyimage"]' ).count(), 'dupa' ); assert.areSame( 0, loadAndUploadCount ); assert.areSame( 1, uploadCount ); @@ -149,8 +152,9 @@ loader.url = IMG_URL; loader.changeStatus( 'uploaded' ); - assert.sameData( '

xx

', editor.getData() ); - assert.areSame( 1, editor.editable().find( 'img[data-widget="image"]' ).count() ); + assert.sameData( '

x

' + WIDGET_HTML + '

x

', + editor.getData() ); + assert.areSame( 1, editor.editable().find( '[data-widget="easyimage"]' ).count() ); assert.areSame( 0, loadAndUploadCount ); assert.areSame( 1, uploadCount ); From 5c86f152877bc5d89fbac5cd6d4d5303c82be04a Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 6 Nov 2017 17:35:44 +0100 Subject: [PATCH 139/642] Docs: removed unused Easy Image config docs. --- plugins/easyimage/plugin.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index aa836dbe8ed..6cbd4d57c87 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -321,20 +321,4 @@ * @member CKEDITOR.config */ CKEDITOR.config.easyimage_sideClass = 'easyimage-side'; - - /** - * The URL where images inserted by Easy Image plugin should be uploaded. - * - * @since 4.8.0 - * @cfg {String} [easyimageUploadUrl='' (empty string = disabled)] - * @member CKEDITOR.config - */ - - /** - * Token used for authorization while uploading images via Easy Image plugin. - * - * @since 4.8.0 - * @cfg {String} [easyimage_token='' (empty string = disabled)] - * @member CKEDITOR.config - */ }() ); From b14e2f1b5d3c1b011ec1f29e3839e5c5a47a1ae8 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 7 Nov 2017 10:10:07 +0100 Subject: [PATCH 140/642] Easy Image should not use img alone (at this point). --- plugins/easyimage/plugin.js | 21 ++------------------- tests/plugins/easyimage/uploadwidget.js | 25 +++++++++++++++---------- tests/plugins/easyimage/widget.html | 5 ----- tests/plugins/easyimage/widget.js | 21 --------------------- 4 files changed, 17 insertions(+), 55 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 6cbd4d57c87..4b03e07421e 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -120,23 +120,6 @@ element.find( 'img' ).length === 1 ) { return element; } - }, - - // Upload widget creates bare img[srcset] elements, so we should also upcast them. - img: function( element ) { - if ( element.attributes.srcset ) { - var figure = new CKEDITOR.htmlParser.element( 'figure' ); - - if ( figureClass ) { - figure.attributes[ 'class' ] = figureClass; - } - - element.wrapWith( figure ); - - return figure; - } - - return false; } }, @@ -184,8 +167,8 @@ onUploaded: function( upload ) { var srcset = CKEDITOR.plugins.easyimage._parseSrcSet( upload.responseData.response ); - this.replaceWith( '' ); + this.replaceWith( '
' ); } } ); diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index 9536e787384..29fab7f0bf4 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -13,6 +13,7 @@ BLOB_IMG = 'blob:', WIDGET_HTML = '
' + '' + + '
' + '
', commonConfig = { cloudServices_url: 'http://foo/upload', @@ -39,16 +40,20 @@ }; function assertUploadingWidgets( editor, expectedSrc ) { - var widgets = editor.editable().find( 'img[data-widget="uploadeasyimage"]' ), - widget, i; + var tools = CKEDITOR.tools, + array = tools.array, + widgets = array.map( tools.objectKeys( editor.widgets.instances ), function( val ) { + return editor.widgets.instances[ val ]; + } ); - assert.areSame( 1, widgets.count(), 'Expected widgets count should be 1' ); + widgets = array.filter( widgets, function( val ) { + return val.name === 'uploadeasyimage'; + } ); - for ( i = 0; i < widgets.count(); i++ ) { - widget = widgets.getItem( i ); - assert.areSame( '0', widget.getAttribute( 'data-cke-upload-id' ) ); - assert.areSame( expectedSrc, widget.getAttribute( 'src' ).substring( 0, 5 ) ); - } + assert.areSame( 1, widgets.length, 'Created widgets count' ); + + assert.areSame( '0', widgets[ 0 ].element.getAttribute( 'data-cke-upload-id' ) ); + assert.areSame( expectedSrc, widgets[ 0 ].element.getAttribute( 'src' ).substring( 0, 5 ) ); } tests = { @@ -213,7 +218,7 @@ 'test not supportedTypes tiff': function( editor, bot ) { bot.setData( '', function() { resumeAfter( editor, 'paste', function() { - assert.areSame( 0, editor.editable().find( 'img[data-widget="uploadeasyimage"]' ).count() ); + assert.areSame( 0, editor.editable().find( 'figure[data-widget="uploadeasyimage"]' ).count() ); } ); pasteFiles( editor, [ { name: 'test.tiff', type: 'image/tiff' } ] ); @@ -242,7 +247,7 @@ 'test paste nested image': function( editor ) { resumeAfter( editor, 'paste', function( evt ) { - var imgs = CKEDITOR.dom.element.createFromHtml( evt.data.dataValue ).find( 'img[data-widget="uploadeasyimage"]' ), + var imgs = CKEDITOR.dom.element.createFromHtml( evt.data.dataValue ).find( '[data-widget="uploadeasyimage"]' ), img, i; assert.areSame( 2, imgs.count(), 'Expected imgs count should be 2' ); diff --git a/tests/plugins/easyimage/widget.html b/tests/plugins/easyimage/widget.html index 4336d593b03..4af404f4fc9 100644 --- a/tests/plugins/easyimage/widget.html +++ b/tests/plugins/easyimage/widget.html @@ -11,8 +11,3 @@
Figure without image
- -
- fig1 - fig1 -
diff --git a/tests/plugins/easyimage/widget.js b/tests/plugins/easyimage/widget.js index 5a2c810e94d..dc7b197b7d8 100644 --- a/tests/plugins/easyimage/widget.js +++ b/tests/plugins/easyimage/widget.js @@ -36,27 +36,6 @@ html: CKEDITOR.document.getById( 'mixedFigures' ).getHtml(), bot: bot } ); - }, - - 'test upcasting image widget (img)': function( editor, bot ) { - widgetTestsTools.assertWidget( { - count: 1, - widgetOffset: 0, - nameCreated: 'easyimage', - html: CKEDITOR.document.getById( 'mixedImgs' ).getHtml(), - bot: bot, - assertCreated: function( widget ) { - var element = widget.element; - - assert.areSame( 'figure', element.getName(), 'img is wrapped in figure' ); - - if ( editor.name !== 'classicAllFigures' ) { - assert.isTrue( element.hasClass( 'easyimage' ), 'figure has appropriate class' ); - } else { - assert.isFalse( element.hasClass( 'easyimage' ), 'figure does not have class' ); - } - } - } ); } }; From bf4a5e6c6d442a10f71d25fe81b20ab5342043d4 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 7 Nov 2017 10:18:18 +0100 Subject: [PATCH 141/642] Removed height and width attributes from a list contributed to ACF by Easy Image. This plugin simply doesn't use it, so there's no need to do that. --- plugins/easyimage/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 4b03e07421e..04e4b3c2534 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -108,7 +108,7 @@ }, img: { - attributes: '!src,srcset,alt,width,height' + attributes: '!src,srcset,alt' } }, From 536e3b52c651a29472c7243a080526ca39994421 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 7 Nov 2017 10:27:29 +0100 Subject: [PATCH 142/642] Added a manual test for Easy Image uploading. --- tests/plugins/easyimage/manual/upload.html | 81 ++++++++++++++++++++++ tests/plugins/easyimage/manual/upload.md | 18 +++++ 2 files changed, 99 insertions(+) create mode 100644 tests/plugins/easyimage/manual/upload.html create mode 100644 tests/plugins/easyimage/manual/upload.md diff --git a/tests/plugins/easyimage/manual/upload.html b/tests/plugins/easyimage/manual/upload.html new file mode 100644 index 00000000000..8083b0bc219 --- /dev/null +++ b/tests/plugins/easyimage/manual/upload.html @@ -0,0 +1,81 @@ +

Note, this test uses a real Cloud Service connection, so you might want to be on-line 😉.

+ +

Classic editor

+ +
+

Sample editor

+

Go on, put some contnet here.

+
+ +

Divarea editor

+ +
+

Sample editor

+

Go on, put some contnet here.

+
+ +

Inline editor

+ +
+

Sample editor

+

Go on, put some contnet here.

+
+ + diff --git a/tests/plugins/easyimage/manual/upload.md b/tests/plugins/easyimage/manual/upload.md new file mode 100644 index 00000000000..e957b48f69e --- /dev/null +++ b/tests/plugins/easyimage/manual/upload.md @@ -0,0 +1,18 @@ +@bender-tags: 4.8.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage + +## Easy Image Upload + +Upload some images: + +1. Execute one of the following steps: + 1. Make a screenshot, copy a graphic to the clipboard and paste using `ctrl/cmd+v`. + 1. Drag and drop an jpg/png/bmp/gif image from your OS explorer to the editable. + 1. Firefox only: Copy an image file (from your OS explorer) into the clipboard, and paste into the editable. + +### Expected + +* Image gets inserted into the editable. +* "File successfully uploaded." notification is displayed. +* Image gets a `src` starting with `https://cdn.cke-cs.com/` (You can check that using source mode). From a64476552d9bd51f9db96ed0c24150cdaea81c85 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 7 Nov 2017 11:54:14 +0100 Subject: [PATCH 143/642] Fix typo in manual test. --- tests/plugins/easyimage/manual/upload.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/plugins/easyimage/manual/upload.html b/tests/plugins/easyimage/manual/upload.html index 8083b0bc219..ae0cb6b5305 100644 --- a/tests/plugins/easyimage/manual/upload.html +++ b/tests/plugins/easyimage/manual/upload.html @@ -4,21 +4,21 @@

Classic editor

Sample editor

-

Go on, put some contnet here.

+

Go on, put some content here.

Divarea editor

Sample editor

-

Go on, put some contnet here.

+

Go on, put some content here.

Inline editor

Sample editor

-

Go on, put some contnet here.

+

Go on, put some content here.

diff --git a/tests/plugins/easyimage/manual/dndimagetype.md b/tests/plugins/easyimage/manual/dndimagetype.md new file mode 100644 index 00000000000..68f1c19415e --- /dev/null +++ b/tests/plugins/easyimage/manual/dndimagetype.md @@ -0,0 +1,15 @@ +@bender-tags: 4.8.0, bug, easyimage, 932, tp3163 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, htmlwriter, elementspath + +1. Focus widget. +2. Switch it to full mode. +3. Drag and drop widget on the beginning of the editor. + +**Expected:** + +* Widget is still in full mode. + +**Unexpected:** + +* Widget switches back to side mode. From d8fa243abbb022995eb9fdaa7d6cea77ca62e2a6 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 9 Nov 2017 16:40:06 +0100 Subject: [PATCH 150/642] Manual test corrections. --- tests/plugins/easyimage/manual/dndimagetype.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/plugins/easyimage/manual/dndimagetype.md b/tests/plugins/easyimage/manual/dndimagetype.md index 68f1c19415e..eb9f2f62178 100644 --- a/tests/plugins/easyimage/manual/dndimagetype.md +++ b/tests/plugins/easyimage/manual/dndimagetype.md @@ -3,13 +3,13 @@ @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, htmlwriter, elementspath 1. Focus widget. -2. Switch it to full mode. +2. Switch it to full size. 3. Drag and drop widget on the beginning of the editor. -**Expected:** +## Expected -* Widget is still in full mode. +Widget is still in full size. -**Unexpected:** +## Unexpected -* Widget switches back to side mode. +Widget switches back to side image. From 9191274a68da737889d0be8373653bc04bea84ac Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 9 Nov 2017 17:17:32 +0100 Subject: [PATCH 151/642] Add manual test for pasting. --- .../plugins/easyimage/manual/pasteimagetype.html | 11 +++++++++++ tests/plugins/easyimage/manual/pasteimagetype.md | 15 +++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/plugins/easyimage/manual/pasteimagetype.html create mode 100644 tests/plugins/easyimage/manual/pasteimagetype.md diff --git a/tests/plugins/easyimage/manual/pasteimagetype.html b/tests/plugins/easyimage/manual/pasteimagetype.html new file mode 100644 index 00000000000..68d877dbc29 --- /dev/null +++ b/tests/plugins/easyimage/manual/pasteimagetype.html @@ -0,0 +1,11 @@ +
+

Easyimage is super widget!

+
+ foo +
Test image
+
+
+ + diff --git a/tests/plugins/easyimage/manual/pasteimagetype.md b/tests/plugins/easyimage/manual/pasteimagetype.md new file mode 100644 index 00000000000..cbf37e2bb2d --- /dev/null +++ b/tests/plugins/easyimage/manual/pasteimagetype.md @@ -0,0 +1,15 @@ +@bender-tags: 4.8.0, bug, easyimage, 932, tp3162 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, htmlwriter, elementspath + +1. Focus widget. +2. Switch it to full size. +3. Copy widget and paste it on the beginning of the editor. + +## Expected + +Widget is still in full size. + +## Unexpected + +Widget switches back to side image. From 4b0417d8dd4b144c529ccbd1485d6c9adf60bfc3 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 9 Nov 2017 18:02:45 +0100 Subject: [PATCH 152/642] Update unit test. --- tests/plugins/easyimage/widget.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/plugins/easyimage/widget.js b/tests/plugins/easyimage/widget.js index 0b767fc1397..8b97130620c 100644 --- a/tests/plugins/easyimage/widget.js +++ b/tests/plugins/easyimage/widget.js @@ -1,5 +1,5 @@ /* bender-tags: editor,widget */ -/* bender-ckeditor-plugins: easyimage,toolbar */ +/* bender-ckeditor-plugins: floatingspace,easyimage,toolbar */ /* bender-include: ../widget/_helpers/tools.js */ /* global widgetTestsTools */ @@ -37,7 +37,7 @@ } function drop( editor, evt, dropRange ) { - var dropTarget = CKEDITOR.env.ie && CKEDITOR.env.version < 9 ? editor.editable() : editor.document; + var dropTarget = CKEDITOR.plugins.clipboard.getDropTarget( editor ); // If drop range is known use a realistic target. If no, then use a mock. if ( dropRange ) { @@ -50,7 +50,7 @@ } function dragend( editor, evt, widget ) { - var dropTarget = CKEDITOR.env.ie && CKEDITOR.env.version < 9 ? editor.editable() : editor.document; + var dropTarget = CKEDITOR.plugins.clipboard.getDropTarget( editor ); // Use realistic target which is the drag handler. evt.setTarget( widget.dragHandlerContainer.findOne( 'img' ) ); @@ -88,7 +88,7 @@ } ); } ); - range.setStartBefore( editor.editable().findOne( 'p' ) ); + range.setStart( editor.editable().findOne( 'p' ).getChild( 0 ), 1 ); range.collapse(); dragstart( editor, evt, widget ); From cd035da1ce8dd4da7bc55c60789ec8a536fcd88c Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 10 Nov 2017 11:19:21 +0100 Subject: [PATCH 153/642] Tests: ignore selection warnings for Easy Image widget test suite. Also D&D tests should be performed on side image, so that attribute preserving is also tested. --- tests/plugins/easyimage/widget.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/plugins/easyimage/widget.js b/tests/plugins/easyimage/widget.js index 8b97130620c..6d80ba873ec 100644 --- a/tests/plugins/easyimage/widget.js +++ b/tests/plugins/easyimage/widget.js @@ -59,6 +59,15 @@ } var tests = { + init: function() { + // Ignore some irrelevant warnings for this test suite. + CKEDITOR.on( 'log', function( evt ) { + if ( evt.data.type == 'warn' ) { + evt.cancel(); + } + } ); + }, + 'test upcasting image widget (figure)': function( editor, bot ) { widgetTestsTools.assertWidget( { count: editor.name === 'classicAllFigures' ? 2 : 1, @@ -77,14 +86,14 @@ range = editor.createRange(); widget.focus(); - editor.execCommand( 'easyimageFull' ); + editor.execCommand( 'easyimageSide' ); editor.once( 'drop', function() { resume( function() { // Drag and drop probably destroyed old widget, so we should fetch it once more. var widget = editor.widgets.focused; - assert.areSame( 'full', widget.data.type, 'Widget has correct data type' ); + assert.areSame( 'side', widget.data.type, 'Widget has correct data type' ); } ); } ); From 7e54afd41fea1e67706b745ceeaf9a5a76d9d8aa Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 10 Nov 2017 14:28:33 +0100 Subject: [PATCH 154/642] Tests: actually drag and drop tests can be handled synchronously, what at the same time fixed Firefox failing. Also skipped test for inline on webkits, as it bleeded because of selection gone in element, and having nothing to scroll to. --- tests/plugins/easyimage/widget.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/tests/plugins/easyimage/widget.js b/tests/plugins/easyimage/widget.js index 6d80ba873ec..8d60fdf00a1 100644 --- a/tests/plugins/easyimage/widget.js +++ b/tests/plugins/easyimage/widget.js @@ -80,6 +80,10 @@ // tp3163 'test drag and drop retains data type': function( editor, bot ) { + if ( CKEDITOR.env.webkit && editor.editable().isInline() ) { + assert.ignore(); + } + bot.setData( CKEDITOR.document.getById( 'typeData' ).getHtml(), function() { var widget = widgetTestsTools.getWidgetByDOMOffset( editor, 0 ), evt = bender.tools.mockDropEvent(), @@ -88,15 +92,6 @@ widget.focus(); editor.execCommand( 'easyimageSide' ); - editor.once( 'drop', function() { - resume( function() { - // Drag and drop probably destroyed old widget, so we should fetch it once more. - var widget = editor.widgets.focused; - - assert.areSame( 'side', widget.data.type, 'Widget has correct data type' ); - } ); - } ); - range.setStart( editor.editable().findOne( 'p' ).getChild( 0 ), 1 ); range.collapse(); @@ -104,7 +99,9 @@ drop( editor, evt, range ); dragend( editor, evt, widget ); - wait(); + // Drag and drop probably destroyed old widget, so we should fetch it once more. + widget = editor.widgets.focused; + assert.areSame( 'side', widget.data.type, 'Widget has correct data type' ); } ); } }; From 05f778400773d057b2cca864674b11fe91541663 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 16:58:54 +0100 Subject: [PATCH 155/642] Constraint width of side image to 50%. --- plugins/easyimage/styles/easyimage.css | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index ea441e0d7fd..32527a5ed90 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -19,6 +19,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license .easyimage-side { float: right; + max-width: 50%; } .easyimage .cke_widget_editable { From 64daef5fb81d01d7f1296f72fbcf6aee0c0d63aa Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 17:07:07 +0100 Subject: [PATCH 156/642] Propagate side class to wrapper element. --- plugins/easyimage/plugin.js | 2 ++ tests/plugins/easyimage/commands.js | 3 +++ 2 files changed, 5 insertions(+) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 6a4ef52f425..c09d1045108 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -148,8 +148,10 @@ if ( data.type === 'side' ) { this.element.addClass( editor.config.easyimage_sideClass ); + this.wrapper.addClass( editor.config.easyimage_sideClass ); } else { this.element.removeClass( editor.config.easyimage_sideClass ); + this.wrapper.removeClass( editor.config.easyimage_sideClass ); } } }; diff --git a/tests/plugins/easyimage/commands.js b/tests/plugins/easyimage/commands.js index fd2e7808ff1..e452613ba60 100644 --- a/tests/plugins/easyimage/commands.js +++ b/tests/plugins/easyimage/commands.js @@ -99,6 +99,8 @@ widget.focus(); assert.isFalse( widget.element.hasClass( 'easyimage-side' ), 'Image does not have side class' ); + assert.isFalse( widget.wrapper.hasClass( 'easyimage-side' ), + 'Widget wrapper does not have side class' ); assert.areSame( 'full', widget.data.type, 'Widget has correct type data' ); bot.contextmenu( function( menu ) { @@ -110,6 +112,7 @@ editor.execCommand( 'easyimageSide' ); assert.isTrue( widget.element.hasClass( 'easyimage-side' ), 'Image has side class' ); + assert.isTrue( widget.wrapper.hasClass( 'easyimage-side' ), 'Widget wrapper has side class' ); assert.areSame( 'side', widget.data.type, 'Widget has correct type data' ); bot.contextmenu( function( menu ) { From 98c31d496d87942b573c1f54439f7f9b333ed64d Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 17:08:40 +0100 Subject: [PATCH 157/642] Ensure that only one side image will be in given line. --- plugins/easyimage/styles/easyimage.css | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index 32527a5ed90..eeb7c0cc7cd 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -20,6 +20,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license .easyimage-side { float: right; max-width: 50%; + clear: both; } .easyimage .cke_widget_editable { From 216145eb026da263c3ae0c60291a9aae2334ea15 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 17:13:12 +0100 Subject: [PATCH 158/642] Move clear: both to easyimage class. --- plugins/easyimage/styles/easyimage.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index eeb7c0cc7cd..ca670a50591 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -8,6 +8,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license border: none; display: block; padding: 0; + clear: both; } .easyimage img { @@ -20,7 +21,6 @@ For licensing, see LICENSE.md or http://ckeditor.com/license .easyimage-side { float: right; max-width: 50%; - clear: both; } .easyimage .cke_widget_editable { From f3cdc021de81a2958edf8a7bc19c8a5cd3b68cd9 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 17:23:22 +0100 Subject: [PATCH 159/642] Ensure that widget wrapper has easyimage class. --- plugins/easyimage/plugin.js | 4 ++++ tests/plugins/easyimage/commands.js | 2 ++ tests/plugins/easyimage/widget.js | 8 +++++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index c09d1045108..af0a2bfc2ae 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -137,6 +137,10 @@ evt.data.easyimageSide = editor.getCommand( 'easyimageSide' ).state; evt.data.easyimageAlt = editor.getCommand( 'easyimageAlt' ).state; } ); + + if ( editor.config.easyimage_class ) { + this.wrapper.addClass( editor.config.easyimage_class ); + } }, data: function( evt ) { diff --git a/tests/plugins/easyimage/commands.js b/tests/plugins/easyimage/commands.js index e452613ba60..89488cf1b73 100644 --- a/tests/plugins/easyimage/commands.js +++ b/tests/plugins/easyimage/commands.js @@ -99,6 +99,7 @@ widget.focus(); assert.isFalse( widget.element.hasClass( 'easyimage-side' ), 'Image does not have side class' ); + assert.isTrue( widget.wrapper.hasClass( 'easyimage' ), 'Widget wrapper has main class' ); assert.isFalse( widget.wrapper.hasClass( 'easyimage-side' ), 'Widget wrapper does not have side class' ); assert.areSame( 'full', widget.data.type, 'Widget has correct type data' ); @@ -112,6 +113,7 @@ editor.execCommand( 'easyimageSide' ); assert.isTrue( widget.element.hasClass( 'easyimage-side' ), 'Image has side class' ); + assert.isTrue( widget.wrapper.hasClass( 'easyimage' ), 'Widget wrapper has main class' ); assert.isTrue( widget.wrapper.hasClass( 'easyimage-side' ), 'Widget wrapper has side class' ); assert.areSame( 'side', widget.data.type, 'Widget has correct type data' ); diff --git a/tests/plugins/easyimage/widget.js b/tests/plugins/easyimage/widget.js index 8d60fdf00a1..8e131bb77d8 100644 --- a/tests/plugins/easyimage/widget.js +++ b/tests/plugins/easyimage/widget.js @@ -74,7 +74,13 @@ widgetOffset: 0, nameCreated: 'easyimage', html: CKEDITOR.document.getById( 'mixedFigures' ).getHtml(), - bot: bot + bot: bot, + + assertCreated: function( widget ) { + if ( editor.name !== 'classicAllFigures' ) { + assert.isTrue( widget.wrapper.hasClass( 'easyimage' ), 'Widget wrapper has main class' ); + } + } } ); }, From c59b162884d9fbd032d41856c89096a239fbe379 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 17:41:26 +0100 Subject: [PATCH 160/642] Add manual test for styles. --- tests/plugins/easyimage/_assets/big.png | Bin 0 -> 4942 bytes tests/plugins/easyimage/manual/styles.html | 73 +++++++++++++++++++++ tests/plugins/easyimage/manual/styles.md | 10 +++ 3 files changed, 83 insertions(+) create mode 100644 tests/plugins/easyimage/_assets/big.png create mode 100644 tests/plugins/easyimage/manual/styles.html create mode 100644 tests/plugins/easyimage/manual/styles.md diff --git a/tests/plugins/easyimage/_assets/big.png b/tests/plugins/easyimage/_assets/big.png new file mode 100644 index 0000000000000000000000000000000000000000..b649dc27ae456ea46b31127fa66fc45fc68c4f51 GIT binary patch literal 4942 zcmeAS@N?(olHy`uVBq!ia0y~yV15B)f8byPl9SK*^#du+0*}aI1_nK45N51cYF`Ev z6sih|C<)0d$w_5k;F#%s%7>kSDT&eeKzZdMpsWl?*0HoCBfkhF&3*E`ugv8nVmN#WAEJ?(OxByayCSoE;NZnY^+0e8v$p?SbfVrikbFE9`#% zZF6s6U}R$95KwS{Fk(a_!t1|VqKFA7eBhRN!PkhYl7)rmivy<;TqlIVe3uthq_Lr) zQBK2=1=$h-g@gsW(X0>zopr0PB4-c>n+a literal 0 HcmV?d00001 diff --git a/tests/plugins/easyimage/manual/styles.html b/tests/plugins/easyimage/manual/styles.html new file mode 100644 index 00000000000..82295bbdf50 --- /dev/null +++ b/tests/plugins/easyimage/manual/styles.html @@ -0,0 +1,73 @@ +

Classic editor

+
+
+ foo +
Test image
+
+

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

+
+ foo +
Test image
+
+
+ foo +
Test image
+
+
+ foo +
Test image
+
+

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

+
+ +

Divarea editor

+
+
+ foo +
Test image
+
+

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

+
+ foo +
Test image
+
+
+ foo +
Test image
+
+
+ foo +
Test image
+
+

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

+
+ +

Inline editor

+
+
+ foo +
Test image
+
+

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

+
+ foo +
Test image
+
+
+ foo +
Test image
+
+
+ foo +
Test image
+
+

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

+
+ + diff --git a/tests/plugins/easyimage/manual/styles.md b/tests/plugins/easyimage/manual/styles.md new file mode 100644 index 00000000000..8464aafb6a3 --- /dev/null +++ b/tests/plugins/easyimage/manual/styles.md @@ -0,0 +1,10 @@ +@bender-tags: 4.8.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage + + +Check if styles are working correctly: + +* There is visible difference between full size image and side image. +* Side image is occupating at most 50% of space. +* Side images does not occupy the same line. From 01dbb9b4936deec05744844c0c07504036165ef0 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sun, 12 Nov 2017 14:44:34 +0100 Subject: [PATCH 161/642] Use widget API to toggle class on wrapper. --- plugins/easyimage/plugin.js | 6 +++--- plugins/easyimage/styles/easyimage.css | 9 +++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index af0a2bfc2ae..5bb12382b35 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -139,7 +139,7 @@ } ); if ( editor.config.easyimage_class ) { - this.wrapper.addClass( editor.config.easyimage_class ); + this.addClass( editor.config.easyimage_class ); } }, @@ -152,10 +152,10 @@ if ( data.type === 'side' ) { this.element.addClass( editor.config.easyimage_sideClass ); - this.wrapper.addClass( editor.config.easyimage_sideClass ); + this.addClass( editor.config.easyimage_sideClass ); } else { this.element.removeClass( editor.config.easyimage_sideClass ); - this.wrapper.removeClass( editor.config.easyimage_sideClass ); + this.removeClass( editor.config.easyimage_sideClass ); } } }; diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index ca670a50591..16bee5df3ff 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -3,7 +3,7 @@ Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -.easyimage { +.easyimage, .cke_widget_wrapper_easyimage { background-color: #fff; border: none; display: block; @@ -18,11 +18,16 @@ For licensing, see LICENSE.md or http://ckeditor.com/license max-width: 100%; } -.easyimage-side { +.easyimage-side, .cke_widget_wrapper_easyimage-side { float: right; max-width: 50%; } +.cke_widget_wrapper_easyimage-side > .easyimage-side { + float: none; + max-width: none; +} + .easyimage .cke_widget_editable { background-color: #f7f7f7; color: #333; From 9e8c086ec6389fb706457e7d43dd72f0f5e2c624 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sun, 12 Nov 2017 14:44:49 +0100 Subject: [PATCH 162/642] Update unit tests. --- tests/plugins/easyimage/commands.js | 8 ++++---- tests/plugins/easyimage/widget.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/plugins/easyimage/commands.js b/tests/plugins/easyimage/commands.js index 89488cf1b73..2406862921a 100644 --- a/tests/plugins/easyimage/commands.js +++ b/tests/plugins/easyimage/commands.js @@ -99,8 +99,8 @@ widget.focus(); assert.isFalse( widget.element.hasClass( 'easyimage-side' ), 'Image does not have side class' ); - assert.isTrue( widget.wrapper.hasClass( 'easyimage' ), 'Widget wrapper has main class' ); - assert.isFalse( widget.wrapper.hasClass( 'easyimage-side' ), + assert.isTrue( widget.hasClass( 'easyimage' ), 'Widget wrapper has main class' ); + assert.isFalse( widget.hasClass( 'easyimage-side' ), 'Widget wrapper does not have side class' ); assert.areSame( 'full', widget.data.type, 'Widget has correct type data' ); @@ -113,8 +113,8 @@ editor.execCommand( 'easyimageSide' ); assert.isTrue( widget.element.hasClass( 'easyimage-side' ), 'Image has side class' ); - assert.isTrue( widget.wrapper.hasClass( 'easyimage' ), 'Widget wrapper has main class' ); - assert.isTrue( widget.wrapper.hasClass( 'easyimage-side' ), 'Widget wrapper has side class' ); + assert.isTrue( widget.hasClass( 'easyimage' ), 'Widget wrapper has main class' ); + assert.isTrue( widget.hasClass( 'easyimage-side' ), 'Widget wrapper has side class' ); assert.areSame( 'side', widget.data.type, 'Widget has correct type data' ); bot.contextmenu( function( menu ) { diff --git a/tests/plugins/easyimage/widget.js b/tests/plugins/easyimage/widget.js index 8e131bb77d8..fd1bc4cb9f8 100644 --- a/tests/plugins/easyimage/widget.js +++ b/tests/plugins/easyimage/widget.js @@ -78,7 +78,7 @@ assertCreated: function( widget ) { if ( editor.name !== 'classicAllFigures' ) { - assert.isTrue( widget.wrapper.hasClass( 'easyimage' ), 'Widget wrapper has main class' ); + assert.isTrue( widget.hasClass( 'easyimage' ), 'Widget wrapper has main class' ); } } } ); From 285e8749509d57bbb98bf18bfcfee34b3c375892 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sun, 12 Nov 2017 14:45:23 +0100 Subject: [PATCH 163/642] Change max-width to 25%. --- plugins/easyimage/styles/easyimage.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index 16bee5df3ff..d5225c08f6f 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -20,7 +20,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license .easyimage-side, .cke_widget_wrapper_easyimage-side { float: right; - max-width: 50%; + max-width: 25%; } .cke_widget_wrapper_easyimage-side > .easyimage-side { From 2dec084c4f0785cb389c8096a018236ded03ecd6 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sun, 12 Nov 2017 14:45:40 +0100 Subject: [PATCH 164/642] Update manual test. --- tests/plugins/easyimage/manual/styles.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plugins/easyimage/manual/styles.md b/tests/plugins/easyimage/manual/styles.md index 8464aafb6a3..f6314f805e7 100644 --- a/tests/plugins/easyimage/manual/styles.md +++ b/tests/plugins/easyimage/manual/styles.md @@ -6,5 +6,5 @@ Check if styles are working correctly: * There is visible difference between full size image and side image. -* Side image is occupating at most 50% of space. -* Side images does not occupy the same line. +* Side image is occupating at most 25% of space. +* Multiple side images can not be placed in the same horizontal line. From 882983f25294ed80387a0899665d6e3afc771d0e Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sun, 12 Nov 2017 14:54:14 +0100 Subject: [PATCH 165/642] Remove redundant add/removeClass calls. --- plugins/easyimage/plugin.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 5bb12382b35..103c6a91d6f 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -151,10 +151,8 @@ } if ( data.type === 'side' ) { - this.element.addClass( editor.config.easyimage_sideClass ); this.addClass( editor.config.easyimage_sideClass ); } else { - this.element.removeClass( editor.config.easyimage_sideClass ); this.removeClass( editor.config.easyimage_sideClass ); } } From 063be9e98f89df573e902c4070529e937a9fe712 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sun, 12 Nov 2017 14:57:13 +0100 Subject: [PATCH 166/642] Simplify styles. --- plugins/easyimage/styles/easyimage.css | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index d5225c08f6f..f5bbc2c46c0 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -18,16 +18,11 @@ For licensing, see LICENSE.md or http://ckeditor.com/license max-width: 100%; } -.easyimage-side, .cke_widget_wrapper_easyimage-side { +.cke_widget_wrapper_easyimage-side { float: right; max-width: 25%; } -.cke_widget_wrapper_easyimage-side > .easyimage-side { - float: none; - max-width: none; -} - .easyimage .cke_widget_editable { background-color: #f7f7f7; color: #333; From c6f77c07b4895591925e32f01130a0e238144e09 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 12 Nov 2017 17:18:52 +0100 Subject: [PATCH 167/642] Modified Easy Image wrapper/element selector so that it works with CKEditor output. --- plugins/easyimage/styles/easyimage.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index f5bbc2c46c0..65482ccc96e 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -18,7 +18,11 @@ For licensing, see LICENSE.md or http://ckeditor.com/license max-width: 100%; } -.cke_widget_wrapper_easyimage-side { +.cke_widget_wrapper_easyimage-side, :not(.cke_widget_wrapper_easyimage-side) > .easyimage { + /* + :not() selector will be used for Easy Image content ouside of the editor. E.g. when the editor was destoryed. + See https://github.com/ckeditor/ckeditor-dev/pull/1150#discussion_r150415261 for more details. + */ float: right; max-width: 25%; } From ffd0d7c40837d248e3a640080f275729a071b30e Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 31 Oct 2017 14:14:35 +0100 Subject: [PATCH 168/642] Add basic link integration. --- plugins/easyimage/plugin.js | 4 +- plugins/imagebase/plugin.js | 96 +++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 103c6a91d6f..c11faf4939f 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -163,6 +163,8 @@ widgetDefinition.allowedContent.figure.classes = '!' + figureClass + ',' + widgetDefinition.allowedContent.figure.classes; } + widgetDefinition = CKEDITOR.plugins.imagebase.addFeature( 'link', widgetDefinition ); + CKEDITOR.plugins.imagebase.addImageWidget( editor, 'easyimage', widgetDefinition ); } @@ -288,7 +290,7 @@ }; CKEDITOR.plugins.add( 'easyimage', { - requires: 'imagebase,uploadwidget,contextmenu,dialog,cloudservices', + requires: 'imagebase,uploadwidget,contextmenu,dialog,cloudservices,link', lang: 'en', onLoad: function() { diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 04d1819b499..7cff507045f 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -6,6 +6,82 @@ ( function() { 'use strict'; + function isWidgetFocused( widget ) { + return widget.editor.widgets.focused === widget; + } + + function wrapInLink( img, linkData ) { + var link = img.getDocument().createElement( 'a', { + attributes: { + href: linkData.url.url + } + } ); + + link.replace( img ); + img.move( link ); + + return link; + } + + var featuresDefinitions = { + link: { + allowedContent: { + a: { + attributes: '!href' + } + }, + parts: { + link: 'a' + }, + + init: function() { + var widget = this; + + widget.editor.on( 'dialogShow', function( evt ) { + var dialog = evt.data, + displayTextField; + + if ( !isWidgetFocused( widget ) || dialog._.name !== 'link' ) { + return; + } + + displayTextField = dialog.getContentElement( 'info', 'linkDisplayText' ).getElement().getParent().getParent(); + + dialog.setupContent( widget.data.link || {} ); + displayTextField.hide(); + + dialog.once( 'ok', function( evt ) { + if ( !isWidgetFocused( widget ) ) { + return; + } + + evt.stop(); + + var data = {}; + + dialog.commitContent( data ); + widget.setData( 'link', data ); + }, null, null, 9 ); + + dialog.once( 'hide', function() { + displayTextField.show(); + } ); + } ); + }, + + data: function( evt ) { + var link = evt.data.link, + img = this.element.findOne( 'img' ); + + if ( !link || !link.url.url ) { + return; + } + + wrapInLink( img, link ); + } + } + }; + function createWidgetDefinition( editor, definition ) { var defaultTemplate = new CKEDITOR.template( '
' + @@ -104,6 +180,26 @@ var widget = editor.widgets.add( name, createWidgetDefinition( editor, definition ) ); editor.addFeature( widget ); + }, + + addFeature: function( name, definition ) { + var featureDefinition = featuresDefinitions[ name ]; + + function mergeMethods( oldOne, newOne ) { + if ( !oldOne && !newOne ) { + return; + } + + return function() { + oldOne && oldOne.apply( this, arguments ); + newOne && newOne.apply( this, arguments ); + }; + } + + featureDefinition.init = mergeMethods( definition.init, featureDefinition.init ); + featureDefinition.data = mergeMethods( definition.data, featureDefinition.data ); + + return CKEDITOR.tools.object.merge( definition, featureDefinition ); } }; }() ); From dc0066e58c0112296970dce44d3ea26f7206e451 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 31 Oct 2017 14:46:21 +0100 Subject: [PATCH 169/642] Add unlinking. --- plugins/imagebase/plugin.js | 56 ++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 7cff507045f..096cc1b9ee3 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -23,6 +23,18 @@ return link; } + function unwrapFromLink( img ) { + var link = img.getAscendant( 'a' ); + + if ( !link ) { + return; + } + + img.replace( link ); + + return img; + } + var featuresDefinitions = { link: { allowedContent: { @@ -35,9 +47,10 @@ }, init: function() { - var widget = this; + var widget = this, + editor = widget.editor; - widget.editor.on( 'dialogShow', function( evt ) { + editor.on( 'dialogShow', function( evt ) { var dialog = evt.data, displayTextField; @@ -67,17 +80,52 @@ displayTextField.show(); } ); } ); + + // Overwrite default behaviour of unlink command. + editor.getCommand( 'unlink' ).on( 'exec', function( evt ) { + // Override unlink only when link truly belongs to the widget. + // If wrapped inline widget in a link, let default unlink work (http://dev.ckeditor.com/ticket/11814). + if ( !isWidgetFocused( widget ) ) { + return; + } + + widget.setData( 'link', null ); + + // Selection (which is fake) may not change if unlinked image in focused widget, + // i.e. if captioned image. Let's refresh command state manually here. + this.refresh( editor, editor.elementPath() ); + + evt.cancel(); + } ); + + // Overwrite default refresh of unlink command. + editor.getCommand( 'unlink' ).on( 'refresh', function( evt ) { + if ( !isWidgetFocused( widget ) ) { + return; + } + + // Note that widget may be wrapped in a link, which + // does not belong to that widget (http://dev.ckeditor.com/ticket/11814). + this.setState( widget.data.link ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED ); + + evt.cancel(); + } ); }, data: function( evt ) { var link = evt.data.link, img = this.element.findOne( 'img' ); - if ( !link || !link.url.url ) { + if ( typeof link === 'undefined' ) { return; } - wrapInLink( img, link ); + // Unlink was invoked. + if ( link === null ) { + unwrapFromLink( img ); + } else { + wrapInLink( img, link ); + } } } }; From 50a944a88d72cdd69a3403f5af9c1c88585f111c Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 31 Oct 2017 15:06:06 +0100 Subject: [PATCH 170/642] Implement updating widget.data.link and fix refreshing unlink command. --- plugins/imagebase/plugin.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 096cc1b9ee3..5d2220d863b 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -89,6 +89,8 @@ return; } + evt.stop(); + widget.setData( 'link', null ); // Selection (which is fake) may not change if unlinked image in focused widget, @@ -104,9 +106,11 @@ return; } + evt.stop(); + // Note that widget may be wrapped in a link, which // does not belong to that widget (http://dev.ckeditor.com/ticket/11814). - this.setState( widget.data.link ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED ); + this.setState( widget.parts.link ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED ); evt.cancel(); } ); @@ -123,8 +127,10 @@ // Unlink was invoked. if ( link === null ) { unwrapFromLink( img ); + + this.parts.link = null; } else { - wrapInLink( img, link ); + this.parts.link = wrapInLink( img, link ); } } } From c422fc46520a2589587d7741f5090e6c870a70f0 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 31 Oct 2017 15:28:48 +0100 Subject: [PATCH 171/642] Set link data if widget is inited with link. --- plugins/imagebase/plugin.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 5d2220d863b..9296717e905 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -35,6 +35,10 @@ return img; } + function getLinkData( widget ) { + return CKEDITOR.plugins.link.parseLinkAttributes( widget.parts.link ); + } + var featuresDefinitions = { link: { allowedContent: { @@ -120,6 +124,11 @@ var link = evt.data.link, img = this.element.findOne( 'img' ); + // Widget is inited with link, so let's set appropriate data. + if ( typeof link === 'undefined' && this.parts.link ) { + this.setData( 'link', getLinkData( this ) ); + } + if ( typeof link === 'undefined' ) { return; } From a9d6b308734f5a8fa24f3c91070d9f0131bdc2d3 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 2 Nov 2017 11:41:55 +0100 Subject: [PATCH 172/642] Fix incorrect parseLinkAttributes invocation. --- plugins/imagebase/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 9296717e905..805c4ebd777 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -36,7 +36,7 @@ } function getLinkData( widget ) { - return CKEDITOR.plugins.link.parseLinkAttributes( widget.parts.link ); + return CKEDITOR.plugins.link.parseLinkAttributes( widget.editor, widget.parts.link ); } var featuresDefinitions = { From d7243cfd7a7bbb026806b81db5e40dfe61589309 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 6 Nov 2017 17:00:16 +0100 Subject: [PATCH 173/642] Add link only if there is no one already. --- plugins/imagebase/plugin.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 805c4ebd777..ca794dbf363 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -11,7 +11,14 @@ } function wrapInLink( img, linkData ) { - var link = img.getDocument().createElement( 'a', { + // Covers cases when widget with link inside is upcasted. + var link = img.getAscendant( 'a' ); + + if ( link ) { + return link; + } + + link = img.getDocument().createElement( 'a', { attributes: { href: linkData.url.url } From 63fefbceb3d3c838586d66998152246ffc049032 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 6 Nov 2017 17:30:10 +0100 Subject: [PATCH 174/642] Force recursive finding img element in figure. --- plugins/easyimage/plugin.js | 2 +- plugins/imagebase/plugin.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index c11faf4939f..af0fea2cf36 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -125,7 +125,7 @@ upcasts: { figure: function( element ) { if ( ( !figureClass || element.hasClass( figureClass ) ) && - element.find( 'img' ).length === 1 ) { + element.find( 'img', true ).length === 1 ) { return element; } } diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index ca794dbf363..deef4aa2cad 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -204,7 +204,7 @@ upcasts: { figure: function( element ) { - if ( element.find( 'img' ).length === 1 ) { + if ( element.find( 'img', true ).length === 1 ) { return element; } } From acbb2d0220851f1424487f9110357c293df51bdd Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 01:11:49 +0100 Subject: [PATCH 175/642] Ensure that listeners are bound only once. --- plugins/easyimage/plugin.js | 2 +- plugins/imagebase/plugin.js | 36 ++++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index af0fea2cf36..99da2a0df61 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -163,7 +163,7 @@ widgetDefinition.allowedContent.figure.classes = '!' + figureClass + ',' + widgetDefinition.allowedContent.figure.classes; } - widgetDefinition = CKEDITOR.plugins.imagebase.addFeature( 'link', widgetDefinition ); + widgetDefinition = CKEDITOR.plugins.imagebase.addFeature( editor, 'link', widgetDefinition ); CKEDITOR.plugins.imagebase.addImageWidget( editor, 'easyimage', widgetDefinition ); } diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index deef4aa2cad..062ff3f017c 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -6,8 +6,12 @@ ( function() { 'use strict'; - function isWidgetFocused( widget ) { - return widget.editor.widgets.focused === widget; + function getFocusedWidget( editor ) { + return editor.widgets.focused; + } + + function isLinkable( widget ) { + return widget && typeof widget.parts.link !== 'undefined'; } function wrapInLink( img, linkData ) { @@ -57,15 +61,13 @@ link: 'a' }, - init: function() { - var widget = this, - editor = widget.editor; - + setUp: function( editor ) { editor.on( 'dialogShow', function( evt ) { - var dialog = evt.data, + var widget = getFocusedWidget( editor ), + dialog = evt.data, displayTextField; - if ( !isWidgetFocused( widget ) || dialog._.name !== 'link' ) { + if ( !isLinkable( widget ) || dialog._.name !== 'link' ) { return; } @@ -75,7 +77,7 @@ displayTextField.hide(); dialog.once( 'ok', function( evt ) { - if ( !isWidgetFocused( widget ) ) { + if ( !isLinkable( widget ) ) { return; } @@ -94,9 +96,11 @@ // Overwrite default behaviour of unlink command. editor.getCommand( 'unlink' ).on( 'exec', function( evt ) { + var widget = getFocusedWidget( editor ); + // Override unlink only when link truly belongs to the widget. // If wrapped inline widget in a link, let default unlink work (http://dev.ckeditor.com/ticket/11814). - if ( !isWidgetFocused( widget ) ) { + if ( !isLinkable( widget ) ) { return; } @@ -113,7 +117,9 @@ // Overwrite default refresh of unlink command. editor.getCommand( 'unlink' ).on( 'refresh', function( evt ) { - if ( !isWidgetFocused( widget ) ) { + var widget = getFocusedWidget( editor ); + + if ( !isLinkable( widget ) ) { return; } @@ -252,7 +258,7 @@ editor.addFeature( widget ); }, - addFeature: function( name, definition ) { + addFeature: function( editor, name, definition ) { var featureDefinition = featuresDefinitions[ name ]; function mergeMethods( oldOne, newOne ) { @@ -269,6 +275,12 @@ featureDefinition.init = mergeMethods( definition.init, featureDefinition.init ); featureDefinition.data = mergeMethods( definition.data, featureDefinition.data ); + if ( featureDefinition.setUp ) { + featureDefinition.setUp( editor ); + + delete featureDefinition.setUp; + } + return CKEDITOR.tools.object.merge( definition, featureDefinition ); } }; From 9371ab226bf4651b4db7388c4a92a50da1dc875e Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 14:00:21 +0100 Subject: [PATCH 176/642] Add link attributes handling. --- plugins/imagebase/plugin.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 062ff3f017c..110dd012303 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -134,7 +134,8 @@ }, data: function( evt ) { - var link = evt.data.link, + var editor = this.editor, + link = evt.data.link, img = this.element.findOne( 'img' ); // Widget is inited with link, so let's set appropriate data. @@ -152,7 +153,19 @@ this.parts.link = null; } else { - this.parts.link = wrapInLink( img, link ); + var linkElement = wrapInLink( img, link ), + // Set and remove all attributes associated with this state. + attributes = CKEDITOR.plugins.link.getLinkAttributes( editor, link ); + + if ( !CKEDITOR.tools.isEmpty( attributes.set ) ) { + linkElement.setAttributes( attributes.set ); + } + + if ( attributes.removed.length ) { + linkElement.removeAttributes( attributes.removed ); + } + + this.parts.link = linkElement; } } } From 906d58fdf33b655ea30e8b360046fdd8a75c030d Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 14:49:14 +0100 Subject: [PATCH 177/642] Add link feature only if link plugin is loaded. --- plugins/easyimage/plugin.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 99da2a0df61..756bc17ab16 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -163,7 +163,9 @@ widgetDefinition.allowedContent.figure.classes = '!' + figureClass + ',' + widgetDefinition.allowedContent.figure.classes; } - widgetDefinition = CKEDITOR.plugins.imagebase.addFeature( editor, 'link', widgetDefinition ); + if ( editor.plugins.link ) { + widgetDefinition = CKEDITOR.plugins.imagebase.addFeature( editor, 'link', widgetDefinition ); + } CKEDITOR.plugins.imagebase.addImageWidget( editor, 'easyimage', widgetDefinition ); } @@ -290,7 +292,7 @@ }; CKEDITOR.plugins.add( 'easyimage', { - requires: 'imagebase,uploadwidget,contextmenu,dialog,cloudservices,link', + requires: 'imagebase,contextmenu,dialog,cloudservices', lang: 'en', onLoad: function() { From cf10891a81b1c7fc8b31de4f7edde8a0dd95dfbc Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 14:55:00 +0100 Subject: [PATCH 178/642] Add API docs for addFeature. --- plugins/imagebase/plugin.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 110dd012303..78ff34ab18e 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -271,6 +271,20 @@ editor.addFeature( widget ); }, + /** + * Adds new feature to the newly created image widget by invoking initial setup once for the editor + * and extending widget's definition to include all fields needed by this feature. + * + * var widgetDefinition = {}; + * widgetDefinition = CKEDITOR.plugins.imagebase.addFeature( editor, 'link', widgetDefinition ); + * CKEDITOR.plugins.imagebase.addImageWidget( editor, 'myWidget', widgetDefinition ); + * + * @param {CKEDITOR.editor} editor Editor that will get the widget registered. + * @param {String} name Feature name. + * @param {CKEDITOR.plugins.imagebase.imageWidgetDefinition} definition Widget's definition. + * @returns {CKEDITOR.plugins.imagebase.imageWidgetDefinition} Widget's definition extended + * with fields needed by feature. + */ addFeature: function( editor, name, definition ) { var featureDefinition = featuresDefinitions[ name ]; From bb59ea39c9572e1ca4ca22328a43cd1555cd3a9a Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 16:14:45 +0100 Subject: [PATCH 179/642] Ensure that every widget gets copy of original feature definition. --- plugins/imagebase/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 78ff34ab18e..96e8737f7f8 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -286,7 +286,7 @@ * with fields needed by feature. */ addFeature: function( editor, name, definition ) { - var featureDefinition = featuresDefinitions[ name ]; + var featureDefinition = CKEDITOR.tools.clone( featuresDefinitions[ name ] ); function mergeMethods( oldOne, newOne ) { if ( !oldOne && !newOne ) { From 4be75f84a7204c91711cf1a6d40c269954d977a9 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 16:29:02 +0100 Subject: [PATCH 180/642] Move registering widget into afterInit. --- plugins/easyimage/plugin.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 756bc17ab16..e8cfe75653a 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -303,6 +303,11 @@ loadStyles( editor, this ); addCommands( editor ); addMenuItems( editor ); + }, + + // Widget must be registered after init in case that link plugin is dynamically loaded e.g. via + // `config.extraPlugins`. + afterInit: function( editor ) { registerWidget( editor ); registerUploadWidget( editor ); } From f67990e704b34140125daa1af5dbce759c893904 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 16:29:24 +0100 Subject: [PATCH 181/642] Add unit test for dynamically adding link feature. --- tests/plugins/easyimage/widget.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/widget.js b/tests/plugins/easyimage/widget.js index fd1bc4cb9f8..5f9b76309cb 100644 --- a/tests/plugins/easyimage/widget.js +++ b/tests/plugins/easyimage/widget.js @@ -1,4 +1,4 @@ -/* bender-tags: editor,widget */ +/* bender-tags: editor,widget */ /* bender-ckeditor-plugins: floatingspace,easyimage,toolbar */ /* bender-include: ../widget/_helpers/tools.js */ /* global widgetTestsTools */ @@ -24,6 +24,12 @@ config: { easyimage_class: null } + }, + + linkEditor: { + config: { + extraPlugins: 'link' + } } }; @@ -77,6 +83,13 @@ bot: bot, assertCreated: function( widget ) { + if ( editor.name === 'linkEditor' ) { + assert.isNull( widget.parts.link, 'Widget does have link part if the editor has link plugin' ); + } else { + assert.isUndefined( widget.parts.link, + 'Widget does not have link part if the editor does not have link plugin' ); + } + if ( editor.name !== 'classicAllFigures' ) { assert.isTrue( widget.hasClass( 'easyimage' ), 'Widget wrapper has main class' ); } From ba7f6f557e81af5a5eb0da8eff67851332f537b7 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 16:36:41 +0100 Subject: [PATCH 182/642] Fix incorrect dependencies list. --- plugins/easyimage/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index e8cfe75653a..f57a9f0f2d3 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -292,7 +292,7 @@ }; CKEDITOR.plugins.add( 'easyimage', { - requires: 'imagebase,contextmenu,dialog,cloudservices', + requires: 'imagebase,uploadwidget,contextmenu,dialog,cloudservices', lang: 'en', onLoad: function() { From 30710ce2e388a31a8618a638b0936cc206d0baca Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 17:14:06 +0100 Subject: [PATCH 183/642] Add unit tests for link. --- tests/plugins/imagebase/features/link.html | 7 + tests/plugins/imagebase/features/link.js | 343 +++++++++++++++++++++ 2 files changed, 350 insertions(+) create mode 100644 tests/plugins/imagebase/features/link.html create mode 100644 tests/plugins/imagebase/features/link.js diff --git a/tests/plugins/imagebase/features/link.html b/tests/plugins/imagebase/features/link.html new file mode 100644 index 00000000000..090e276f4e0 --- /dev/null +++ b/tests/plugins/imagebase/features/link.html @@ -0,0 +1,7 @@ +
+
+ + + +
+
diff --git a/tests/plugins/imagebase/features/link.js b/tests/plugins/imagebase/features/link.js new file mode 100644 index 00000000000..d586d157af0 --- /dev/null +++ b/tests/plugins/imagebase/features/link.js @@ -0,0 +1,343 @@ +/* bender-tags: editor,widget */ +/* bender-ckeditor-plugins: imagebase,link,toolbar */ +/* bender-include: ../../widget/_helpers/tools.js */ +/* global widgetTestsTools */ + +( function() { + 'use strict'; + + bender.editors = { + classic: {}, + + divarea: { + config: { + extraPlugins: 'divarea' + } + }, + + inline: { + creator: 'inline' + } + }; + + function addTestWidget( editor ) { + if ( editor.widgets.registered.testWidget ) { + return; + } + + var plugin = CKEDITOR.plugins.imagebase; + + plugin.addImageWidget( editor, 'testWidget', plugin.addFeature( editor, 'link', {} ) ); + } + + function assertAttributes( editor, linkElement, linkData ) { + var attributes = CKEDITOR.plugins.link.getLinkAttributes( editor, linkData ), + attribute; + + for ( attribute in attributes.set ) { + assert.areSame( attributes.set[ attribute ], linkElement.getAttribute( attribute ), + 'Link has proper value for ' + attribute + ' attribute' ); + } + + CKEDITOR.tools.array.forEach( attributes.removed, function( attribute ) { + assert.isFalse( linkElement.hasAttribute( attribute ), 'Link does not have ' + attribute + ' attribute' ); + } ); + } + + function assertLinkWidget( options ) { + var editor = options.editor, + linkCmd = editor.getCommand( 'link' ), + unlinkCmd = editor.getCommand( 'unlink' ), + widget; + + if ( options.widget ) { + widget = options.widget; + } else { + widget = widgetTestsTools.getWidgetByDOMOffset( editor, 0 ); + } + + widget.focus(); + + assert.areSame( 1, widget.element.find( 'a' ).count(), 'There is only one link element inside widget' ); + assert.areSame( CKEDITOR.TRISTATE_OFF, linkCmd.state, 'Link command state' ); + assert.areSame( CKEDITOR.TRISTATE_OFF, unlinkCmd.state, 'Unlink command state' ); + assert.isObject( widget.parts.link, 'Widget has link part' ); + objectAssert.areDeepEqual( options.data, widget.data.link, 'Widget has correct link data' ); + assertAttributes( editor, widget.parts.link, options.data ); + } + + function assertUnlinkWidget( options ) { + var editor = options.editor, + linkCmd = editor.getCommand( 'link' ), + unlinkCmd = editor.getCommand( 'unlink' ), + widget; + + if ( options.widget ) { + widget = options.widget; + } else { + widget = widgetTestsTools.getWidgetByDOMOffset( editor, 0 ); + } + + widget.focus(); + + assert.areSame( 0, widget.element.find( 'a' ).count(), 'There is no link element inside widget' ); + assert.areSame( CKEDITOR.TRISTATE_OFF, linkCmd.state, 'Link command state' ); + assert.areSame( CKEDITOR.TRISTATE_DISABLED, unlinkCmd.state, 'Unlink command state' ); + assert.isNull( widget.parts.link, 'Widget does not have link part' ); + assert.isNull( widget.data.link, 'Widget does not have link data' ); + } + + function testLinkCommand( options ) { + var bot = options.bot, + editor = bot.editor, + linkCmd = editor.getCommand( 'link' ), + unlinkCmd = editor.getCommand( 'unlink' ), + linkCmdState = typeof options.linkCmdState === 'number' ? options.linkCmdState : CKEDITOR.TRISTATE_OFF, + unlinkCmdState = typeof options.unlinkCmdState === 'number' ? options.unlinkCmdState : + CKEDITOR.TRISTATE_DISABLED; + + bot.setData( options.html, function() { + var widget = widgetTestsTools.getWidgetByDOMOffset( editor, 0 ); + + editor.once( 'dialogShow', function( evt ) { + resume( function() { + var dialog = evt.data; + + options.dialogCallback( dialog, widget ); + } ); + } ); + + widget.focus(); + + assert.areSame( linkCmdState, linkCmd.state, 'Link command state' ); + assert.areSame( unlinkCmdState, unlinkCmd.state, 'Unlink command state' ); + + editor.execCommand( 'link' ); + wait(); + } ); + } + + function testUnlinkCommand( options ) { + var bot = options.bot, + editor = bot.editor, + linkCmd = editor.getCommand( 'link' ), + unlinkCmd = editor.getCommand( 'unlink' ), + linkCmdState = typeof options.linkCmdState === 'number' ? options.linkCmdState : CKEDITOR.TRISTATE_OFF, + unlinkCmdState = typeof options.unlinkCmdState === 'number' ? options.unlinkCmdState : + CKEDITOR.TRISTATE_OFF; + + bot.setData( options.html, function() { + var widget = widgetTestsTools.getWidgetByDOMOffset( editor, 0 ); + + editor.once( 'afterCommandExec', function( evt ) { + resume( function() { + options.callback( evt, widget ); + } ); + } ); + + widget.focus(); + + assert.areSame( linkCmdState, linkCmd.state, 'Link command state' ); + assert.areSame( unlinkCmdState, unlinkCmd.state, 'Unlink command state' ); + + editor.execCommand( 'unlink' ); + wait(); + } ); + } + + var tests = { + 'test adding image widget with link feature': function( editor ) { + var expectedParts = { + caption: 'figcaption', + image: 'img', + link: 'a' + }; + + addTestWidget( editor ); + + objectAssert.ownsKeys( [ 'testWidget' ], editor.widgets.registered ); + objectAssert.areDeepEqual( expectedParts, editor.widgets.registered.testWidget.parts ); + + }, + + 'test upcasting image widget with link': function( editor, bot ) { + addTestWidget( editor ); + + widgetTestsTools.assertWidget( { + count: 1, + widgetOffset: 0, + nameCreated: 'testWidget', + html: CKEDITOR.document.getById( 'upcastTest' ).getHtml(), + bot: bot, + assertCreated: function( widget ) { + assertLinkWidget( { + widget: widget, + editor: editor, + url: 'foo', + data: { + type: 'url', + url: { + protocol: 'http://', + url: 'foo' + } + } + } ); + } + } ); + }, + + 'test add link to existing image widget': function( editor, bot ) { + addTestWidget( editor ); + + testLinkCommand( { + bot: bot, + html: '
', + url: 'x', + dialogCallback: function( dialog, widget ) { + var data = {}; + + dialog.setValueOf( 'info', 'url', 'x' ); + dialog.getButton( 'ok' ).click(); + + dialog.commitContent( data ); + + assertLinkWidget( { + widget: widget, + editor: editor, + data: data + } ); + } + } ); + }, + + 'test edit link in existing image widget': function( editor, bot ) { + addTestWidget( editor ); + + testLinkCommand( { + bot: bot, + html: '
', + initialUrl: 'foo', + unlinkCmdState: CKEDITOR.TRISTATE_OFF, + dialogCallback: function( dialog, widget ) { + var data = {}; + + assert.areSame( 'foo', dialog.getValueOf( 'info', 'url' ), + 'Dialog contains correct URL' ); + + dialog.setValueOf( 'info', 'url', 'x' ); + dialog.getButton( 'ok' ).click(); + + dialog.commitContent( data ); + + assertLinkWidget( { + widget: widget, + editor: editor, + data: data + } ); + } + } ); + }, + + 'test add link with attribute to existing image widget': function( editor, bot ) { + addTestWidget( editor ); + + testLinkCommand( { + bot: bot, + html: '
', + url: 'x', + dialogCallback: function( dialog, widget ) { + var data = {}; + + dialog.setValueOf( 'info', 'url', 'x' ); + dialog.setValueOf( 'target', 'linkTargetType', '_blank' ); + dialog.getButton( 'ok' ).click(); + + dialog.commitContent( data ); + + assertLinkWidget( { + widget: widget, + editor: editor, + data: data + } ); + } + } ); + }, + + 'test edit link attribute in existing image widget': function( editor, bot ) { + addTestWidget( editor ); + + testLinkCommand( { + bot: bot, + html: '
', + initialUrl: 'foo', + unlinkCmdState: CKEDITOR.TRISTATE_OFF, + dialogCallback: function( dialog, widget ) { + var data = {}; + + assert.areSame( 'foo', dialog.getValueOf( 'info', 'url' ), + 'Dialog contains correct URL' ); + + dialog.setValueOf( 'info', 'url', 'x' ); + dialog.setValueOf( 'target', 'linkTargetType', 'popup' ); + dialog.getButton( 'ok' ).click(); + + dialog.commitContent( data ); + + assertLinkWidget( { + widget: widget, + editor: editor, + data: data + } ); + } + } ); + }, + + 'test remove link attribute in existing image widget': function( editor, bot ) { + addTestWidget( editor ); + + testLinkCommand( { + bot: bot, + html: '
', + initialUrl: 'foo', + unlinkCmdState: CKEDITOR.TRISTATE_OFF, + dialogCallback: function( dialog, widget ) { + var data = {}; + + assert.areSame( 'foo', dialog.getValueOf( 'info', 'url' ), + 'Dialog contains correct URL' ); + + dialog.setValueOf( 'info', 'url', 'x' ); + dialog.setValueOf( 'target', 'linkTargetType', 'notSet' ); + dialog.getButton( 'ok' ).click(); + + dialog.commitContent( data ); + + assertLinkWidget( { + widget: widget, + editor: editor, + data: data + } ); + } + } ); + }, + + 'test unlink image widget': function( editor, bot ) { + addTestWidget( editor ); + + testUnlinkCommand( { + bot: bot, + html: '
', + + callback: function( evt, widget ) { + assertUnlinkWidget( { + widget: widget, + editor: editor + } ); + } + } ); + } + }; + + tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); + bender.test( tests ); +} )(); From 56ac2212ee670369502a280aad130b5ef4f08498 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 17:27:16 +0100 Subject: [PATCH 184/642] Make features definitions public. --- plugins/imagebase/plugin.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 96e8737f7f8..6c3673c86ad 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -258,6 +258,12 @@ * @class CKEDITOR.plugins.imagebase */ CKEDITOR.plugins.imagebase = { + /** + * Object containing all available features definitions. + * @property {Object} + */ + featuresDefinitions: featuresDefinitions, + /** * Registers a new widget based on passed definition. * @@ -286,7 +292,7 @@ * with fields needed by feature. */ addFeature: function( editor, name, definition ) { - var featureDefinition = CKEDITOR.tools.clone( featuresDefinitions[ name ] ); + var featureDefinition = CKEDITOR.tools.clone( this.featuresDefinitions[ name ] ); function mergeMethods( oldOne, newOne ) { if ( !oldOne && !newOne ) { From fded0a69596ed4ab60abcbc7d5a6858746b23db7 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 17:38:10 +0100 Subject: [PATCH 185/642] Add unit test for features API. --- tests/plugins/imagebase/features/api.js | 36 +++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/plugins/imagebase/features/api.js diff --git a/tests/plugins/imagebase/features/api.js b/tests/plugins/imagebase/features/api.js new file mode 100644 index 00000000000..d8c81944156 --- /dev/null +++ b/tests/plugins/imagebase/features/api.js @@ -0,0 +1,36 @@ +/* bender-tags: editor,imagebase */ +/* bender-ckeditor-plugins: imagebase,link */ + + +( function() { + 'use strict'; + + bender.editor = true; + + bender.test( { + 'testing adding new feature': function() { + var plugin = CKEDITOR.plugins.imagebase, + editor = this.editor, + widgetDefinition = {}, + linkDefinition = plugin.featuresDefinitions.link, + originalSetUp = linkDefinition.setUp, + callCount = 0, + originalLinkDefinition, + extendedDefinition; + + linkDefinition.setUp = function() { + callCount++; + }; + originalLinkDefinition = CKEDITOR.tools.clone( linkDefinition ); + + extendedDefinition = plugin.addFeature( editor, 'link', widgetDefinition ); + + objectAssert.areDeepEqual( originalLinkDefinition, plugin.featuresDefinitions.link, + 'Link feature definition is not modified' ); + assert.areNotSame( widgetDefinition, extendedDefinition, 'addFeature returns new definition' ); + assert.areSame( 1, callCount, 'setUp was called only once' ); + + linkDefinition.setUp = originalSetUp; + } + } ); +} )(); From 9c5f379af53e98f8164a4353b22773d39ef419f0 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 17:45:53 +0100 Subject: [PATCH 186/642] Add manual test. --- .../imagebase/features/manual/link.html | 29 +++++++++++++++++++ .../plugins/imagebase/features/manual/link.md | 11 +++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/plugins/imagebase/features/manual/link.html create mode 100644 tests/plugins/imagebase/features/manual/link.md diff --git a/tests/plugins/imagebase/features/manual/link.html b/tests/plugins/imagebase/features/manual/link.html new file mode 100644 index 00000000000..5bfc9150a77 --- /dev/null +++ b/tests/plugins/imagebase/features/manual/link.html @@ -0,0 +1,29 @@ + +
+

Widget with no link:

+
+ foo +
Test image
+
+

Widget with predefined link:

+
+ + foo + +
Test image
+
+
+ + diff --git a/tests/plugins/imagebase/features/manual/link.md b/tests/plugins/imagebase/features/manual/link.md new file mode 100644 index 00000000000..606cf038465 --- /dev/null +++ b/tests/plugins/imagebase/features/manual/link.md @@ -0,0 +1,11 @@ +@bender-tags: 4.8.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, imagebase, link, htmlwriter, elementspath + +Check if integration with link is working: + +* Widget with link inside is properly upcasted. +* Widget could be linked. +* Widget could be unlinked. +* Link in the widget is editable. +* All attributes defined in link dialog are bound to the link. From bd417c6b4ff016562ed66ec1f44f07bbfe010573 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 8 Nov 2017 17:55:38 +0100 Subject: [PATCH 187/642] Move away DOM logic from widget data callback. --- plugins/imagebase/plugin.js | 47 +++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 6c3673c86ad..db70b8db52b 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -14,27 +14,34 @@ return widget && typeof widget.parts.link !== 'undefined'; } - function wrapInLink( img, linkData ) { - // Covers cases when widget with link inside is upcasted. - var link = img.getAscendant( 'a' ); + function addLinkAttributes( editor, linkElement, linkData ) { + // Set and remove all attributes associated with this state. + var attributes = CKEDITOR.plugins.link.getLinkAttributes( editor, linkData ); - if ( link ) { - return link; + if ( !CKEDITOR.tools.isEmpty( attributes.set ) ) { + linkElement.setAttributes( attributes.set ); } - link = img.getDocument().createElement( 'a', { - attributes: { - href: linkData.url.url - } - } ); + if ( attributes.removed.length ) { + linkElement.removeAttributes( attributes.removed ); + } + } + + function createLink( editor, img, linkData ) { + // Covers cases when widget with link inside is upcasted. + var link = img.getAscendant( 'a' ) || editor.document.createElement( 'a' ); - link.replace( img ); - img.move( link ); + addLinkAttributes( editor, link, linkData ); + + if ( !link.contains( img ) ) { + link.replace( img ); + img.move( link ); + } return link; } - function unwrapFromLink( img ) { + function deleteLink( img ) { var link = img.getAscendant( 'a' ); if ( !link ) { @@ -149,21 +156,11 @@ // Unlink was invoked. if ( link === null ) { - unwrapFromLink( img ); + deleteLink( img ); this.parts.link = null; } else { - var linkElement = wrapInLink( img, link ), - // Set and remove all attributes associated with this state. - attributes = CKEDITOR.plugins.link.getLinkAttributes( editor, link ); - - if ( !CKEDITOR.tools.isEmpty( attributes.set ) ) { - linkElement.setAttributes( attributes.set ); - } - - if ( attributes.removed.length ) { - linkElement.removeAttributes( attributes.removed ); - } + var linkElement = createLink( editor, img, link ); this.parts.link = linkElement; } From 5861cef6c40a8e9d864b04e0b8b5fbcb414322ef Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 12:41:19 +0100 Subject: [PATCH 188/642] Add widgetFeatures property. --- plugins/imagebase/plugin.js | 9 +++++++++ tests/plugins/imagebase/features/api.js | 2 ++ 2 files changed, 11 insertions(+) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index db70b8db52b..9c7c01346df 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -205,6 +205,13 @@ requiredContent: 'figure; img[!src]', + /** + * The array containing names of features added to this widget's definition + * + * @property {String[]} widgetFeatures + */ + widgetFeatures: [], + editables: { caption: { selector: 'figcaption', @@ -311,6 +318,8 @@ delete featureDefinition.setUp; } + featureDefinition.widgetFeatures = [ name ]; + return CKEDITOR.tools.object.merge( definition, featureDefinition ); } }; diff --git a/tests/plugins/imagebase/features/api.js b/tests/plugins/imagebase/features/api.js index d8c81944156..9d769b13402 100644 --- a/tests/plugins/imagebase/features/api.js +++ b/tests/plugins/imagebase/features/api.js @@ -29,6 +29,8 @@ 'Link feature definition is not modified' ); assert.areNotSame( widgetDefinition, extendedDefinition, 'addFeature returns new definition' ); assert.areSame( 1, callCount, 'setUp was called only once' ); + arrayAssert.itemsAreSame( [ 'link' ], extendedDefinition.widgetFeatures, + 'Widget definition has correct value for widgetFeatures property' ); linkDefinition.setUp = originalSetUp; } From 08a963480ff899444a21621e94ab09b4d4321e28 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 12:45:17 +0100 Subject: [PATCH 189/642] Get rid of duck-typing. --- plugins/imagebase/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 9c7c01346df..f26b1cfb4d4 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -11,7 +11,7 @@ } function isLinkable( widget ) { - return widget && typeof widget.parts.link !== 'undefined'; + return widget && widget.widgetFeatures && CKEDITOR.tools.array.indexOf( widget.widgetFeatures, 'link' ) !== -1; } function addLinkAttributes( editor, linkElement, linkData ) { From 378b81c3da5710dba8aab555f1b1a76afae16726 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 12:47:58 +0100 Subject: [PATCH 190/642] Remove unnecessary comment. --- plugins/imagebase/plugin.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index f26b1cfb4d4..54692820e03 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -28,7 +28,6 @@ } function createLink( editor, img, linkData ) { - // Covers cases when widget with link inside is upcasted. var link = img.getAscendant( 'a' ) || editor.document.createElement( 'a' ); addLinkAttributes( editor, link, linkData ); From b767a1844061c5bf6ff15ae2cb97502bc0c8d876 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 14:17:15 +0100 Subject: [PATCH 191/642] Ensure that ok listener is removed when closing dialog. --- plugins/imagebase/plugin.js | 6 +++-- tests/plugins/imagebase/features/link.js | 30 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 54692820e03..d0e692daf55 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -71,7 +71,8 @@ editor.on( 'dialogShow', function( evt ) { var widget = getFocusedWidget( editor ), dialog = evt.data, - displayTextField; + displayTextField, + okListener; if ( !isLinkable( widget ) || dialog._.name !== 'link' ) { return; @@ -82,7 +83,7 @@ dialog.setupContent( widget.data.link || {} ); displayTextField.hide(); - dialog.once( 'ok', function( evt ) { + okListener = dialog.once( 'ok', function( evt ) { if ( !isLinkable( widget ) ) { return; } @@ -96,6 +97,7 @@ }, null, null, 9 ); dialog.once( 'hide', function() { + okListener.removeListener(); displayTextField.show(); } ); } ); diff --git a/tests/plugins/imagebase/features/link.js b/tests/plugins/imagebase/features/link.js index d586d157af0..1c2a7aab424 100644 --- a/tests/plugins/imagebase/features/link.js +++ b/tests/plugins/imagebase/features/link.js @@ -321,6 +321,36 @@ } ); }, + 'test dialog ok listener is deleted when closing the dialog': function( editor, bot ) { + addTestWidget( editor ); + + testLinkCommand( { + bot: bot, + html: '

test

', + dialogCallback: function( dialog ) { + var paragraph = editor.editable().findOne( 'p' ).getChild( 0 ), + range = editor.createRange(); + + editor.once( 'dialogShow', function() { + resume( function() { + dialog.setValueOf( 'info', 'url', 'x' ); + dialog.getButton( 'ok' ).click(); + + assert.areSame( 1, editor.editable().find( 'p > a' ).count(), 'Link is correctly added' ); + } ); + } ); + + dialog.getButton( 'cancel' ).click(); + + range.setStart( paragraph, 1 ); + range.setEnd( paragraph, 3 ); + range.select(); + editor.execCommand( 'link' ); + wait(); + } + } ); + }, + 'test unlink image widget': function( editor, bot ) { addTestWidget( editor ); From 73f70581256c4870cba2e5676b767b5d1df25b51 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 14:20:56 +0100 Subject: [PATCH 192/642] Add explanation to ok listener. --- plugins/imagebase/plugin.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index d0e692daf55..601a884c577 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -83,6 +83,10 @@ dialog.setupContent( widget.data.link || {} ); displayTextField.hide(); + // This listener overwrites the default action after pressing "OK" button in link dialog. + // It gets the user input and set appropriate data in the widget. + // `evt.stop` and higher priority are necessary to prevent adding unwanted link to + // widget's caption. okListener = dialog.once( 'ok', function( evt ) { if ( !isLinkable( widget ) ) { return; From 1438830226a8d0ba19108aca257d6028765b45b5 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 14:25:52 +0100 Subject: [PATCH 193/642] Inline deleteLink function. --- plugins/imagebase/plugin.js | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 601a884c577..c68f1e7ee60 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -40,18 +40,6 @@ return link; } - function deleteLink( img ) { - var link = img.getAscendant( 'a' ); - - if ( !link ) { - return; - } - - img.replace( link ); - - return img; - } - function getLinkData( widget ) { return CKEDITOR.plugins.link.parseLinkAttributes( widget.editor, widget.parts.link ); } @@ -161,8 +149,7 @@ // Unlink was invoked. if ( link === null ) { - deleteLink( img ); - + this.parts.link.remove( true ); this.parts.link = null; } else { var linkElement = createLink( editor, img, link ); From 9429e7f1e06100bafd6ebc95394a065dcd0d7151 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 14:27:42 +0100 Subject: [PATCH 194/642] Inline createLink invocation. --- plugins/imagebase/plugin.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index c68f1e7ee60..1bc87349daf 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -152,9 +152,7 @@ this.parts.link.remove( true ); this.parts.link = null; } else { - var linkElement = createLink( editor, img, link ); - - this.parts.link = linkElement; + this.parts.link = createLink( editor, img, link ); } } } From 068dd7bb2d835a54956abb4ea54f838b78e1740d Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 14:29:13 +0100 Subject: [PATCH 195/642] Adjust API docs. --- plugins/imagebase/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 1bc87349daf..b5b35910232 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -272,7 +272,7 @@ }, /** - * Adds new feature to the newly created image widget by invoking initial setup once for the editor + * Adds new feature to the passed widget's definition by invoking initial setup once for the editor * and extending widget's definition to include all fields needed by this feature. * * var widgetDefinition = {}; From f458b57de6a4496fb32aa5903ba4e5fdabd3c39c Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 14:34:54 +0100 Subject: [PATCH 196/642] Pass widget definition as second parameter to setUp. --- plugins/imagebase/plugin.js | 2 +- tests/plugins/imagebase/features/api.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index b5b35910232..85fc12f0318 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -303,7 +303,7 @@ featureDefinition.data = mergeMethods( definition.data, featureDefinition.data ); if ( featureDefinition.setUp ) { - featureDefinition.setUp( editor ); + featureDefinition.setUp( editor, definition ); delete featureDefinition.setUp; } diff --git a/tests/plugins/imagebase/features/api.js b/tests/plugins/imagebase/features/api.js index 9d769b13402..bc21471ec5c 100644 --- a/tests/plugins/imagebase/features/api.js +++ b/tests/plugins/imagebase/features/api.js @@ -33,6 +33,24 @@ 'Widget definition has correct value for widgetFeatures property' ); linkDefinition.setUp = originalSetUp; + }, + + 'testing feature.setUp parameters': function() { + var plugin = CKEDITOR.plugins.imagebase, + editor = this.editor, + widgetDefinition = {}, + spy = sinon.spy(); + + plugin.featuresDefinitions.foo = { + setUp: spy + }; + + plugin.addFeature( editor, 'foo', widgetDefinition ); + + assert.isTrue( spy.calledWithExactly( editor, widgetDefinition ), + 'setUp is called with appropriate parameters' ); + + delete plugin.featuresDefinitions.foo; } } ); } )(); From c5db91fb6a72ff8a862b2f5c676224092c5a7cd0 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 10 Nov 2017 15:18:13 +0100 Subject: [PATCH 197/642] Prevent setUp if there is no link plugin loaded. --- plugins/imagebase/plugin.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 85fc12f0318..0eebcdbe51f 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -56,6 +56,10 @@ }, setUp: function( editor ) { + if ( !editor.plugins.link ) { + return; + } + editor.on( 'dialogShow', function( evt ) { var widget = getFocusedWidget( editor ), dialog = evt.data, From 507817180d8ab0782b0fd72efbebf80bcf57174d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 10 Nov 2017 18:23:14 +0100 Subject: [PATCH 198/642] Docs: minor corrections to API docs. --- plugins/imagebase/plugin.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 0eebcdbe51f..6ae2ad0dd89 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -57,6 +57,7 @@ setUp: function( editor ) { if ( !editor.plugins.link ) { + // All of listeners registered later on make only when link plugin is loaded. return; } @@ -200,7 +201,7 @@ requiredContent: 'figure; img[!src]', /** - * The array containing names of features added to this widget's definition + * The array containing names of features added to this widget's definition. * * @property {String[]} widgetFeatures */ From 98c7cc96b4e4ee21138ad1970b8a358db129dc0e Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 11 Nov 2017 14:58:47 +0100 Subject: [PATCH 199/642] Docs: added missing word in base image code comment. --- plugins/imagebase/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 6ae2ad0dd89..c28702c8dcb 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -57,7 +57,7 @@ setUp: function( editor ) { if ( !editor.plugins.link ) { - // All of listeners registered later on make only when link plugin is loaded. + // All of listeners registered later on make only sense when link plugin is loaded. return; } From 9e6f988dafd4d28cc944a3c418fb9cb599cfcba4 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 11 Nov 2017 13:41:53 +0100 Subject: [PATCH 200/642] Tests: added a TC for widgetFeatures being added. --- tests/plugins/imagebase/features/api.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/plugins/imagebase/features/api.js b/tests/plugins/imagebase/features/api.js index bc21471ec5c..32db10e30a6 100644 --- a/tests/plugins/imagebase/features/api.js +++ b/tests/plugins/imagebase/features/api.js @@ -51,6 +51,23 @@ 'setUp is called with appropriate parameters' ); delete plugin.featuresDefinitions.foo; + }, + + 'test widgetDefinition.widgetFeatures stacking': function() { + var plugin = CKEDITOR.plugins.imagebase, + inputDefinition = { + widgetFeatures: [ 'bar' ] + }; + + plugin.featuresDefinitions.foo = {}; + plugin.featuresDefinitions.bar = {}; + + var outputDefinition = plugin.addFeature( this.editor, 'foo', inputDefinition ); + + // Cleanup. + delete plugin.featuresDefinitions.foo; + + arrayAssert.itemsAreSame( [ 'bar', 'foo' ], outputDefinition.widgetFeatures ); } } ); } )(); From f626a277eaff8388c945ff89ec78ab5ae433af71 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 11 Nov 2017 14:06:54 +0100 Subject: [PATCH 201/642] Make sure that existing widget features are preserved. --- plugins/imagebase/plugin.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index c28702c8dcb..1a62d5af722 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -291,7 +291,8 @@ * with fields needed by feature. */ addFeature: function( editor, name, definition ) { - var featureDefinition = CKEDITOR.tools.clone( this.featuresDefinitions[ name ] ); + var featureDefinition = CKEDITOR.tools.clone( this.featuresDefinitions[ name ] ), + ret; function mergeMethods( oldOne, newOne ) { if ( !oldOne && !newOne ) { @@ -313,9 +314,15 @@ delete featureDefinition.setUp; } - featureDefinition.widgetFeatures = [ name ]; + ret = CKEDITOR.tools.object.merge( definition, featureDefinition ); - return CKEDITOR.tools.object.merge( definition, featureDefinition ); + if ( !CKEDITOR.tools.isArray( ret.widgetFeatures ) ) { + ret.widgetFeatures = []; + } + + ret.widgetFeatures.push( name ); + + return ret; } }; }() ); From 36abcbfdd7ab9baae7988029d117f0f022a2b86d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 11 Nov 2017 14:18:24 +0100 Subject: [PATCH 202/642] Tests: corrections to features API test suite. --- tests/plugins/imagebase/features/api.js | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/tests/plugins/imagebase/features/api.js b/tests/plugins/imagebase/features/api.js index 32db10e30a6..022135bb4ed 100644 --- a/tests/plugins/imagebase/features/api.js +++ b/tests/plugins/imagebase/features/api.js @@ -8,34 +8,28 @@ bender.editor = true; bender.test( { - 'testing adding new feature': function() { + 'test adding new feature': function() { var plugin = CKEDITOR.plugins.imagebase, editor = this.editor, widgetDefinition = {}, linkDefinition = plugin.featuresDefinitions.link, - originalSetUp = linkDefinition.setUp, - callCount = 0, - originalLinkDefinition, + originalLinkDefinition = CKEDITOR.tools.clone( linkDefinition ), + setUp = sinon.stub( linkDefinition, 'setUp' ), extendedDefinition; - linkDefinition.setUp = function() { - callCount++; - }; - originalLinkDefinition = CKEDITOR.tools.clone( linkDefinition ); - extendedDefinition = plugin.addFeature( editor, 'link', widgetDefinition ); + setUp.restore(); + objectAssert.areDeepEqual( originalLinkDefinition, plugin.featuresDefinitions.link, 'Link feature definition is not modified' ); assert.areNotSame( widgetDefinition, extendedDefinition, 'addFeature returns new definition' ); - assert.areSame( 1, callCount, 'setUp was called only once' ); + assert.areSame( 1, setUp.callCount, 'setUp call count' ); arrayAssert.itemsAreSame( [ 'link' ], extendedDefinition.widgetFeatures, 'Widget definition has correct value for widgetFeatures property' ); - - linkDefinition.setUp = originalSetUp; }, - 'testing feature.setUp parameters': function() { + 'test feature.setUp parameters': function() { var plugin = CKEDITOR.plugins.imagebase, editor = this.editor, widgetDefinition = {}, @@ -47,10 +41,10 @@ plugin.addFeature( editor, 'foo', widgetDefinition ); + delete plugin.featuresDefinitions.foo; + assert.isTrue( spy.calledWithExactly( editor, widgetDefinition ), 'setUp is called with appropriate parameters' ); - - delete plugin.featuresDefinitions.foo; }, 'test widgetDefinition.widgetFeatures stacking': function() { From 15f67adbdd17c3f7d46ef08979dd4394681c9c57 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 11 Nov 2017 14:40:50 +0100 Subject: [PATCH 203/642] Tests: Simplified link command assertions. --- tests/plugins/imagebase/features/link.js | 41 ++++++++---------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/tests/plugins/imagebase/features/link.js b/tests/plugins/imagebase/features/link.js index 1c2a7aab424..2fa98ae7b10 100644 --- a/tests/plugins/imagebase/features/link.js +++ b/tests/plugins/imagebase/features/link.js @@ -44,45 +44,32 @@ } ); } - function assertLinkWidget( options ) { + function assertLinkWidgetStatus( options, linkCount, linkCmdState, unlinkCmdState ) { var editor = options.editor, linkCmd = editor.getCommand( 'link' ), unlinkCmd = editor.getCommand( 'unlink' ), - widget; - - if ( options.widget ) { - widget = options.widget; - } else { - widget = widgetTestsTools.getWidgetByDOMOffset( editor, 0 ); - } + widget = options.widget || widgetTestsTools.getWidgetByDOMOffset( editor, 0 ); widget.focus(); - assert.areSame( 1, widget.element.find( 'a' ).count(), 'There is only one link element inside widget' ); - assert.areSame( CKEDITOR.TRISTATE_OFF, linkCmd.state, 'Link command state' ); - assert.areSame( CKEDITOR.TRISTATE_OFF, unlinkCmd.state, 'Unlink command state' ); + assert.areSame( linkCount, widget.element.find( 'a' ).count(), 'There is only one link element inside widget' ); + assert.areSame( linkCmdState, linkCmd.state, 'Link command state' ); + assert.areSame( unlinkCmdState, unlinkCmd.state, 'Unlink command state' ); + + return widget; + } + + function assertLinkWidget( options ) { + var widget = assertLinkWidgetStatus( options, 1, CKEDITOR.TRISTATE_OFF, CKEDITOR.TRISTATE_OFF ); + assert.isObject( widget.parts.link, 'Widget has link part' ); objectAssert.areDeepEqual( options.data, widget.data.link, 'Widget has correct link data' ); - assertAttributes( editor, widget.parts.link, options.data ); + assertAttributes( options.editor, widget.parts.link, options.data ); } function assertUnlinkWidget( options ) { - var editor = options.editor, - linkCmd = editor.getCommand( 'link' ), - unlinkCmd = editor.getCommand( 'unlink' ), - widget; - - if ( options.widget ) { - widget = options.widget; - } else { - widget = widgetTestsTools.getWidgetByDOMOffset( editor, 0 ); - } - - widget.focus(); + var widget = assertLinkWidgetStatus( options, 0, CKEDITOR.TRISTATE_OFF, CKEDITOR.TRISTATE_DISABLED ); - assert.areSame( 0, widget.element.find( 'a' ).count(), 'There is no link element inside widget' ); - assert.areSame( CKEDITOR.TRISTATE_OFF, linkCmd.state, 'Link command state' ); - assert.areSame( CKEDITOR.TRISTATE_DISABLED, unlinkCmd.state, 'Unlink command state' ); assert.isNull( widget.parts.link, 'Widget does not have link part' ); assert.isNull( widget.data.link, 'Widget does not have link data' ); } From 685ff570f3f23a8885bf970e6cef1d1a0b7a3d2d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 11 Nov 2017 14:57:24 +0100 Subject: [PATCH 204/642] Tests: added test case for https link upcasting. --- tests/plugins/imagebase/features/link.html | 8 +++++++ tests/plugins/imagebase/features/link.js | 26 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/tests/plugins/imagebase/features/link.html b/tests/plugins/imagebase/features/link.html index 090e276f4e0..2c1c8b25be1 100644 --- a/tests/plugins/imagebase/features/link.html +++ b/tests/plugins/imagebase/features/link.html @@ -5,3 +5,11 @@
+ +
+
+ + + +
+
diff --git a/tests/plugins/imagebase/features/link.js b/tests/plugins/imagebase/features/link.js index 2fa98ae7b10..29a494a77a2 100644 --- a/tests/plugins/imagebase/features/link.js +++ b/tests/plugins/imagebase/features/link.js @@ -173,6 +173,32 @@ } ); }, + 'test upcasting image widget with https link': function( editor, bot ) { + addTestWidget( editor ); + + widgetTestsTools.assertWidget( { + count: 1, + widgetOffset: 0, + nameCreated: 'testWidget', + html: CKEDITOR.document.getById( 'upcastTestHttps' ).getHtml(), + bot: bot, + assertCreated: function( widget ) { + assertLinkWidget( { + widget: widget, + editor: editor, + url: 'foo', + data: { + type: 'url', + url: { + protocol: 'https://', + url: 'img' + } + } + } ); + } + } ); + }, + 'test add link to existing image widget': function( editor, bot ) { addTestWidget( editor ); From 4dd2fc946feeff300ab19b4ab9edd523201c5ae2 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 11 Nov 2017 15:52:13 +0100 Subject: [PATCH 205/642] Tests: added test case for checking whether both base and widget feature data/init are called. --- tests/plugins/imagebase/features/api.js | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/plugins/imagebase/features/api.js b/tests/plugins/imagebase/features/api.js index 022135bb4ed..9e7f601ec7b 100644 --- a/tests/plugins/imagebase/features/api.js +++ b/tests/plugins/imagebase/features/api.js @@ -29,6 +29,39 @@ 'Widget definition has correct value for widgetFeatures property' ); }, + 'test baseWidget functions remain called': function() { + var plugin = CKEDITOR.plugins.imagebase, + editor = this.editor, + inputDefinition = { + init: sinon.stub(), + data: sinon.stub() + }, + dummyFeature = { + init: sinon.stub(), + data: sinon.stub() + }, + outputDefinition; + + plugin.featuresDefinitions.dummy = dummyFeature; + + outputDefinition = plugin.addFeature( editor, 'dummy', inputDefinition ); + + delete plugin.featuresDefinitions.dummy; + + outputDefinition.init( 1 ); + outputDefinition.data( 2 ); + + assert.areSame( 1, inputDefinition.init.callCount, 'inputDefinition.init call count' ); + assert.areSame( 1, inputDefinition.data.callCount, 'inputDefinition.data call count' ); + assert.areSame( 1, dummyFeature.init.callCount, 'dummyFeature.init call count' ); + assert.areSame( 1, dummyFeature.data.callCount, 'dummyFeature.data call count' ); + + sinon.assert.alwaysCalledWithExactly( inputDefinition.init, 1 ); + sinon.assert.alwaysCalledWithExactly( inputDefinition.data, 2 ); + sinon.assert.alwaysCalledWithExactly( dummyFeature.init, 1 ); + sinon.assert.alwaysCalledWithExactly( dummyFeature.data, 2 ); + }, + 'test feature.setUp parameters': function() { var plugin = CKEDITOR.plugins.imagebase, editor = this.editor, From 69f126ba135fb9286893be9dc905efc8736500db Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 11 Nov 2017 16:05:16 +0100 Subject: [PATCH 206/642] Tests: increase editor height, so that both images are visible without scrolling. Also removed redundant config. --- tests/plugins/imagebase/features/manual/link.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plugins/imagebase/features/manual/link.html b/tests/plugins/imagebase/features/manual/link.html index 5bfc9150a77..bb66ee43500 100644 --- a/tests/plugins/imagebase/features/manual/link.html +++ b/tests/plugins/imagebase/features/manual/link.html @@ -16,7 +16,6 @@ From 02591f89aa4be7ee2358d35ca4b6abd2b903cb43 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 11 Nov 2017 16:21:44 +0100 Subject: [PATCH 207/642] Tests: linked a common image, so that browser does not complain about 404 / unresolved urls. --- tests/plugins/imagebase/features/link.html | 4 ++-- tests/plugins/imagebase/features/link.js | 14 +++++++------- tests/plugins/imagebase/imagebase.html | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/plugins/imagebase/features/link.html b/tests/plugins/imagebase/features/link.html index 2c1c8b25be1..0f18fe530ca 100644 --- a/tests/plugins/imagebase/features/link.html +++ b/tests/plugins/imagebase/features/link.html @@ -1,7 +1,7 @@ @@ -9,7 +9,7 @@ diff --git a/tests/plugins/imagebase/features/link.js b/tests/plugins/imagebase/features/link.js index 29a494a77a2..111761d1d61 100644 --- a/tests/plugins/imagebase/features/link.js +++ b/tests/plugins/imagebase/features/link.js @@ -204,7 +204,7 @@ testLinkCommand( { bot: bot, - html: '
', + html: '
', url: 'x', dialogCallback: function( dialog, widget ) { var data = {}; @@ -228,7 +228,7 @@ testLinkCommand( { bot: bot, - html: '
', + html: '
', initialUrl: 'foo', unlinkCmdState: CKEDITOR.TRISTATE_OFF, dialogCallback: function( dialog, widget ) { @@ -256,7 +256,7 @@ testLinkCommand( { bot: bot, - html: '
', + html: '
', url: 'x', dialogCallback: function( dialog, widget ) { var data = {}; @@ -281,7 +281,7 @@ testLinkCommand( { bot: bot, - html: '
', + html: '
', initialUrl: 'foo', unlinkCmdState: CKEDITOR.TRISTATE_OFF, dialogCallback: function( dialog, widget ) { @@ -310,7 +310,7 @@ testLinkCommand( { bot: bot, - html: '
', + html: '
', initialUrl: 'foo', unlinkCmdState: CKEDITOR.TRISTATE_OFF, dialogCallback: function( dialog, widget ) { @@ -339,7 +339,7 @@ testLinkCommand( { bot: bot, - html: '

test

', + html: '

test

', dialogCallback: function( dialog ) { var paragraph = editor.editable().findOne( 'p' ).getChild( 0 ), range = editor.createRange(); @@ -369,7 +369,7 @@ testUnlinkCommand( { bot: bot, - html: '
', + html: '
', callback: function( evt, widget ) { assertUnlinkWidget( { diff --git a/tests/plugins/imagebase/imagebase.html b/tests/plugins/imagebase/imagebase.html index 818b61647f5..7728408efad 100644 --- a/tests/plugins/imagebase/imagebase.html +++ b/tests/plugins/imagebase/imagebase.html @@ -2,10 +2,10 @@
Foo
- +
- +
From 549d5c05aa80ed3d0675258033fbd23914244e99 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 11 Nov 2017 16:22:38 +0100 Subject: [PATCH 208/642] Rename property enumerating implemented features from widgetFeatures to features. --- plugins/imagebase/plugin.js | 12 ++++++------ tests/plugins/imagebase/features/api.js | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 1a62d5af722..c080875229d 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -11,7 +11,7 @@ } function isLinkable( widget ) { - return widget && widget.widgetFeatures && CKEDITOR.tools.array.indexOf( widget.widgetFeatures, 'link' ) !== -1; + return widget && widget.features && CKEDITOR.tools.array.indexOf( widget.features, 'link' ) !== -1; } function addLinkAttributes( editor, linkElement, linkData ) { @@ -203,9 +203,9 @@ /** * The array containing names of features added to this widget's definition. * - * @property {String[]} widgetFeatures + * @property {String[]} features */ - widgetFeatures: [], + features: [], editables: { caption: { @@ -316,11 +316,11 @@ ret = CKEDITOR.tools.object.merge( definition, featureDefinition ); - if ( !CKEDITOR.tools.isArray( ret.widgetFeatures ) ) { - ret.widgetFeatures = []; + if ( !CKEDITOR.tools.isArray( ret.features ) ) { + ret.features = []; } - ret.widgetFeatures.push( name ); + ret.features.push( name ); return ret; } diff --git a/tests/plugins/imagebase/features/api.js b/tests/plugins/imagebase/features/api.js index 9e7f601ec7b..fda3897b091 100644 --- a/tests/plugins/imagebase/features/api.js +++ b/tests/plugins/imagebase/features/api.js @@ -25,8 +25,8 @@ 'Link feature definition is not modified' ); assert.areNotSame( widgetDefinition, extendedDefinition, 'addFeature returns new definition' ); assert.areSame( 1, setUp.callCount, 'setUp call count' ); - arrayAssert.itemsAreSame( [ 'link' ], extendedDefinition.widgetFeatures, - 'Widget definition has correct value for widgetFeatures property' ); + arrayAssert.itemsAreSame( [ 'link' ], extendedDefinition.features, + 'Widget definition has correct value for features property' ); }, 'test baseWidget functions remain called': function() { @@ -80,10 +80,10 @@ 'setUp is called with appropriate parameters' ); }, - 'test widgetDefinition.widgetFeatures stacking': function() { + 'test widgetDefinition.features stacking': function() { var plugin = CKEDITOR.plugins.imagebase, inputDefinition = { - widgetFeatures: [ 'bar' ] + features: [ 'bar' ] }; plugin.featuresDefinitions.foo = {}; @@ -94,7 +94,7 @@ // Cleanup. delete plugin.featuresDefinitions.foo; - arrayAssert.itemsAreSame( [ 'bar', 'foo' ], outputDefinition.widgetFeatures ); + arrayAssert.itemsAreSame( [ 'bar', 'foo' ], outputDefinition.features ); } } ); } )(); From ea83cf4c450a1dcfe2543bec153b0b5a56d44129 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sun, 12 Nov 2017 15:26:49 +0100 Subject: [PATCH 209/642] Reuse options in assertLinkWidgetStatus. --- tests/plugins/imagebase/features/link.js | 26 ++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tests/plugins/imagebase/features/link.js b/tests/plugins/imagebase/features/link.js index 111761d1d61..9f390454662 100644 --- a/tests/plugins/imagebase/features/link.js +++ b/tests/plugins/imagebase/features/link.js @@ -44,7 +44,7 @@ } ); } - function assertLinkWidgetStatus( options, linkCount, linkCmdState, unlinkCmdState ) { + function assertLinkWidgetStatus( options ) { var editor = options.editor, linkCmd = editor.getCommand( 'link' ), unlinkCmd = editor.getCommand( 'unlink' ), @@ -52,15 +52,22 @@ widget.focus(); - assert.areSame( linkCount, widget.element.find( 'a' ).count(), 'There is only one link element inside widget' ); - assert.areSame( linkCmdState, linkCmd.state, 'Link command state' ); - assert.areSame( unlinkCmdState, unlinkCmd.state, 'Unlink command state' ); + assert.areSame( options.linkCount, widget.element.find( 'a' ).count(), 'There is only one link element inside widget' ); + assert.areSame( options.linkCmdState, linkCmd.state, 'Link command state' ); + assert.areSame( options.unlinkCmdState, unlinkCmd.state, 'Unlink command state' ); return widget; } function assertLinkWidget( options ) { - var widget = assertLinkWidgetStatus( options, 1, CKEDITOR.TRISTATE_OFF, CKEDITOR.TRISTATE_OFF ); + var widget; + + CKEDITOR.tools.extend( options, { + linkCount: 1, + linkCmdState: CKEDITOR.TRISTATE_OFF, + unlinkCmdState: CKEDITOR.TRISTATE_OFF + } ); + widget = assertLinkWidgetStatus( options ); assert.isObject( widget.parts.link, 'Widget has link part' ); objectAssert.areDeepEqual( options.data, widget.data.link, 'Widget has correct link data' ); @@ -68,7 +75,14 @@ } function assertUnlinkWidget( options ) { - var widget = assertLinkWidgetStatus( options, 0, CKEDITOR.TRISTATE_OFF, CKEDITOR.TRISTATE_DISABLED ); + var widget; + + CKEDITOR.tools.extend( options, { + linkCount: 0, + linkCmdState: CKEDITOR.TRISTATE_OFF, + unlinkCmdState: CKEDITOR.TRISTATE_DISABLED + } ); + widget = assertLinkWidgetStatus( options ); assert.isNull( widget.parts.link, 'Widget does not have link part' ); assert.isNull( widget.data.link, 'Widget does not have link data' ); From da332ed811b98e828dca34f9638c68e9f8a21059 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sun, 12 Nov 2017 15:32:15 +0100 Subject: [PATCH 210/642] Remove not longer used initialUrl option. --- tests/plugins/imagebase/features/link.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/plugins/imagebase/features/link.js b/tests/plugins/imagebase/features/link.js index 9f390454662..32d4817f277 100644 --- a/tests/plugins/imagebase/features/link.js +++ b/tests/plugins/imagebase/features/link.js @@ -243,7 +243,6 @@ testLinkCommand( { bot: bot, html: '
', - initialUrl: 'foo', unlinkCmdState: CKEDITOR.TRISTATE_OFF, dialogCallback: function( dialog, widget ) { var data = {}; @@ -296,7 +295,6 @@ testLinkCommand( { bot: bot, html: '
', - initialUrl: 'foo', unlinkCmdState: CKEDITOR.TRISTATE_OFF, dialogCallback: function( dialog, widget ) { var data = {}; @@ -325,7 +323,6 @@ testLinkCommand( { bot: bot, html: '
', - initialUrl: 'foo', unlinkCmdState: CKEDITOR.TRISTATE_OFF, dialogCallback: function( dialog, widget ) { var data = {}; From 86c8d2868118984454417b07302efa920d7a0435 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sun, 12 Nov 2017 15:45:00 +0100 Subject: [PATCH 211/642] Clean up remaining dummy feature. --- tests/plugins/imagebase/features/api.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/plugins/imagebase/features/api.js b/tests/plugins/imagebase/features/api.js index fda3897b091..ab7a6a5b4c4 100644 --- a/tests/plugins/imagebase/features/api.js +++ b/tests/plugins/imagebase/features/api.js @@ -93,6 +93,7 @@ // Cleanup. delete plugin.featuresDefinitions.foo; + delete plugin.featuresDefinitions.bar; arrayAssert.itemsAreSame( [ 'bar', 'foo' ], outputDefinition.features ); } From 9a0e9ac1b422c34cc63e8779a4a2da26da76503a Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 12 Nov 2017 23:32:27 +0100 Subject: [PATCH 212/642] Corrected side image CSS selector. --- plugins/easyimage/styles/easyimage.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index 65482ccc96e..44773b84db8 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -18,7 +18,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license max-width: 100%; } -.cke_widget_wrapper_easyimage-side, :not(.cke_widget_wrapper_easyimage-side) > .easyimage { +.cke_widget_wrapper_easyimage-side, :not(.cke_widget_wrapper_easyimage):not(.cke_widget_wrapper_easyimage-side) > .easyimage-side { /* :not() selector will be used for Easy Image content ouside of the editor. E.g. when the editor was destoryed. See https://github.com/ckeditor/ckeditor-dev/pull/1150#discussion_r150415261 for more details. From ebeff803a6e5943d167a7623ff38fbff91f4018f Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 13 Nov 2017 02:28:40 +0100 Subject: [PATCH 213/642] Tests: corrected assertion message. --- tests/plugins/easyimage/uploadwidget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index 29fab7f0bf4..7fcfb998b92 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -129,7 +129,7 @@ loader.changeStatus( 'uploaded' ); assert.sameData( WIDGET_HTML, editor.getData() ); - assert.areSame( 1, editor.editable().find( '[data-widget="easyimage"]' ).count(), 'dupa' ); + assert.areSame( 1, editor.editable().find( '[data-widget="easyimage"]' ).count(), 'Easy Image widgets count' ); assert.areSame( 0, loadAndUploadCount ); assert.areSame( 1, uploadCount ); From 324d201be1f62e9240a4e2ccfc970c6a3793a5e2 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 8 Nov 2017 14:34:57 +0100 Subject: [PATCH 214/642] Added manual test for upload notification, that is reusing logic from uploadwidget helper. --- .../plugins/easyimage/manual/progressbar.html | 52 +++++++++++++++++++ tests/plugins/easyimage/manual/progressbar.md | 19 +++++++ .../uploadwidget/manual/_helpers/xhr.js | 4 +- 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/plugins/easyimage/manual/progressbar.html create mode 100644 tests/plugins/easyimage/manual/progressbar.md diff --git a/tests/plugins/easyimage/manual/progressbar.html b/tests/plugins/easyimage/manual/progressbar.html new file mode 100644 index 00000000000..96186f51265 --- /dev/null +++ b/tests/plugins/easyimage/manual/progressbar.html @@ -0,0 +1,52 @@ + +

Classic editor

+ +
+

Sample editor

+ +

Go on, put some content here.

+
+ +

Divarea editor

+ +
+

Sample editor

+ +

Go on, put some content here.

+
+ +

Inline editor

+ +
+

Sample editor

+ +

Go on, put some content here.

+
+ + diff --git a/tests/plugins/easyimage/manual/progressbar.md b/tests/plugins/easyimage/manual/progressbar.md new file mode 100644 index 00000000000..d46f2799fc7 --- /dev/null +++ b/tests/plugins/easyimage/manual/progressbar.md @@ -0,0 +1,19 @@ +@bender-tags: 4.8.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage +@bender-include: ../../uploadwidget/manual/_helpers/xhr.js + +## Upload Progress + +Remarks: + +* In the end your image will be replaced with old CKEditor 4 logo. +* Upload progress is intentionally slowed down. + +### Steps + +1. Drop an image into the editor. + +### Expected + +* Upload progress is shown. diff --git a/tests/plugins/uploadwidget/manual/_helpers/xhr.js b/tests/plugins/uploadwidget/manual/_helpers/xhr.js index fd774780071..eb0c90d5ac1 100644 --- a/tests/plugins/uploadwidget/manual/_helpers/xhr.js +++ b/tests/plugins/uploadwidget/manual/_helpers/xhr.js @@ -11,7 +11,7 @@ window.FormData = function() { var total, uploadedFilename; return { append: function( name, file, filename ) { - if ( name == 'upload' ) { + if ( CKEDITOR.tools.array.indexOf( [ 'upload', 'file' ], name ) !== -1 ) { total = file.size; uploadedFilename = filename; } @@ -32,6 +32,8 @@ window.XMLHttpRequest = function() { return { open: function() {}, + setRequestHeader: function() {}, + upload: {}, send: function( formData ) { From 8623ff185c47c486bd058acc185a463283208bc0 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 8 Nov 2017 21:04:51 +0100 Subject: [PATCH 215/642] Added a basic custom implementation for a progress bar in Easy Image plugin. --- plugins/easyimage/plugin.js | 75 ++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index f57a9f0f2d3..ae9dbd96e2c 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -171,6 +171,51 @@ } function registerUploadWidget( editor ) { + editor.on( 'widgetDefinition', function( evt ) { + var definition = evt.data, + baseInit; + + if ( definition.name === 'uploadeasyimage' ) { + // Extend init method. + baseInit = definition.init; + + definition.init = function() { + var loader = this.definition._getLoader( this ), + progressListeners = []; + + function removeProgressListeners() { + if ( progressListeners ) { + CKEDITOR.tools.array.forEach( progressListeners, function( listener ) { + listener.removeListener(); + } ); + + progressListeners = null; + } + } + + // Add a progress bar. + this.definition._createProgressBar( this ); + + progressListeners.push( loader.on( 'update', function() { + var progressBar = this.parts.progressBar.findOne( '.cke_bar' ), + percentage; + + if ( progressBar && loader.uploadTotal ) { + percentage = ( loader.uploaded / loader.uploadTotal ) * 100; + progressBar.setStyle( 'width', percentage + '%' ); + } + }, this ) ); + + progressListeners.push( loader.once( 'abort', removeProgressListeners ) ); + progressListeners.push( loader.once( 'error', removeProgressListeners ) ); + progressListeners.push( loader.once( 'uploaded', removeProgressListeners ) ); + + // Call base init implementation. + baseInit.call( this ); + }; + } + } ); + CKEDITOR.fileTools.addUploadWidget( editor, 'uploadeasyimage', { supportedTypes: /image\/(jpeg|png|gif|bmp)/, @@ -186,7 +231,8 @@ }, parts: { - img: 'img' + img: 'img', + loader: '.cke_loader' }, onUploading: function( upload ) { @@ -199,6 +245,30 @@ this.replaceWith( '
' ); + }, + + /** + * Creates a progress bar in a given widget.h + * + * Also puts it in it's {@link CKEDITOR.plugins.widget#parts} structure as `progressBar` + * + * @private + * @param {CKEDITOR.plugins.widget} widget + */ + _createProgressBar: function( widget ) { + var ret = new CKEDITOR.dom.element( 'span' ); + ret.addClass( 'cke_loader' ); + + ret.setHtml( '' ); + + widget.wrapper.append( ret, true ); + + widget.parts.progressBar = ret; + }, + + // @todo: this function should be moved to uploadwidget core definition. + _getLoader: function( widget ) { + return widget.editor.uploadRepository.loaders[ widget.wrapper.findOne( '[data-cke-upload-id]' ).data( 'cke-upload-id' ) ]; } } ); @@ -297,6 +367,9 @@ onLoad: function() { CKEDITOR.dialog.add( 'easyimageAlt', this.path + 'dialogs/easyimagealt.js' ); + + CKEDITOR.addCss( '.cke_loader { height: 15px; display: block; background: yellow; position: absolute; left: 0px; right: 0px; }\n' + + '.cke_loader .cke_bar { display:block; height: 13px; background: red; width: 0; }' ); }, init: function( editor ) { From 0b40d9b62c004d605dfd0f30340289976f4ef925 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 9 Nov 2017 12:08:28 +0100 Subject: [PATCH 216/642] Added throttling for Easy Image upload progress and a smoother transition in progress bar. --- plugins/easyimage/plugin.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index ae9dbd96e2c..5c0b9368823 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -11,6 +11,8 @@ // jscs:disable maximumLineLength // Black rectangle which is shown before image is loaded. var loadingImage = 'data:image/gif;base64,R0lGODlhDgAOAIAAAAAAAP///yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs='; + // Throttling of progress update in ms. + var UPLOAD_PROGRESS_THROTTLING = 100; // jscs:enable maximumLineLength function addCommands( editor ) { @@ -196,7 +198,7 @@ // Add a progress bar. this.definition._createProgressBar( this ); - progressListeners.push( loader.on( 'update', function() { + var updateListener = CKEDITOR.tools.eventsBuffer( UPLOAD_PROGRESS_THROTTLING, function() { var progressBar = this.parts.progressBar.findOne( '.cke_bar' ), percentage; @@ -204,7 +206,9 @@ percentage = ( loader.uploaded / loader.uploadTotal ) * 100; progressBar.setStyle( 'width', percentage + '%' ); } - }, this ) ); + }, this ); + + progressListeners.push( loader.on( 'update', updateListener.input ) ); progressListeners.push( loader.once( 'abort', removeProgressListeners ) ); progressListeners.push( loader.once( 'error', removeProgressListeners ) ); @@ -369,7 +373,7 @@ CKEDITOR.dialog.add( 'easyimageAlt', this.path + 'dialogs/easyimagealt.js' ); CKEDITOR.addCss( '.cke_loader { height: 15px; display: block; background: yellow; position: absolute; left: 0px; right: 0px; }\n' + - '.cke_loader .cke_bar { display:block; height: 13px; background: red; width: 0; }' ); + '.cke_loader .cke_bar { display:block; height: 13px; background: red; width: 0; transition: width ' + UPLOAD_PROGRESS_THROTTLING / 1000 + 's; }' ); }, init: function( editor ) { From 8ef5bf7caeb5dd07573b8ed25a524741c443d5e0 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 9 Nov 2017 12:48:33 +0100 Subject: [PATCH 217/642] Improved styling, removed default upload notifications. --- plugins/easyimage/plugin.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 5c0b9368823..cbf9a36deb0 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -226,6 +226,8 @@ // Easy image uses only upload method, as is manually handled in onUploading function. loadMethod: 'upload', + skipNotifications: true, + loaderType: CKEDITOR.plugins.cloudservices.cloudServicesLoader, fileToElement: function() { @@ -372,8 +374,8 @@ onLoad: function() { CKEDITOR.dialog.add( 'easyimageAlt', this.path + 'dialogs/easyimagealt.js' ); - CKEDITOR.addCss( '.cke_loader { height: 15px; display: block; background: yellow; position: absolute; left: 0px; right: 0px; }\n' + - '.cke_loader .cke_bar { display:block; height: 13px; background: red; width: 0; transition: width ' + UPLOAD_PROGRESS_THROTTLING / 1000 + 's; }' ); + CKEDITOR.addCss( '.cke_loader { display: block; position: absolute; left: 0px; right: 0px; }\n' + + '.cke_loader .cke_bar { display:block; height: 10px; background: #6a9ed1; width: 0; transition: width ' + UPLOAD_PROGRESS_THROTTLING / 1000 + 's; }' ); }, init: function( editor ) { From cc57553863da844aa913de0992f059afce8b838d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 9 Nov 2017 16:05:49 +0100 Subject: [PATCH 218/642] Refactoring: converted CSS into multi-line format. --- plugins/easyimage/plugin.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index cbf9a36deb0..0dd8e716aa8 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -374,8 +374,20 @@ onLoad: function() { CKEDITOR.dialog.add( 'easyimageAlt', this.path + 'dialogs/easyimagealt.js' ); - CKEDITOR.addCss( '.cke_loader { display: block; position: absolute; left: 0px; right: 0px; }\n' + - '.cke_loader .cke_bar { display:block; height: 10px; background: #6a9ed1; width: 0; transition: width ' + UPLOAD_PROGRESS_THROTTLING / 1000 + 's; }' ); + CKEDITOR.addCss( + '.cke_loader {' + + 'display: block;' + + 'position: absolute;' + + 'left: 0px;' + + 'right: 0px;' + + '}' + + '.cke_loader .cke_bar {' + + 'display:block;' + + 'height: 10px;' + + 'background: #6a9ed1;' + + 'width: 0;' + + 'transition: width ' + UPLOAD_PROGRESS_THROTTLING / 1000 + 's;' + + '}' ); }, init: function( editor ) { From 48338075cee4a18c7f893076f9d1ee2e91094b9d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 9 Nov 2017 16:11:24 +0100 Subject: [PATCH 219/642] Docs: changed _createProgressBar docs to a private api docs format, as it was leaking to the global namespace. --- plugins/easyimage/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 0dd8e716aa8..b36c45b898f 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -253,7 +253,7 @@ upload.responseData.response[ 'default' ] + '" srcset="' + srcset + '" sizes="100vw">
' ); }, - /** + /* * Creates a progress bar in a given widget.h * * Also puts it in it's {@link CKEDITOR.plugins.widget#parts} structure as `progressBar` From a4805d2f0798069a95e54a1bb4090fb4c38453f8 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 9 Nov 2017 16:23:40 +0100 Subject: [PATCH 220/642] Corrected unit tests. --- tests/plugins/easyimage/uploadwidget.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index 7fcfb998b92..c4a607e3f28 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -392,14 +392,12 @@ wait(); }, - 'test bindNotifications when paste image': function( editor ) { + 'test custom loader': function( editor ) { CKEDITOR.fileTools.bindNotifications = sinon.spy(); resumeAfter( editor, 'paste', function() { var spy = CKEDITOR.fileTools.bindNotifications; - assert.areSame( 1, spy.callCount ); - assert.isTrue( spy.calledWith( editor ) ); - assert.areSame( bender.tools.pngBase64, spy.firstCall.args[ 1 ].data ); + assert.areSame( 0, spy.callCount ); } ); editor.fire( 'paste', { From 80e368e35a5cba380b657376d48ae3d840a5358d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 12 Nov 2017 23:51:02 +0100 Subject: [PATCH 221/642] Limit uploaded image max width too. --- plugins/easyimage/styles/easyimage.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index 44773b84db8..ecd2c82fc3e 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -11,7 +11,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license clear: both; } -.easyimage img { +.easyimage img, .cke_widget_uploadeasyimage img { display: block; height: auto; margin: 0 auto; From 7544f30d05b2a05f97a257d465e78410168d5af5 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 13 Nov 2017 00:07:45 +0100 Subject: [PATCH 222/642] Refactoring: cleaned up JS file, moved CSS to Easy Image contents CSS file. --- plugins/easyimage/plugin.js | 32 ++++++-------------------- plugins/easyimage/styles/easyimage.css | 16 +++++++++++++ 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index b36c45b898f..b6ca9d6b786 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -6,14 +6,11 @@ ( function() { 'use strict'; - var stylesLoaded = false; - - // jscs:disable maximumLineLength - // Black rectangle which is shown before image is loaded. - var loadingImage = 'data:image/gif;base64,R0lGODlhDgAOAIAAAAAAAP///yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs='; - // Throttling of progress update in ms. - var UPLOAD_PROGRESS_THROTTLING = 100; - // jscs:enable maximumLineLength + var stylesLoaded = false, + // Black rectangle which is shown before image is loaded. + loadingImage = 'data:image/gif;base64,R0lGODlhDgAOAIAAAAAAAP///yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs=', + // Throttling of progress update in ms. + UPLOAD_PROGRESS_THROTTLING = 100; function addCommands( editor ) { function isSideImage( widget ) { @@ -254,7 +251,7 @@ }, /* - * Creates a progress bar in a given widget.h + * Creates a progress bar in a given widget. * * Also puts it in it's {@link CKEDITOR.plugins.widget#parts} structure as `progressBar` * @@ -265,7 +262,7 @@ var ret = new CKEDITOR.dom.element( 'span' ); ret.addClass( 'cke_loader' ); - ret.setHtml( '' ); + ret.setHtml( '' ); widget.wrapper.append( ret, true ); @@ -373,21 +370,6 @@ onLoad: function() { CKEDITOR.dialog.add( 'easyimageAlt', this.path + 'dialogs/easyimagealt.js' ); - - CKEDITOR.addCss( - '.cke_loader {' + - 'display: block;' + - 'position: absolute;' + - 'left: 0px;' + - 'right: 0px;' + - '}' + - '.cke_loader .cke_bar {' + - 'display:block;' + - 'height: 10px;' + - 'background: #6a9ed1;' + - 'width: 0;' + - 'transition: width ' + UPLOAD_PROGRESS_THROTTLING / 1000 + 's;' + - '}' ); }, init: function( editor ) { diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index ecd2c82fc3e..74bdea679c5 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -42,3 +42,19 @@ For licensing, see LICENSE.md or http://ckeditor.com/license border: 1px solid #48a3f5; outline: none; } + +/* Loaders */ + +.cke_loader { + display: block; + position: absolute; + left: 0px; + right: 0px; +} + +.cke_loader .cke_bar { + display: block; + height: 10px; + background: #6a9ed1; + width: 0; +} \ No newline at end of file From 0c65019596b8e6f5e946e4cc73a73fc131527671 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 13 Nov 2017 00:14:02 +0100 Subject: [PATCH 223/642] Simplified progress bar CSS by making it a div. --- plugins/easyimage/plugin.js | 12 ++++-------- plugins/easyimage/styles/easyimage.css | 2 -- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index b6ca9d6b786..77dc0086d9f 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -259,14 +259,10 @@ * @param {CKEDITOR.plugins.widget} widget */ _createProgressBar: function( widget ) { - var ret = new CKEDITOR.dom.element( 'span' ); - ret.addClass( 'cke_loader' ); - - ret.setHtml( '' ); - - widget.wrapper.append( ret, true ); - - widget.parts.progressBar = ret; + widget.parts.progressBar = CKEDITOR.dom.element.createFromHtml( '
' + + '
' + + '
' ); + widget.wrapper.append( widget.parts.progressBar, true ); }, // @todo: this function should be moved to uploadwidget core definition. diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index 74bdea679c5..608e0b999bd 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -46,14 +46,12 @@ For licensing, see LICENSE.md or http://ckeditor.com/license /* Loaders */ .cke_loader { - display: block; position: absolute; left: 0px; right: 0px; } .cke_loader .cke_bar { - display: block; height: 10px; background: #6a9ed1; width: 0; From c411cc516c516a31c0ef58a96d4c143ebd1d5a72 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 13 Nov 2017 00:53:16 +0100 Subject: [PATCH 224/642] Wrapped all the upload progress bar in a single function, to keep it more modular. --- plugins/easyimage/plugin.js | 148 +++++++++++++----------- tests/plugins/easyimage/uploadwidget.js | 4 +- 2 files changed, 81 insertions(+), 71 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 77dc0086d9f..5d5e0ca02af 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -170,60 +170,13 @@ } function registerUploadWidget( editor ) { - editor.on( 'widgetDefinition', function( evt ) { - var definition = evt.data, - baseInit; - - if ( definition.name === 'uploadeasyimage' ) { - // Extend init method. - baseInit = definition.init; - - definition.init = function() { - var loader = this.definition._getLoader( this ), - progressListeners = []; - - function removeProgressListeners() { - if ( progressListeners ) { - CKEDITOR.tools.array.forEach( progressListeners, function( listener ) { - listener.removeListener(); - } ); - - progressListeners = null; - } - } - - // Add a progress bar. - this.definition._createProgressBar( this ); - - var updateListener = CKEDITOR.tools.eventsBuffer( UPLOAD_PROGRESS_THROTTLING, function() { - var progressBar = this.parts.progressBar.findOne( '.cke_bar' ), - percentage; - - if ( progressBar && loader.uploadTotal ) { - percentage = ( loader.uploaded / loader.uploadTotal ) * 100; - progressBar.setStyle( 'width', percentage + '%' ); - } - }, this ); - - progressListeners.push( loader.on( 'update', updateListener.input ) ); - - progressListeners.push( loader.once( 'abort', removeProgressListeners ) ); - progressListeners.push( loader.once( 'error', removeProgressListeners ) ); - progressListeners.push( loader.once( 'uploaded', removeProgressListeners ) ); - - // Call base init implementation. - baseInit.call( this ); - }; - } - } ); - - CKEDITOR.fileTools.addUploadWidget( editor, 'uploadeasyimage', { + var uploadWidgetDefinition = { supportedTypes: /image\/(jpeg|png|gif|bmp)/, // Easy image uses only upload method, as is manually handled in onUploading function. loadMethod: 'upload', - skipNotifications: true, + inline: false, loaderType: CKEDITOR.plugins.cloudservices.cloudServicesLoader, @@ -248,28 +201,12 @@ this.replaceWith( '
' ); - }, + } + }; - /* - * Creates a progress bar in a given widget. - * - * Also puts it in it's {@link CKEDITOR.plugins.widget#parts} structure as `progressBar` - * - * @private - * @param {CKEDITOR.plugins.widget} widget - */ - _createProgressBar: function( widget ) { - widget.parts.progressBar = CKEDITOR.dom.element.createFromHtml( '
' + - '
' + - '
' ); - widget.wrapper.append( widget.parts.progressBar, true ); - }, + addUploadProgressBar( editor, uploadWidgetDefinition ); - // @todo: this function should be moved to uploadwidget core definition. - _getLoader: function( widget ) { - return widget.editor.uploadRepository.loaders[ widget.wrapper.findOne( '[data-cke-upload-id]' ).data( 'cke-upload-id' ) ]; - } - } ); + CKEDITOR.fileTools.addUploadWidget( editor, 'uploadeasyimage', uploadWidgetDefinition ); // Handle images which are not available in the dataTransfer. // This means that we need to read them from the elements. @@ -317,6 +254,79 @@ } ); } + // Extends given uploadWidget `definition` with an upload progress bar, added within wrapper. + function addUploadProgressBar( editor, definition ) { + definition.skipNotifications = true; + definition.parts.loader = '.cke_loader'; + + /* + * Creates a progress bar in a given widget. + * + * Also puts it in it's {@link CKEDITOR.plugins.widget#parts} structure as `progressBar` + * + * @private + * @param {CKEDITOR.plugins.widget} widget + */ + definition._createProgressBar = function( widget ) { + widget.parts.progressBar = CKEDITOR.dom.element.createFromHtml( '
' + + '
' + + '
' ); + widget.wrapper.append( widget.parts.progressBar, true ); + }; + + // @todo: this function should be moved to uploadwidget core definition. + definition._getLoader = function( widget ) { + return widget.editor.uploadRepository.loaders[ widget.wrapper.findOne( '[data-cke-upload-id]' ).data( 'cke-upload-id' ) ]; + }; + + editor.on( 'widgetDefinition', function( evt ) { + var definition = evt.data, + baseInit; + + if ( definition.name === 'uploadeasyimage' ) { + // Extend init method, that was initially defined by the uploadwidget plugin. + baseInit = definition.init; + + definition.init = function() { + var loader = this.definition._getLoader( this ), + progressListeners = []; + + function removeProgressListeners() { + if ( progressListeners ) { + CKEDITOR.tools.array.forEach( progressListeners, function( listener ) { + listener.removeListener(); + } ); + + progressListeners = null; + } + } + + // Add a progress bar. + this.definition._createProgressBar( this ); + + var updateListener = CKEDITOR.tools.eventsBuffer( UPLOAD_PROGRESS_THROTTLING, function() { + var progressBar = this.parts.progressBar.findOne( '.cke_bar' ), + percentage; + + if ( progressBar && loader.uploadTotal ) { + percentage = ( loader.uploaded / loader.uploadTotal ) * 100; + progressBar.setStyle( 'width', percentage + '%' ); + } + }, this ); + + progressListeners.push( loader.on( 'update', updateListener.input ) ); + + progressListeners.push( loader.once( 'abort', removeProgressListeners ) ); + progressListeners.push( loader.once( 'error', removeProgressListeners ) ); + progressListeners.push( loader.once( 'uploaded', removeProgressListeners ) ); + + // Call base init implementation. + baseInit.call( this ); + }; + } + } ); + } + function loadStyles( editor, plugin ) { if ( !stylesLoaded ) { CKEDITOR.document.appendStyleSheet( plugin.path + 'styles/easyimage.css' ); diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index c4a607e3f28..fde3a4bd190 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -141,7 +141,7 @@ pasteFiles( editor, [], '

xx

' ); assertUploadingWidgets( editor, DATA_IMG ); - assert.areSame( '

xx

', editor.getData(), 'getData on loading.' ); + assert.areSame( '

x

x

', editor.getData(), 'getData on loading.' ); var loader = editor.uploadRepository.loaders[ 0 ]; @@ -149,7 +149,7 @@ loader.changeStatus( 'uploading' ); assertUploadingWidgets( editor, BLOB_IMG ); - assert.areSame( '

xx

', editor.getData(), 'getData on uploading.' ); + assert.areSame( '

x

x

', editor.getData(), 'getData on uploading.' ); var image = editor.editable().find( 'img[data-widget="uploadeasyimage"]' ).getItem( 0 ); From 77f06d5a08f97727d5fa4833139b4a8e4af7af55 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 13 Nov 2017 02:05:24 +0100 Subject: [PATCH 225/642] Added unit tests coverage for Easy Image progress bar. --- tests/plugins/easyimage/uploadwidget.js | 77 ++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 8 deletions(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index fde3a4bd190..c0a765be592 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -39,21 +39,34 @@ } }; - function assertUploadingWidgets( editor, expectedSrc ) { + function assertUploadingWidgets( editor, options ) { var tools = CKEDITOR.tools, array = tools.array, widgets = array.map( tools.objectKeys( editor.widgets.instances ), function( val ) { return editor.widgets.instances[ val ]; } ); + if ( typeof options === 'string' ) { + // Compatibility with the older format. + options = { + expectedSrc: options + }; + } + widgets = array.filter( widgets, function( val ) { return val.name === 'uploadeasyimage'; } ); assert.areSame( 1, widgets.length, 'Created widgets count' ); - assert.areSame( '0', widgets[ 0 ].element.getAttribute( 'data-cke-upload-id' ) ); - assert.areSame( expectedSrc, widgets[ 0 ].element.getAttribute( 'src' ).substring( 0, 5 ) ); + + if ( typeof options.expectedSrc !== 'undefined' ) { + assert.areSame( options.expectedSrc, widgets[ 0 ].element.getAttribute( 'src' ).substring( 0, 5 ) ); + } + + if ( options.callback ) { + options.callback( widgets ); + } } tests = { @@ -157,8 +170,7 @@ loader.url = IMG_URL; loader.changeStatus( 'uploaded' ); - assert.sameData( '

x

' + WIDGET_HTML + '

x

', - editor.getData() ); + assert.sameData( '

x

' + WIDGET_HTML + '

x

', editor.getData() ); assert.areSame( 1, editor.editable().find( '[data-widget="easyimage"]' ).count() ); assert.areSame( 0, loadAndUploadCount ); @@ -393,11 +405,11 @@ }, 'test custom loader': function( editor ) { - CKEDITOR.fileTools.bindNotifications = sinon.spy(); + var bindStub = sinon.stub( CKEDITOR.fileTools, 'bindNotifications' ); resumeAfter( editor, 'paste', function() { - var spy = CKEDITOR.fileTools.bindNotifications; - assert.areSame( 0, spy.callCount ); + bindStub.restore(); + assert.areSame( 0, bindStub.callCount ); } ); editor.fire( 'paste', { @@ -495,6 +507,55 @@ dataValue: '' } ); + wait(); + }, + + 'test progress bar': function( editor ) { + // When run in batch, this test tends to "inherit" some widgets from previous runs. Make sure that the list is clear. + editor.widgets.destroyAll(); + + pasteFiles( editor, [ bender.tools.getTestPngFile() ] ); + + // First stage, image file has just been pasted. This should create a progress bar, with initial markup. + assertUploadingWidgets( editor, { + callback: function( widgets ) { + var progressBarWrappers = widgets[ 0 ].wrapper.find( '.cke_loader' ), + progressBar; + + assert.areSame( 1, progressBarWrappers.count(), 'Progress bar wrappers count' ); + + progressBar = progressBarWrappers.getItem( 0 ).findOne( '.cke_bar' ); + + assert.isInstanceOf( CKEDITOR.dom.element, progressBar, 'Progress bar type' ); + assert.areSame( 0, progressBar.getClientRect().width, 'Progress bar width' ); + } + } ); + + // Then pick up the loader, and fake some progress. + var loader = editor.uploadRepository.loaders[ 0 ]; + + loader.data = bender.tools.pngBase64; + loader.uploaded = 2; + loader.uploadTotal = 10; + loader.changeStatus( 'uploading' ); + + // Status update is throttled, so we need to delay the checking. + window.setTimeout( function() { + resume( function() { + assertUploadingWidgets( editor, { + callback: function( widgets ) { + var progressBar = widgets[ 0 ].wrapper.findOne( '.cke_bar' ); + assert.areSame( '20%', progressBar.getStyle( 'width' ), 'Progress bar width after first update' ); + } + } ); + + // Normally we would wait for image to load, but we don't care for image in this test case, we fake all the progress update by ourself. + loader.changeStatus( 'uploaded' ); + + assert.areSame( 0, editor.editable().find( '.cke_loader' ).count(), 'Progress bar wrappers count in the whole editable' ); + } ); + }, 250 ); + wait(); } }; From 17466b9da0e47aa9b48e634d3da8ea2ef822be0a Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 13 Nov 2017 02:46:08 +0100 Subject: [PATCH 226/642] Removed old notification call in paste listener. --- plugins/easyimage/plugin.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 5d5e0ca02af..ea816f75ff0 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -245,8 +245,6 @@ loader.upload( widgetDef.uploadUrl, widgetDef.additionalRequestParameters ); fileTools.markElement( img, 'uploadeasyimage', loader.id ); - - fileTools.bindNotifications( editor, loader ); } } From 892758caf990363afc2f7d53f8b0bdd1ff7de43d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 13 Nov 2017 03:12:38 +0100 Subject: [PATCH 227/642] Moved loader getter to the Upload Widget base definition. --- plugins/easyimage/plugin.js | 7 +------ plugins/uploadwidget/plugin.js | 8 ++++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index ea816f75ff0..4dbd51c6c25 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -272,11 +272,6 @@ widget.wrapper.append( widget.parts.progressBar, true ); }; - // @todo: this function should be moved to uploadwidget core definition. - definition._getLoader = function( widget ) { - return widget.editor.uploadRepository.loaders[ widget.wrapper.findOne( '[data-cke-upload-id]' ).data( 'cke-upload-id' ) ]; - }; - editor.on( 'widgetDefinition', function( evt ) { var definition = evt.data, baseInit; @@ -286,7 +281,7 @@ baseInit = definition.init; definition.init = function() { - var loader = this.definition._getLoader( this ), + var loader = this._getLoader( this ), progressListeners = []; function removeProgressListeners() { diff --git a/plugins/uploadwidget/plugin.js b/plugins/uploadwidget/plugin.js index af580653674..46e48dd82f3 100644 --- a/plugins/uploadwidget/plugin.js +++ b/plugins/uploadwidget/plugin.js @@ -337,7 +337,15 @@ } else { editor.getSelection().selectBookmarks( bookmarks ); } + }, + /** + * @private + * @returns {CKEDITOR.fileTools.fileLoader/null} Loader associated with this widget instance or `null` if not found. + */ + _getLoader: function() { + var marker = this.wrapper.findOne( '[data-cke-upload-id]' ); + return marker ? this.editor.uploadRepository.loaders[ marker.data( 'cke-upload-id' ) ] : null; } /** From 93205d35fdd2e85ed72e514aed83ae2908b0c919 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 13 Nov 2017 12:54:16 +0100 Subject: [PATCH 228/642] Add unit test for _getLoader. --- tests/plugins/uploadwidget/uploadwidget.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/plugins/uploadwidget/uploadwidget.js b/tests/plugins/uploadwidget/uploadwidget.js index f11b69a1f57..2c7c2b4755a 100644 --- a/tests/plugins/uploadwidget/uploadwidget.js +++ b/tests/plugins/uploadwidget/uploadwidget.js @@ -162,6 +162,21 @@ assert.sameData( '

', element.getOuterHtml() ); }, + 'test _getLoader': function() { + var bot = this.editorBot, + editor = bot.editor, + uploads = editor.uploadRepository, + loader = uploads.create( bender.tools.getTestPngFile() ); + + addTestUploadWidget( editor, 'testGetLoader' ); + + bot.setData( '

xuploading...x

', function() { + var widget = editor.widgets.getByElement( editor.editable().findOne( 'span[data-widget="testGetLoader"]' ) ); + + assert.areSame( loader, widget._getLoader(), '_getLoader return value' ); + } ); + }, + 'test replaceWith 1 element': function() { var bot = this.editorBot, editor = bot.editor, From ea34c118905535e8717aecc24902f68c222ba816 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 28 Sep 2017 20:53:32 +0200 Subject: [PATCH 229/642] Add @ckeditor/ckeditor-cloudservices-core to dev dependencies. --- package.json | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 903112120a1..6199c4002fd 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,28 @@ -{ +{ "name": "ckeditor-dev", "version": "4.9.0", "description": "The development version of CKEditor - JavaScript WYSIWYG web text editor.", "devDependencies": { - "benderjs-coverage": "^0.2.1", + "@ckeditor/ckeditor-cloudservices-core": "^0.1.0", "benderjs": "^0.4.2", + "benderjs-coverage": "^0.2.1", "benderjs-jquery": "^0.3.0", "benderjs-sinon": "^0.3.1", "benderjs-yui": "^0.3.2", - "benderjs-yui-beautified": "0.0.6", + "benderjs-yui-beautified": "0.0.6", + "cksource-samples-framework": "^1.0.1", "grunt": "^1.0.1", + "grunt-contrib-concat": "^1.0.0", "grunt-contrib-imagemin": "^1.0.0", - "grunt-jscs": "^3.0.1", "grunt-contrib-jshint": "^1.0.0", "grunt-contrib-less": "^1.0.0", "grunt-contrib-watch": "^1.0.0", - "grunt-contrib-concat": "^1.0.0", - "grunt-jsduck": "^1.0.1", "grunt-githooks": "^0.6.0", + "grunt-jscs": "^3.0.1", + "grunt-jsduck": "^1.0.1", "less": "^2.5.0", "lesshat": "^4.1.0", - "shelljs": "^0.7.6", - "cksource-samples-framework": "^1.0.1" + "shelljs": "^0.7.6" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" From f32abc991d60f4cdfd6a81fa7d860ed08aef10c5 Mon Sep 17 00:00:00 2001 From: Wojciech Wozniak Date: Thu, 16 Nov 2017 08:20:45 +0100 Subject: [PATCH 230/642] Added error in case missing cludeservice token or URL. --- plugins/cloudservices/plugin.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugins/cloudservices/plugin.js b/plugins/cloudservices/plugin.js index 0eeec9831e8..844b12ac8ff 100644 --- a/plugins/cloudservices/plugin.js +++ b/plugins/cloudservices/plugin.js @@ -55,6 +55,13 @@ CloudServicesLoader.prototype.upload = function( url, additionalRequestParameters ) { url = url || this.editor.config.cloudServices_url; + if ( !url ) { + CKEDITOR.error( 'cloudservices-url-error', { + msg: 'To use cloudservice you should set up CKEDITOR.config.cloudServices_url.' + } ); + return; + } + FileLoader.prototype.upload.call( this, url, additionalRequestParameters ); }; @@ -79,6 +86,12 @@ reqData.file = reqData.upload; delete reqData.upload; + if ( !( fileLoader.customToken || editor.config.cloudServices_token ) ) { + CKEDITOR.error( 'cloudservices-token-error', { + msg: 'To use cloudservice you should set up CKEDITOR.config.cloudServices_token.' + } ); + return; + } // Add authorization token. evt.data.fileLoader.xhr.setRequestHeader( 'Authorization', fileLoader.customToken || editor.config.cloudServices_token ); } From 2ece51ebfd82b81bc56b3be04e132a1d58db602f Mon Sep 17 00:00:00 2001 From: Wojciech Wozniak Date: Fri, 17 Nov 2017 11:21:06 +0100 Subject: [PATCH 231/642] Unit test for URL and TOKEN errors. --- tests/plugins/cloudservices/unit.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/plugins/cloudservices/unit.js b/tests/plugins/cloudservices/unit.js index 68e3cc25503..fa3dfcff2ba 100644 --- a/tests/plugins/cloudservices/unit.js +++ b/tests/plugins/cloudservices/unit.js @@ -81,6 +81,31 @@ bender.test( { listener.removeListener(); } }, + 'test no URL error': function() { + var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64, null, 'different_token' ), + listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); + this.editor.config.cloudServices_url = undefined; + CKEDITOR.once( 'log', function( evt ) { + evt.cancel(); + assert.areEqual( 'cloudservices-url-error', evt.data.errorCode, 'There should be URL error log.' ); + } ); + instance.upload(); + this.editor.config.cloudServices_url = 'cs_url'; + listener.removeListener(); + }, + + 'test no TOKEN error': function() { + var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), + listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); + this.editor.config.cloudServices_token = undefined; + CKEDITOR.once( 'log', function( evt ) { + evt.cancel(); + assert.areEqual( 'cloudservices-token-error', evt.data.errorCode, 'There should be TOKEN error log.' ); + } ); + instance.upload(); + listener.removeListener(); + this.editor.config.cloudServices_token = 'cs_token'; + }, // Common fileUploadRequest listener reused by tests. commonRequestListener: function( evt ) { From f422da493cd4a9f54997b3cb1982eee5a9826261 Mon Sep 17 00:00:00 2001 From: Wojciech Wozniak Date: Mon, 20 Nov 2017 14:37:12 +0100 Subject: [PATCH 232/642] Unit tests fix for IE8-9 and cleaned up error messages. --- plugins/cloudservices/plugin.js | 8 +- tests/plugins/cloudservices/unit.js | 229 +++++++++++++++------------- 2 files changed, 122 insertions(+), 115 deletions(-) diff --git a/plugins/cloudservices/plugin.js b/plugins/cloudservices/plugin.js index 844b12ac8ff..dea968d8c5a 100644 --- a/plugins/cloudservices/plugin.js +++ b/plugins/cloudservices/plugin.js @@ -56,9 +56,7 @@ url = url || this.editor.config.cloudServices_url; if ( !url ) { - CKEDITOR.error( 'cloudservices-url-error', { - msg: 'To use cloudservice you should set up CKEDITOR.config.cloudServices_url.' - } ); + CKEDITOR.error( 'cloudservices-url-error' ); return; } @@ -87,9 +85,7 @@ delete reqData.upload; if ( !( fileLoader.customToken || editor.config.cloudServices_token ) ) { - CKEDITOR.error( 'cloudservices-token-error', { - msg: 'To use cloudservice you should set up CKEDITOR.config.cloudServices_token.' - } ); + CKEDITOR.error( 'cloudservices-token-error' ); return; } // Add authorization token. diff --git a/tests/plugins/cloudservices/unit.js b/tests/plugins/cloudservices/unit.js index fa3dfcff2ba..f85f725ad32 100644 --- a/tests/plugins/cloudservices/unit.js +++ b/tests/plugins/cloudservices/unit.js @@ -1,118 +1,129 @@ /* @bender-ckeditor-plugins: cloudservices */ - -bender.editor = { - config: { - cloudServices_url: 'cs_url', - cloudServices_token: 'cs_token' +( function() { + bender.editor = { + config: { + cloudServices_url: 'cs_url', + cloudServices_token: 'cs_token' + } + }; + function igonreOnIE() { + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) { + assert.ignore(); + } } -}; - -var mockBase64 = 'data:image/gif;base64,R0lGODlhDgAOAIAAAAAAAP///yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs='; - -bender.test( { - setUp: function() { - this.cloudservices = CKEDITOR.plugins.cloudservices; - }, - - 'test plugin exposes loader': function() { - assert.isInstanceOf( Function, this.cloudservices.cloudServicesLoader, 'cloudServicesLoader property type' ); - }, - 'test loader uses config url/token': function() { - var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), - // Stub loader.xhr methods before it's actually called. - listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); - - try { + var mockBase64 = 'data:image/gif;base64,R0lGODlhDgAOAIAAAAAAAP///yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs='; + + bender.test( { + setUp: function() { + this.cloudservices = CKEDITOR.plugins.cloudservices; + this.editor.config.cloudServices_token = 'cs_token'; + this.editor.config.cloudServices_url = 'cs_url'; + }, + + 'test plugin exposes loader': function() { + assert.isInstanceOf( Function, this.cloudservices.cloudServicesLoader, 'cloudServicesLoader property type' ); + }, + + 'test loader uses config url/token': function() { + igonreOnIE(); + var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), + // Stub loader.xhr methods before it's actually called. + listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); + + try { + instance.upload(); + + // Make sure that configured URL has been requested. + sinon.assert.calledWithExactly( instance.xhr.open, 'POST', 'cs_url', true ); + + // Make sure that proper header has been added. + sinon.assert.calledWithExactly( instance.xhr.setRequestHeader, 'Authorization', 'cs_token' ); + + assert.areSame( 1, instance.xhr.send.callCount, 'Call count' ); + } catch ( e ) { + // Propagate. + throw e; + } finally { + // Always remove listener. + listener.removeListener(); + } + }, + + 'test loader allows url overriding': function() { + igonreOnIE(); + var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), + // Stub loader.xhr methods before it's actually called. + listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); + + try { + instance.upload( 'my_custom_url' ); + + sinon.assert.calledWithExactly( instance.xhr.open, 'POST', 'my_custom_url', true ); + + assert.areSame( 1, instance.xhr.send.callCount, 'Call count' ); + } catch ( e ) { + // Propagate. + throw e; + } finally { + // Always remove listener. + listener.removeListener(); + } + }, + + 'test loader allows token overriding': function() { + igonreOnIE(); + var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64, null, 'different_token' ), + // Stub loader.xhr methods before it's actually called. + listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); + + try { + instance.upload(); + + sinon.assert.calledWithExactly( instance.xhr.setRequestHeader, 'Authorization', 'different_token' ); + + assert.areSame( 1, instance.xhr.send.callCount, 'Call count' ); + } catch ( e ) { + // Propagate. + throw e; + } finally { + // Always remove listener. + listener.removeListener(); + } + }, + 'test no URL error': function() {//if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) + igonreOnIE(); + var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64, null, 'different_token' ), + listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); + this.editor.config.cloudServices_url = undefined; + CKEDITOR.once( 'log', function( evt ) { + evt.cancel(); + assert.areEqual( 'cloudservices-url-error', evt.data.errorCode, 'There should be URL error log.' ); + } ); instance.upload(); - - // Make sure that configured URL has been requested. - sinon.assert.calledWithExactly( instance.xhr.open, 'POST', 'cs_url', true ); - - // Make sure that proper header has been added. - sinon.assert.calledWithExactly( instance.xhr.setRequestHeader, 'Authorization', 'cs_token' ); - - assert.areSame( 1, instance.xhr.send.callCount, 'Call count' ); - } catch ( e ) { - // Propagate. - throw e; - } finally { - // Always remove listener. - listener.removeListener(); - } - }, - - 'test loader allows url overriding': function() { - var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), - // Stub loader.xhr methods before it's actually called. - listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); - - try { - instance.upload( 'my_custom_url' ); - - sinon.assert.calledWithExactly( instance.xhr.open, 'POST', 'my_custom_url', true ); - - assert.areSame( 1, instance.xhr.send.callCount, 'Call count' ); - } catch ( e ) { - // Propagate. - throw e; - } finally { - // Always remove listener. listener.removeListener(); - } - }, - - 'test loader allows token overriding': function() { - var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64, null, 'different_token' ), - // Stub loader.xhr methods before it's actually called. - listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); - - try { + }, + + 'test no TOKEN error': function() { + igonreOnIE(); + var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), + listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); + this.editor.config.cloudServices_token = undefined; + CKEDITOR.once( 'log', function( evt ) { + evt.cancel(); + assert.areEqual( 'cloudservices-token-error', evt.data.errorCode, 'There should be TOKEN error log.' ); + } ); instance.upload(); + listener.removeListener(); + }, - sinon.assert.calledWithExactly( instance.xhr.setRequestHeader, 'Authorization', 'different_token' ); + // Common fileUploadRequest listener reused by tests. + commonRequestListener: function( evt ) { + var loader = evt.data.fileLoader; - assert.areSame( 1, instance.xhr.send.callCount, 'Call count' ); - } catch ( e ) { - // Propagate. - throw e; - } finally { - // Always remove listener. - listener.removeListener(); + sinon.stub( loader.xhr, 'open' ); + sinon.stub( loader.xhr, 'send' ); + sinon.stub( loader.xhr, 'setRequestHeader' ); } - }, - 'test no URL error': function() { - var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64, null, 'different_token' ), - listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); - this.editor.config.cloudServices_url = undefined; - CKEDITOR.once( 'log', function( evt ) { - evt.cancel(); - assert.areEqual( 'cloudservices-url-error', evt.data.errorCode, 'There should be URL error log.' ); - } ); - instance.upload(); - this.editor.config.cloudServices_url = 'cs_url'; - listener.removeListener(); - }, - - 'test no TOKEN error': function() { - var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), - listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); - this.editor.config.cloudServices_token = undefined; - CKEDITOR.once( 'log', function( evt ) { - evt.cancel(); - assert.areEqual( 'cloudservices-token-error', evt.data.errorCode, 'There should be TOKEN error log.' ); - } ); - instance.upload(); - listener.removeListener(); - this.editor.config.cloudServices_token = 'cs_token'; - }, - - // Common fileUploadRequest listener reused by tests. - commonRequestListener: function( evt ) { - var loader = evt.data.fileLoader; - - sinon.stub( loader.xhr, 'open' ); - sinon.stub( loader.xhr, 'send' ); - sinon.stub( loader.xhr, 'setRequestHeader' ); - } -} ); \ No newline at end of file + } ); +} )(); \ No newline at end of file From 2831b5d1efa6967adbdab7ceaf0c0fbd014073a6 Mon Sep 17 00:00:00 2001 From: Wojciech Wozniak Date: Mon, 20 Nov 2017 16:33:32 +0100 Subject: [PATCH 233/642] Manual test for cloudservices errors. --- .../plugins/cloudservices/manual/errors.html | 27 +++++++++++++++++++ tests/plugins/cloudservices/manual/errors.md | 12 +++++++++ tests/plugins/cloudservices/unit.js | 2 +- 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/plugins/cloudservices/manual/errors.html create mode 100644 tests/plugins/cloudservices/manual/errors.md diff --git a/tests/plugins/cloudservices/manual/errors.html b/tests/plugins/cloudservices/manual/errors.html new file mode 100644 index 00000000000..91c22e72ec5 --- /dev/null +++ b/tests/plugins/cloudservices/manual/errors.html @@ -0,0 +1,27 @@ + + +
+ Sample text +
+ + \ No newline at end of file diff --git a/tests/plugins/cloudservices/manual/errors.md b/tests/plugins/cloudservices/manual/errors.md new file mode 100644 index 00000000000..c93fb4dd20b --- /dev/null +++ b/tests/plugins/cloudservices/manual/errors.md @@ -0,0 +1,12 @@ +@bender-tags: 4.8.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, toolbar, cloudservices + +1. Open web inspector. +1. Click `Test undefinded URL` button. + +In console we should have information about error with code `cloudservices-url-error`. + +1. Click `Test undefinded TOKEN` button. + +In console we should have information about error with code `cloudservices-token-error`. \ No newline at end of file diff --git a/tests/plugins/cloudservices/unit.js b/tests/plugins/cloudservices/unit.js index f85f725ad32..d070f08b03d 100644 --- a/tests/plugins/cloudservices/unit.js +++ b/tests/plugins/cloudservices/unit.js @@ -91,7 +91,7 @@ listener.removeListener(); } }, - 'test no URL error': function() {//if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) + 'test no URL error': function() { igonreOnIE(); var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64, null, 'different_token' ), listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); From 6ac6cd929d3193fde1a952b0844c9eeb7c595179 Mon Sep 17 00:00:00 2001 From: Wojciech Wozniak Date: Tue, 21 Nov 2017 13:35:50 +0100 Subject: [PATCH 234/642] Review changes to error logs in cloudservice plugin. --- plugins/cloudservices/plugin.js | 5 +++-- .../cloudservices/{unit.js => cloudservices.js} | 17 +++++------------ tests/plugins/cloudservices/manual/errors.html | 4 ++-- tests/plugins/cloudservices/manual/errors.md | 4 ++-- 4 files changed, 12 insertions(+), 18 deletions(-) rename tests/plugins/cloudservices/{unit.js => cloudservices.js} (90%) diff --git a/plugins/cloudservices/plugin.js b/plugins/cloudservices/plugin.js index dea968d8c5a..e60db74aa21 100644 --- a/plugins/cloudservices/plugin.js +++ b/plugins/cloudservices/plugin.js @@ -56,7 +56,7 @@ url = url || this.editor.config.cloudServices_url; if ( !url ) { - CKEDITOR.error( 'cloudservices-url-error' ); + CKEDITOR.error( 'cloudservices-no-url' ); return; } @@ -85,7 +85,8 @@ delete reqData.upload; if ( !( fileLoader.customToken || editor.config.cloudServices_token ) ) { - CKEDITOR.error( 'cloudservices-token-error' ); + CKEDITOR.error( 'cloudservices-no-token' ); + evt.cancel(); return; } // Add authorization token. diff --git a/tests/plugins/cloudservices/unit.js b/tests/plugins/cloudservices/cloudservices.js similarity index 90% rename from tests/plugins/cloudservices/unit.js rename to tests/plugins/cloudservices/cloudservices.js index d070f08b03d..79226f4bf76 100644 --- a/tests/plugins/cloudservices/unit.js +++ b/tests/plugins/cloudservices/cloudservices.js @@ -6,11 +6,6 @@ cloudServices_token: 'cs_token' } }; - function igonreOnIE() { - if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) { - assert.ignore(); - } - } var mockBase64 = 'data:image/gif;base64,R0lGODlhDgAOAIAAAAAAAP///yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs='; @@ -19,6 +14,9 @@ this.cloudservices = CKEDITOR.plugins.cloudservices; this.editor.config.cloudServices_token = 'cs_token'; this.editor.config.cloudServices_url = 'cs_url'; + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) { + assert.ignore(); + } }, 'test plugin exposes loader': function() { @@ -26,7 +24,6 @@ }, 'test loader uses config url/token': function() { - igonreOnIE(); var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), // Stub loader.xhr methods before it's actually called. listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); @@ -51,7 +48,6 @@ }, 'test loader allows url overriding': function() { - igonreOnIE(); var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), // Stub loader.xhr methods before it's actually called. listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); @@ -72,7 +68,6 @@ }, 'test loader allows token overriding': function() { - igonreOnIE(); var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64, null, 'different_token' ), // Stub loader.xhr methods before it's actually called. listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); @@ -92,26 +87,24 @@ } }, 'test no URL error': function() { - igonreOnIE(); var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64, null, 'different_token' ), listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); this.editor.config.cloudServices_url = undefined; CKEDITOR.once( 'log', function( evt ) { evt.cancel(); - assert.areEqual( 'cloudservices-url-error', evt.data.errorCode, 'There should be URL error log.' ); + assert.areEqual( 'cloudservices-no-url', evt.data.errorCode, 'There should be URL error log.' ); } ); instance.upload(); listener.removeListener(); }, 'test no TOKEN error': function() { - igonreOnIE(); var instance = new this.cloudservices.cloudServicesLoader( this.editor, mockBase64 ), listener = this.editor.once( 'fileUploadRequest', this.commonRequestListener, null, null, 0 ); this.editor.config.cloudServices_token = undefined; CKEDITOR.once( 'log', function( evt ) { evt.cancel(); - assert.areEqual( 'cloudservices-token-error', evt.data.errorCode, 'There should be TOKEN error log.' ); + assert.areEqual( 'cloudservices-no-token', evt.data.errorCode, 'There should be TOKEN error log.' ); } ); instance.upload(); listener.removeListener(); diff --git a/tests/plugins/cloudservices/manual/errors.html b/tests/plugins/cloudservices/manual/errors.html index 91c22e72ec5..f9ad9e15936 100644 --- a/tests/plugins/cloudservices/manual/errors.html +++ b/tests/plugins/cloudservices/manual/errors.html @@ -11,14 +11,14 @@ cloudServices_token: 'cs_token', height: 500 } ); - document.getElementById('url').addEventListener('click', function( event ) { + document.getElementById( 'url' ).addEventListener( 'click', function( event ) { var instance = new CKEDITOR.plugins.cloudservices.cloudServicesLoader( CKEDITOR.instances.classic, mockBase64 ); CKEDITOR.instances.classic.config.cloudServices_url = undefined; CKEDITOR.instances.classic.config.cloudServices_token = 'cs_token'; instance.upload(); } ); - document.getElementById('token').addEventListener('click', function( event ) { + document.getElementById( 'token' ).addEventListener( 'click', function( event ) { var instance = new CKEDITOR.plugins.cloudservices.cloudServicesLoader( CKEDITOR.instances.classic, mockBase64 ); CKEDITOR.instances.classic.config.cloudServices_url = 'cs_url'; CKEDITOR.instances.classic.config.cloudServices_token = undefined; diff --git a/tests/plugins/cloudservices/manual/errors.md b/tests/plugins/cloudservices/manual/errors.md index c93fb4dd20b..f5d8de4f9ad 100644 --- a/tests/plugins/cloudservices/manual/errors.md +++ b/tests/plugins/cloudservices/manual/errors.md @@ -5,8 +5,8 @@ 1. Open web inspector. 1. Click `Test undefinded URL` button. -In console we should have information about error with code `cloudservices-url-error`. +In console we should have information about error with code `cloudservices-no-url`. 1. Click `Test undefinded TOKEN` button. -In console we should have information about error with code `cloudservices-token-error`. \ No newline at end of file +In console we should have information about error with code `cloudservices-no-token`. \ No newline at end of file From d06480f3d5acc6f349451ce687aaf117092cfdb2 Mon Sep 17 00:00:00 2001 From: Wojciech Wozniak Date: Tue, 21 Nov 2017 15:45:32 +0100 Subject: [PATCH 235/642] Minor tests fixes. --- tests/plugins/cloudservices/cloudservices.js | 6 +++--- tests/plugins/cloudservices/manual/errors.html | 3 +++ tests/plugins/cloudservices/manual/errors.md | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/plugins/cloudservices/cloudservices.js b/tests/plugins/cloudservices/cloudservices.js index 79226f4bf76..62aea83b651 100644 --- a/tests/plugins/cloudservices/cloudservices.js +++ b/tests/plugins/cloudservices/cloudservices.js @@ -11,12 +11,12 @@ bender.test( { setUp: function() { + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) { + assert.ignore(); + } this.cloudservices = CKEDITOR.plugins.cloudservices; this.editor.config.cloudServices_token = 'cs_token'; this.editor.config.cloudServices_url = 'cs_url'; - if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) { - assert.ignore(); - } }, 'test plugin exposes loader': function() { diff --git a/tests/plugins/cloudservices/manual/errors.html b/tests/plugins/cloudservices/manual/errors.html index f9ad9e15936..a36fa6e6a4e 100644 --- a/tests/plugins/cloudservices/manual/errors.html +++ b/tests/plugins/cloudservices/manual/errors.html @@ -5,6 +5,9 @@ diff --git a/tests/plugins/easyimage/manual/linkcontextmenu.md b/tests/plugins/easyimage/manual/linkcontextmenu.md new file mode 100644 index 00000000000..939c5a4d5ce --- /dev/null +++ b/tests/plugins/easyimage/manual/linkcontextmenu.md @@ -0,0 +1,11 @@ +@bender-tags: 4.8.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, link + + +1. Right click to to add link. +1. Click "Source" button to check output. + +## Expected + +* There is created link. From 7855339e2c07c59e36dba710dbb546d7dac6d722 Mon Sep 17 00:00:00 2001 From: Wojciech Wozniak Date: Tue, 14 Nov 2017 17:59:29 +0100 Subject: [PATCH 238/642] unit test for link option in context menu --- tests/plugins/easyimage/linkcommand.js | 53 ++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/plugins/easyimage/linkcommand.js diff --git a/tests/plugins/easyimage/linkcommand.js b/tests/plugins/easyimage/linkcommand.js new file mode 100644 index 00000000000..19fe3226c0e --- /dev/null +++ b/tests/plugins/easyimage/linkcommand.js @@ -0,0 +1,53 @@ +/* bender-tags: editor,widget */ +/* bender-ckeditor-plugins: easyimage,toolbar, link */ + +( function() { + 'use strict'; + + bender.editors = { + classic: {}, + + divarea: { + config: { + extraPlugins: 'divarea' + } + }, + + inline: { + creator: 'inline' + } + }; + + + + var widgetHtml = '
foo
Test image
', + tests = { + tearDown: function() { + var currentDialog = CKEDITOR.dialog.getCurrent(); + + if ( currentDialog ) { + currentDialog.hide(); + } + }, + + 'test link option in context menu': function( editor, bot ) { + bot.setData( widgetHtml, function() { + var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ); + + widget.focus(); + editor.contextMenu.open( editor.editable() ); + var itemsExist = 0; + for ( var i = 0; i < editor.contextMenu.items.length; ++i ) + if ( editor.contextMenu.items[ i ].command == 'link' ) + itemsExist += 1; + + editor.contextMenu.hide(); + + assert.areSame( 1, itemsExist, 'there is one link item in context menu' ); + } ); + } + }; + + tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); + bender.test( tests ); +} )(); From f1a3ebe7256ae9bc45ede60a3ccc086730fd7434 Mon Sep 17 00:00:00 2001 From: Wojciech Wozniak Date: Thu, 16 Nov 2017 17:45:05 +0100 Subject: [PATCH 239/642] Link in contextmenu support for inline widget. --- plugins/easyimage/plugin.js | 19 ++++-------- plugins/imagebase/plugin.js | 24 +++++++++++++++ .../easyimage/manual/linkcontextmenu.html | 16 ---------- .../features}/linkcommand.js | 12 ++++++-- .../features/manual/linkcontextmenu.html | 29 +++++++++++++++++++ .../features}/manual/linkcontextmenu.md | 10 ++++++- 6 files changed, 76 insertions(+), 34 deletions(-) delete mode 100644 tests/plugins/easyimage/manual/linkcontextmenu.html rename tests/plugins/{easyimage => imagebase/features}/linkcommand.js (69%) create mode 100644 tests/plugins/imagebase/features/manual/linkcontextmenu.html rename tests/plugins/{easyimage => imagebase/features}/manual/linkcontextmenu.md (54%) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 53883111139..ae51346ebdf 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -73,7 +73,7 @@ function addMenuItems( editor ) { editor.addMenuGroup( 'easyimage' ); - var itemsData = { + editor.addMenuItems( { easyimageFull: { label: editor.lang.easyimage.commands.fullImage, command: 'easyimageFull', @@ -94,16 +94,7 @@ group: 'easyimage', order: 3 } - }; - if ( editor.plugins.link ) { - itemsData.link = { - label: editor.lang.link.toolbar, - command: 'link', - group: 'easyimage', - order: 4 - }; - } - editor.addMenuItems( itemsData ); + } ); } function getInitialImageType( widget ) { @@ -144,9 +135,9 @@ evt.data.easyimageFull = editor.getCommand( 'easyimageFull' ).state; evt.data.easyimageSide = editor.getCommand( 'easyimageSide' ).state; evt.data.easyimageAlt = editor.getCommand( 'easyimageAlt' ).state; - if ( editor.plugins.link ) { - evt.data.link = editor.getCommand( 'link' ).state; - } + // if ( editor.plugins.link ) { + // evt.data.link = editor.getCommand( 'link' ).state; + // } } ); if ( editor.config.easyimage_class ) { diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index c080875229d..4ce10c3f33d 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -54,12 +54,36 @@ parts: { link: 'a' }, + init: function() { + if ( this.editor.plugins.link ) { + this.on( 'contextMenu', function( evt ) { + evt.data.link = this.editor.getCommand( 'link' ).state; + evt.data.unlink = this.editor.getCommand( 'unlink' ).state; + } ); + } + }, setUp: function( editor ) { if ( !editor.plugins.link ) { // All of listeners registered later on make only sense when link plugin is loaded. return; } + if ( editor.addMenuItems ) { + editor.addMenuItems( { + link: { + label: editor.lang.link.menu, + command: 'link', + group: 'imagebase', + order: 1 + }, + unlink: { + label: editor.lang.link.unlink, + command: 'unlink', + group: 'imagebase', + order: 2 + } + } ); + } editor.on( 'dialogShow', function( evt ) { var widget = getFocusedWidget( editor ), diff --git a/tests/plugins/easyimage/manual/linkcontextmenu.html b/tests/plugins/easyimage/manual/linkcontextmenu.html deleted file mode 100644 index 9ec4e5d2d26..00000000000 --- a/tests/plugins/easyimage/manual/linkcontextmenu.html +++ /dev/null @@ -1,16 +0,0 @@ - -
-

Context menu should have option link:

-
- foo -
Test image
-
-
- - diff --git a/tests/plugins/easyimage/linkcommand.js b/tests/plugins/imagebase/features/linkcommand.js similarity index 69% rename from tests/plugins/easyimage/linkcommand.js rename to tests/plugins/imagebase/features/linkcommand.js index 19fe3226c0e..83aa4c8733c 100644 --- a/tests/plugins/easyimage/linkcommand.js +++ b/tests/plugins/imagebase/features/linkcommand.js @@ -1,5 +1,5 @@ /* bender-tags: editor,widget */ -/* bender-ckeditor-plugins: easyimage,toolbar, link */ +/* bender-ckeditor-plugins: imagebase,toolbar, link,contextmenu */ ( function() { 'use strict'; @@ -19,8 +19,7 @@ }; - - var widgetHtml = '
foo
Test image
', + var widgetHtml = '
', tests = { tearDown: function() { var currentDialog = CKEDITOR.dialog.getCurrent(); @@ -29,6 +28,13 @@ currentDialog.hide(); } }, + setUp: function() { + var plugin = CKEDITOR.plugins.imagebase, + editors = this.editors; + CKEDITOR.tools.array.forEach( CKEDITOR.tools.objectKeys( editors ), function( editor ) { + plugin.addImageWidget( editors[ editor ], 'testWidget', plugin.addFeature( editors[ editor ], 'link', {} ) ); + } ); + }, 'test link option in context menu': function( editor, bot ) { bot.setData( widgetHtml, function() { diff --git a/tests/plugins/imagebase/features/manual/linkcontextmenu.html b/tests/plugins/imagebase/features/manual/linkcontextmenu.html new file mode 100644 index 00000000000..bb66ee43500 --- /dev/null +++ b/tests/plugins/imagebase/features/manual/linkcontextmenu.html @@ -0,0 +1,29 @@ + +
+

Widget with no link:

+
+ foo +
Test image
+
+

Widget with predefined link:

+
+ + foo + +
Test image
+
+
+ + diff --git a/tests/plugins/easyimage/manual/linkcontextmenu.md b/tests/plugins/imagebase/features/manual/linkcontextmenu.md similarity index 54% rename from tests/plugins/easyimage/manual/linkcontextmenu.md rename to tests/plugins/imagebase/features/manual/linkcontextmenu.md index 939c5a4d5ce..8f7f51183fa 100644 --- a/tests/plugins/easyimage/manual/linkcontextmenu.md +++ b/tests/plugins/imagebase/features/manual/linkcontextmenu.md @@ -1,6 +1,6 @@ @bender-tags: 4.8.0, feature, 932 @bender-ui: collapsed -@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, link +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, imagebase, link, htmlwriter, elementspath, contextmenu 1. Right click to to add link. @@ -9,3 +9,11 @@ ## Expected * There is created link. + + +1. Try to remove link with context menu. +1. Click "Source" button to check output. + +## Expected + +* The link should be reomved. From 24a705113fbf9e5347cd3c75dcb77ab42173ba5c Mon Sep 17 00:00:00 2001 From: Wojciech Wozniak Date: Mon, 20 Nov 2017 13:08:38 +0100 Subject: [PATCH 240/642] Unit test updates and UX fix in link command for base image. --- plugins/easyimage/plugin.js | 3 - plugins/imagebase/plugin.js | 28 ++++----- tests/plugins/imagebase/features/link.js | 59 ++++++++++++++++++- .../plugins/imagebase/features/linkcommand.js | 59 ------------------- 4 files changed, 69 insertions(+), 80 deletions(-) delete mode 100644 tests/plugins/imagebase/features/linkcommand.js diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index ae51346ebdf..4dbd51c6c25 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -135,9 +135,6 @@ evt.data.easyimageFull = editor.getCommand( 'easyimageFull' ).state; evt.data.easyimageSide = editor.getCommand( 'easyimageSide' ).state; evt.data.easyimageAlt = editor.getCommand( 'easyimageAlt' ).state; - // if ( editor.plugins.link ) { - // evt.data.link = editor.getCommand( 'link' ).state; - // } } ); if ( editor.config.easyimage_class ) { diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 4ce10c3f33d..11529c5a979 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -55,10 +55,11 @@ link: 'a' }, init: function() { - if ( this.editor.plugins.link ) { + if ( this.editor.plugins.link && this.editor.contextMenu ) { this.on( 'contextMenu', function( evt ) { - evt.data.link = this.editor.getCommand( 'link' ).state; - evt.data.unlink = this.editor.getCommand( 'unlink' ).state; + if ( this.parts.link || this.wrapper.getAscendant( 'a' ) ) { + evt.data.link = evt.data.unlink = CKEDITOR.TRISTATE_OFF; + } } ); } }, @@ -68,20 +69,13 @@ // All of listeners registered later on make only sense when link plugin is loaded. return; } - if ( editor.addMenuItems ) { - editor.addMenuItems( { - link: { - label: editor.lang.link.menu, - command: 'link', - group: 'imagebase', - order: 1 - }, - unlink: { - label: editor.lang.link.unlink, - command: 'unlink', - group: 'imagebase', - order: 2 - } + if ( editor.contextMenu ) { + editor.addMenuGroup( 'imagebase', 10 ); + + editor.addMenuItem( 'imagebase', { + label: editor.lang.link.menu, + command: 'link', + group: 'imagebase' } ); } diff --git a/tests/plugins/imagebase/features/link.js b/tests/plugins/imagebase/features/link.js index 32d4817f277..9ede25f986b 100644 --- a/tests/plugins/imagebase/features/link.js +++ b/tests/plugins/imagebase/features/link.js @@ -1,5 +1,5 @@ /* bender-tags: editor,widget */ -/* bender-ckeditor-plugins: imagebase,link,toolbar */ +/* bender-ckeditor-plugins: imagebase,link,toolbar,contextmenu */ /* bender-include: ../../widget/_helpers/tools.js */ /* global widgetTestsTools */ @@ -389,6 +389,63 @@ } ); } } ); + }, + 'test link option in context menu': function( editor, bot ) { + addTestWidget( editor ); + bot.setData( '
', function() { + var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ); + + widget.focus(); + editor.contextMenu.open( editor.editable() ); + var itemsExist = 0; + for ( var i = 0; i < editor.contextMenu.items.length; ++i ) { + if ( editor.contextMenu.items[ i ].command == 'link' ) { + itemsExist += 1; + } + } + + editor.contextMenu.hide(); + + assert.areSame( 1, itemsExist, 'there is one link item in context menu' ); + } ); + }, + 'test unlink option in context menu': function( editor, bot ) { + addTestWidget( editor ); + bot.setData( '
', function() { + var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ); + + widget.focus(); + editor.contextMenu.open( editor.editable() ); + var itemsExist = 0; + for ( var i = 0; i < editor.contextMenu.items.length; ++i ) { + if ( editor.contextMenu.items[ i ].command == 'unlink' ) { + itemsExist += 1; + } + } + + editor.contextMenu.hide(); + + assert.areSame( 1, itemsExist, 'there is one link item in context menu' ); + } ); + }, + 'test no link option in context menu': function( editor, bot ) { + addTestWidget( editor ); + bot.setData( '
', function() { + var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ); + + widget.focus(); + editor.contextMenu.open( editor.editable() ); + var itemsExist = 0; + for ( var i = 0; i < editor.contextMenu.items.length; ++i ) { + if ( editor.contextMenu.items[ i ].command == 'unlink' || editor.contextMenu.items[ i ].command == 'link' ) { + itemsExist += 1; + } + } + + editor.contextMenu.hide(); + + assert.areSame( 0, itemsExist, 'there should not be any link option in contextmenu' ); + } ); } }; diff --git a/tests/plugins/imagebase/features/linkcommand.js b/tests/plugins/imagebase/features/linkcommand.js deleted file mode 100644 index 83aa4c8733c..00000000000 --- a/tests/plugins/imagebase/features/linkcommand.js +++ /dev/null @@ -1,59 +0,0 @@ -/* bender-tags: editor,widget */ -/* bender-ckeditor-plugins: imagebase,toolbar, link,contextmenu */ - -( function() { - 'use strict'; - - bender.editors = { - classic: {}, - - divarea: { - config: { - extraPlugins: 'divarea' - } - }, - - inline: { - creator: 'inline' - } - }; - - - var widgetHtml = '
', - tests = { - tearDown: function() { - var currentDialog = CKEDITOR.dialog.getCurrent(); - - if ( currentDialog ) { - currentDialog.hide(); - } - }, - setUp: function() { - var plugin = CKEDITOR.plugins.imagebase, - editors = this.editors; - CKEDITOR.tools.array.forEach( CKEDITOR.tools.objectKeys( editors ), function( editor ) { - plugin.addImageWidget( editors[ editor ], 'testWidget', plugin.addFeature( editors[ editor ], 'link', {} ) ); - } ); - }, - - 'test link option in context menu': function( editor, bot ) { - bot.setData( widgetHtml, function() { - var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ); - - widget.focus(); - editor.contextMenu.open( editor.editable() ); - var itemsExist = 0; - for ( var i = 0; i < editor.contextMenu.items.length; ++i ) - if ( editor.contextMenu.items[ i ].command == 'link' ) - itemsExist += 1; - - editor.contextMenu.hide(); - - assert.areSame( 1, itemsExist, 'there is one link item in context menu' ); - } ); - } - }; - - tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); - bender.test( tests ); -} )(); From 711223cc1e7e3954ee02e6570be8706d487c3a81 Mon Sep 17 00:00:00 2001 From: Wojciech Wozniak Date: Thu, 14 Dec 2017 14:42:42 +0100 Subject: [PATCH 241/642] Unit test clean up. --- tests/plugins/imagebase/features/link.js | 78 ++++++++++-------------- 1 file changed, 31 insertions(+), 47 deletions(-) diff --git a/tests/plugins/imagebase/features/link.js b/tests/plugins/imagebase/features/link.js index 9ede25f986b..d156c3d87e2 100644 --- a/tests/plugins/imagebase/features/link.js +++ b/tests/plugins/imagebase/features/link.js @@ -146,6 +146,26 @@ } ); } + function testLinkOptionInContextMenu( editor, bot, data, testCase, cb ) { + addTestWidget( editor ); + bot.setData( data, function() { + var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ); + + widget.focus(); + editor.contextMenu.open( editor.editable() ); + var itemsExist = 0; + for ( var i = 0; i < editor.contextMenu.items.length; ++i ) { + if ( testCase( editor, i ) ) { + itemsExist += 1; + } + } + + editor.contextMenu.hide(); + + cb( itemsExist ); + } ); + } + var tests = { 'test adding image widget with link feature': function( editor ) { var expectedParts = { @@ -391,60 +411,24 @@ } ); }, 'test link option in context menu': function( editor, bot ) { - addTestWidget( editor ); - bot.setData( '
', function() { - var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ); - - widget.focus(); - editor.contextMenu.open( editor.editable() ); - var itemsExist = 0; - for ( var i = 0; i < editor.contextMenu.items.length; ++i ) { - if ( editor.contextMenu.items[ i ].command == 'link' ) { - itemsExist += 1; - } - } - - editor.contextMenu.hide(); - + testLinkOptionInContextMenu( editor, bot, '
', function( editor, index ) { + return editor.contextMenu.items[ index ].command == 'link'; + }, function( itemsExist ) { assert.areSame( 1, itemsExist, 'there is one link item in context menu' ); } ); }, 'test unlink option in context menu': function( editor, bot ) { - addTestWidget( editor ); - bot.setData( '
', function() { - var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ); - - widget.focus(); - editor.contextMenu.open( editor.editable() ); - var itemsExist = 0; - for ( var i = 0; i < editor.contextMenu.items.length; ++i ) { - if ( editor.contextMenu.items[ i ].command == 'unlink' ) { - itemsExist += 1; - } - } - - editor.contextMenu.hide(); - - assert.areSame( 1, itemsExist, 'there is one link item in context menu' ); + testLinkOptionInContextMenu( editor, bot, '
', function( editor, index ) { + return editor.contextMenu.items[ index ].command == 'unlink'; + }, function( itemsExist ) { + assert.areSame( 1, itemsExist, 'there is one unlink item in context menu' ); } ); }, 'test no link option in context menu': function( editor, bot ) { - addTestWidget( editor ); - bot.setData( '
', function() { - var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ); - - widget.focus(); - editor.contextMenu.open( editor.editable() ); - var itemsExist = 0; - for ( var i = 0; i < editor.contextMenu.items.length; ++i ) { - if ( editor.contextMenu.items[ i ].command == 'unlink' || editor.contextMenu.items[ i ].command == 'link' ) { - itemsExist += 1; - } - } - - editor.contextMenu.hide(); - - assert.areSame( 0, itemsExist, 'there should not be any link option in contextmenu' ); + testLinkOptionInContextMenu( editor, bot, '
', function( editor, index ) { + return editor.contextMenu.items[ index ].command == 'unlink' || editor.contextMenu.items[ index ].command == 'link'; + }, function( itemsExist ) { + assert.areSame( 0, itemsExist, 'there is one link item in context menu' ); } ); } }; From c68cec0f407852ee1607084b8bce5e2f7ad41209 Mon Sep 17 00:00:00 2001 From: Wojciech Wozniak Date: Thu, 14 Dec 2017 14:47:24 +0100 Subject: [PATCH 242/642] Manual test clean up. --- tests/plugins/imagebase/features/manual/linkcontextmenu.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/plugins/imagebase/features/manual/linkcontextmenu.md b/tests/plugins/imagebase/features/manual/linkcontextmenu.md index 8f7f51183fa..d157b19f5bb 100644 --- a/tests/plugins/imagebase/features/manual/linkcontextmenu.md +++ b/tests/plugins/imagebase/features/manual/linkcontextmenu.md @@ -1,9 +1,10 @@ -@bender-tags: 4.8.0, feature, 932 +@bender-tags: 4.8.1, feature, 932 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, imagebase, link, htmlwriter, elementspath, contextmenu -1. Right click to to add link. +1. Focus widget. +1. Add link using `link` option in top bar menu. 1. Click "Source" button to check output. ## Expected From 69a9bc7e4f487e92d1323753ddc3c9b15c21a90f Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 18 Dec 2017 13:57:15 +0100 Subject: [PATCH 243/642] Update manual test. --- .../features/manual/linkcontextmenu.md | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/plugins/imagebase/features/manual/linkcontextmenu.md b/tests/plugins/imagebase/features/manual/linkcontextmenu.md index d157b19f5bb..3838089382c 100644 --- a/tests/plugins/imagebase/features/manual/linkcontextmenu.md +++ b/tests/plugins/imagebase/features/manual/linkcontextmenu.md @@ -1,20 +1,31 @@ -@bender-tags: 4.8.1, feature, 932 +@bender-tags: 4.9.0, feature, 932 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, imagebase, link, htmlwriter, elementspath, contextmenu +## Scenario 1 -1. Focus widget. -1. Add link using `link` option in top bar menu. -1. Click "Source" button to check output. +1. Right-click the first image to show the context menu. -## Expected +### Expected -* There is created link. +* There are no link connected options in the menu. +## Scenario 2 -1. Try to remove link with context menu. -1. Click "Source" button to check output. +1. Add link to the first image in the editor. +2. Right click on it to show the context menu. +3. Click "Edit Link" and change URL of the link. -## Expected +### Excepted -* The link should be reomved. +* There are link connected options in the menu. +* Editing link's URL actually changes link's URL. + +## Scenario 3 + +1. Right-click the second image in the editor to show the context menu. +2. Choose "Unlink". + +### Expected + +* Link is removed. From aaeab74899b26d6b01a184029279e84c42188816 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 18 Dec 2017 14:31:40 +0100 Subject: [PATCH 244/642] Simplify condition. --- plugins/imagebase/plugin.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 11529c5a979..f8d31440019 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -57,7 +57,7 @@ init: function() { if ( this.editor.plugins.link && this.editor.contextMenu ) { this.on( 'contextMenu', function( evt ) { - if ( this.parts.link || this.wrapper.getAscendant( 'a' ) ) { + if ( this.parts.link ) { evt.data.link = evt.data.unlink = CKEDITOR.TRISTATE_OFF; } } ); @@ -69,6 +69,7 @@ // All of listeners registered later on make only sense when link plugin is loaded. return; } + if ( editor.contextMenu ) { editor.addMenuGroup( 'imagebase', 10 ); From 8f6d389e455b91fa436df46ee2efb683c590fcb1 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 12 Dec 2017 11:06:59 +0100 Subject: [PATCH 245/642] Add new icons. --- plugins/easyimage/icons/easyimagealt.png | Bin 0 -> 545 bytes plugins/easyimage/icons/easyimagefull.png | Bin 0 -> 147 bytes plugins/easyimage/icons/easyimageside.png | Bin 0 -> 152 bytes plugins/easyimage/icons/hidpi/easyimagealt.png | Bin 0 -> 1290 bytes plugins/easyimage/icons/hidpi/easyimagefull.png | Bin 0 -> 253 bytes plugins/easyimage/icons/hidpi/easyimageside.png | Bin 0 -> 315 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 plugins/easyimage/icons/easyimagealt.png create mode 100644 plugins/easyimage/icons/easyimagefull.png create mode 100644 plugins/easyimage/icons/easyimageside.png create mode 100644 plugins/easyimage/icons/hidpi/easyimagealt.png create mode 100644 plugins/easyimage/icons/hidpi/easyimagefull.png create mode 100644 plugins/easyimage/icons/hidpi/easyimageside.png diff --git a/plugins/easyimage/icons/easyimagealt.png b/plugins/easyimage/icons/easyimagealt.png new file mode 100644 index 0000000000000000000000000000000000000000..3b99772534110591b034e32aca39de55a06f0ef8 GIT binary patch literal 545 zcmV++0^a?JP)}VrN@7-};23U-YEv{cM1%P5@!S{h;X7n-k4Uc7YU_ttuG6T1?rHv~8V zq&pbsbM)LOqsw6l8Zz#rdYR!0A*?LAxmVKT7htIO3b~Vkz=)*QC?H%_z>gT!F(BSp zdX_C2?ubv&gN*T~Le;vf{Z&MG=gs9i!nzbBj5R*{Z?aXUGD zqV9B~IgWa0iF0}AhY&$F&Eiwr_%6TAC|8e-?pR;s0MFQtneQaG)5 j*;NER=0ES({{MUr@JFjv9vG9x00000NkvXXu0mjf>fHcx literal 0 HcmV?d00001 diff --git a/plugins/easyimage/icons/easyimagefull.png b/plugins/easyimage/icons/easyimagefull.png new file mode 100644 index 0000000000000000000000000000000000000000..37bc79d4b5b6332a1d1d9beca4cdb96ade173603 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!6#=yXs@#Xw?AcrO0(btiIVPik{pF~z5-^p8Xv4$DbBTI v2ScPT_om>9suPZW+_>^NYt6O`A$$yM2?8EXQ#MHhO=a+O^>bP0l+XkKr$8>B literal 0 HcmV?d00001 diff --git a/plugins/easyimage/icons/easyimageside.png b/plugins/easyimage/icons/easyimageside.png new file mode 100644 index 0000000000000000000000000000000000000000..7a520becc42c13719624974c2aba398df93cc4cc GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!6#=yXs@#Xw?AcrO0(btiIVPik{pF~z5-`~^4 zF~mYJIbnhDhfa_G{D(xM*o~Rof-~-{D7)3dpnN7G=yB%hu9*pYeGHg4Tr_aK@gyNh z$AGQF?V7`y?f@QzFyT#0EA~3{HJ)g@+|J987$oLkcGasBXf%VTtDnm{r-UW|+RrhF literal 0 HcmV?d00001 diff --git a/plugins/easyimage/icons/hidpi/easyimagealt.png b/plugins/easyimage/icons/hidpi/easyimagealt.png new file mode 100644 index 0000000000000000000000000000000000000000..a39c3dd465286f92ad892a65e269ff0a154a6992 GIT binary patch literal 1290 zcmV+l1@-!gP)C}K}&6-hNehONkAwmRMgT$KWHI$rY(Ww zC?WllyQD^~=m$Ydss%y(BAVoK6{$jdLBVJ)v`Sl(evv>$1gmXRwO5I;QA@Nb$=%-W zjPGr3)=hG!;b=iH1G)M0e((3*zIpRz!dSMpJGg&CLv!dl$$)Mefl~nZiCvARpH^ z0zj`vcH4)_A$0T$jN6eV1{+$!;|fGV8v9%J*U*@w*1_RepTIR)^y-N z5e<<3X96K(!V%>9@iOJY+`4s5Q8l)OE32!wm0tMf+@ES~IlYrK3P}5C3M+woS!qi9 zEDB4cWS1C|4-p3U_fk9-*{tx+nwsE;3q)K2CRZ7tZzCcOyiG81csSNy(HQKgwS@Rm z;Q{#5@mSwmZZ>HQ_KK zDFcw8*vGYp)u(-QyyvPHyE49&5ol-*kL1JWW}?42e1!<&1CfnX)&jwfDE7NCxxPox zi?prT47da&BofJ_t{1{~D=Co>Mj6NlF&7F+&OzHb6zlzz#;UmlR3fMf0E1tV#2g;z zuTUULEcE6~WSW8cxc{45H}31+DeNP1dt#xn|XWuSl>x+k-$SG@ROXA z?3@K5B<8jDz#7i)OsDPd80b443wREs5Yc&Skect27!9G(muc=0pi6j;?6Elw$^c5% zNtwO?Iy`}&lK=_UyrL{n1Prvm(DBHtG2z9789u$rGVRYif&CHI zl$XS#-Lr(Jwt#>Z&^-u*4iy=*f0UZm+$7hvO~MkV5h!Vk36oc&EzURD@-n!h^goKg zl03%4Fp9angHDmbwYuAVi!5<~f=~BgTG*p_0xOjxTH}t1fyDY}C{_hE1E%?0b3$r1+|S~~r}>|^+)s|kap^DzUo9~MU> z*VY7rp*|s4c(E~zyWl{}5btrnjtQ@XCz zgAKFF5iIr=-Zr{J25f@fKQ!*@>MBV5Zq6W=;WgwPa}EbpHFn=d_$GP(W>ILSYNNvJ%KOrF}f@0^@hfse<{cjboeD@;Oewhnaem`L}=gJ|27fV$;5^b;+bTf@?L-!_Cm^Fa{|V5tXczBUXxyV&pcs zoB)@BX}jXFo^Rc?%pj`+UeJ?!JGKj3yr3KU^MmjAj5oD)mL*eyj%pQt(WDP#on*R+ z(K(AZ4jFZmRixymp;-SZFW=(vzdEp3LCu?5!}lajhDViE0LYQG1?9VLn7^%G9Fbhf zs(A8tKoMl?=U@8vQN57u`}k-ikqxu5_MeHsU$Cwpuj=c9kpKVy07*qoM6N<$g0?zs A*#H0l literal 0 HcmV?d00001 diff --git a/plugins/easyimage/icons/hidpi/easyimagefull.png b/plugins/easyimage/icons/hidpi/easyimagefull.png new file mode 100644 index 0000000000000000000000000000000000000000..2de074a6cc46c26dbebea585b02b638e950cb4c7 GIT binary patch literal 253 zcmV2i_n~B`W#<8jpRu&+=5rVSsxlq>2Vy*XFzsG%wwzD`2if z9X`RzV~|sYxYt~XW&m?DCFrbg;blSh)2&^BKNWcDSe#&^%Nlc(7nzA^!g5#Ob(vu( zY^h?YHDAX_x@7K7Aew@hWF=8Hea5{DnpUTitD?XK^?EdlH0rgX00000NkvXXu0mjf D~dj)|N0kUey-EbqZZ15_o2)s?@(B=_F z2ut$3cRCQ>MCTk1Ybub Date: Tue, 12 Dec 2017 11:25:46 +0100 Subject: [PATCH 246/642] Add icons configuration to plugin. --- plugins/easyimage/plugin.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 4dbd51c6c25..79d1a519a7c 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -366,6 +366,8 @@ CKEDITOR.plugins.add( 'easyimage', { requires: 'imagebase,uploadwidget,contextmenu,dialog,cloudservices', lang: 'en', + icons: 'easyimagefull,easyimageside,easyimagealt', // %REMOVE_LINE_CORE% + hidpi: true, // %REMOVE_LINE_CORE% onLoad: function() { CKEDITOR.dialog.add( 'easyimageAlt', this.path + 'dialogs/easyimagealt.js' ); From c8d21db7861075dbe9caa08108e560804f5e76b0 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 12 Dec 2017 11:30:02 +0100 Subject: [PATCH 247/642] Update side icon. --- plugins/easyimage/icons/easyimageside.png | Bin 152 -> 149 bytes plugins/easyimage/icons/hidpi/easyimageside.png | Bin 315 -> 299 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/plugins/easyimage/icons/easyimageside.png b/plugins/easyimage/icons/easyimageside.png index 7a520becc42c13719624974c2aba398df93cc4cc..d096f33967f954bc02c65c48de53d79791d21799 100644 GIT binary patch delta 104 zcmV-u0GI!m0hIxeG+|6hL_t(I5o2H&1p^xbJ`w5vK`wyNOatp2>e$W*GX~}>7@rWm zWyMUeUV@ZReyOwAJkToG2PS6XuG$I=^uxtQE7ZNTM0r5-#0000< KMNUMnLSTZ9c_YUF delta 107 zcmV-x0F?ig0hj@hG-OXnL_t(I5o2JW6Yz;h{|~|xS_d-%MpJ0qsCL?f03*y;QsZgM zikV=&OfUnm(J)2WbDarr< diff --git a/plugins/easyimage/icons/hidpi/easyimageside.png b/plugins/easyimage/icons/hidpi/easyimageside.png index ac50432e53a3ae891c4d249647a9c4b66a2b61d6..aaac75fefedce0119fc537f4b7b728e65e4682d3 100644 GIT binary patch delta 255 zcmVX$G=JhrL_t(o3GGzD5yCJG3moGy02?q98!$lkgDZz}x}-WKHEnsM zpTv$W%Zk&K#&@Iw*W3Ly*T;H3lFYAap8$leV7qmCK0dit1q3R9)KzI^^^;5D8<_TPy1)faHq6A<&k1{(M(N)R-E_jeZd7l9s19i?|tM>L5 z6zbZR72fa<1p*4>IR?gNFXmg|@8&98e#w zgk0?N`Eqr;EPuJ~kLM=8;4n}i2I;c>Hx67td-OT2@7LaY1%VX-vTDfPa3is7@G7bZ zyiMiM<`G5+OY*#TIuPDO=Nt}eDv-@&yHIZJPOpLbKhsdHvVR3)L{QKr0MH_rTt#3_ zvvShdBNmM7YCeS)!!!l0Az4cYd=7l~7;yIHpdO8<+y7w)aFU~rp$|@0A2TE+Y9MNQ zAj1LQi&Q|b5p^vHc^0+cumDZS2D3aB;60fa2LVyR;F%VO--1yEr*mNRAlWy~fe+1? WSZqu@6^Z}=00{s|MNUMnLSTY1Sa>l2 From 4109407e575274606ed272ee61d2e391363ecb26 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 5 Dec 2017 12:45:08 +0100 Subject: [PATCH 248/642] Add integration with balloon toolbar. --- plugins/easyimage/plugin.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 79d1a519a7c..5c03f861739 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -71,6 +71,31 @@ } ) ); } + function addToolbar( editor ) { + editor.ui.addButton( 'EasyimageFull', { + label: editor.lang.easyimage.commands.fullImage, + command: 'easyimageFull', + toolbar: 'easyimage,1' + } ); + + editor.ui.addButton( 'EasyimageSide', { + label: editor.lang.easyimage.commands.sideImage, + command: 'easyimageSide', + toolbar: 'easyimage,2' + } ); + + editor.ui.addButton( 'EasyimageAlt', { + label: editor.lang.easyimage.commands.altText, + command: 'easyimageAlt', + toolbar: 'easyimage,3' + } ); + + editor.balloonToolbars.create( { + buttons: 'EasyimageFull,EasyimageSide,EasyimageAlt', + widgets: [ 'easyimage' ] + } ); + } + function addMenuItems( editor ) { editor.addMenuGroup( 'easyimage' ); editor.addMenuItems( { @@ -364,7 +389,7 @@ }; CKEDITOR.plugins.add( 'easyimage', { - requires: 'imagebase,uploadwidget,contextmenu,dialog,cloudservices', + requires: 'imagebase,uploadwidget,balloontoolbar,contextmenu,dialog,cloudservices', lang: 'en', icons: 'easyimagefull,easyimageside,easyimagealt', // %REMOVE_LINE_CORE% hidpi: true, // %REMOVE_LINE_CORE% @@ -384,6 +409,7 @@ afterInit: function( editor ) { registerWidget( editor ); registerUploadWidget( editor ); + addToolbar( editor ); } } ); From 76e60ef9cf0054caa4767383920fef33ed9e7ac5 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 5 Dec 2017 13:15:15 +0100 Subject: [PATCH 249/642] Make integration with context menu optional. --- plugins/easyimage/plugin.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 5c03f861739..74f2b78c487 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -97,6 +97,10 @@ } function addMenuItems( editor ) { + if ( !editor.plugins.contextmenu ) { + return; + } + editor.addMenuGroup( 'easyimage' ); editor.addMenuItems( { easyimageFull: { @@ -389,7 +393,7 @@ }; CKEDITOR.plugins.add( 'easyimage', { - requires: 'imagebase,uploadwidget,balloontoolbar,contextmenu,dialog,cloudservices', + requires: 'imagebase,uploadwidget,balloontoolbar,dialog,cloudservices', lang: 'en', icons: 'easyimagefull,easyimageside,easyimagealt', // %REMOVE_LINE_CORE% hidpi: true, // %REMOVE_LINE_CORE% From fb49bd6f0be5ac97b8e88f508fc9971661d7f9e2 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 27 Dec 2017 14:12:08 +0100 Subject: [PATCH 250/642] Add manual test. --- .../easyimage/manual/balloontoolbar.html | 37 +++++++++++++++++++ .../easyimage/manual/balloontoolbar.md | 12 ++++++ 2 files changed, 49 insertions(+) create mode 100644 tests/plugins/easyimage/manual/balloontoolbar.html create mode 100644 tests/plugins/easyimage/manual/balloontoolbar.md diff --git a/tests/plugins/easyimage/manual/balloontoolbar.html b/tests/plugins/easyimage/manual/balloontoolbar.html new file mode 100644 index 00000000000..d880e0da1eb --- /dev/null +++ b/tests/plugins/easyimage/manual/balloontoolbar.html @@ -0,0 +1,37 @@ +

Classic editor

+
+

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

+
+ foo +
Test image
+
+

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

+
+ +

Divarea editor

+
+

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

+
+ foo +
Test image
+
+

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

+
+ +

Inline editor

+
+

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

+
+ foo +
Test image
+
+

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

+
+ + diff --git a/tests/plugins/easyimage/manual/balloontoolbar.md b/tests/plugins/easyimage/manual/balloontoolbar.md new file mode 100644 index 00000000000..41a3c2b9304 --- /dev/null +++ b/tests/plugins/easyimage/manual/balloontoolbar.md @@ -0,0 +1,12 @@ +@bender-tags: 4.9.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, undo, easyimage + +Check integration between balloon toolbar and easy image: + +* Clicking on image should show balloon toolbar with three buttons. + * First button should change image to full size. + * Second button should change image to side image. + * Third button should show dialog for changing alt text. +* Balloon toolbar position should be refreshed according to changes of image's size. +* Buttons in toolbar should mirror real commands' states. From 597ed83dfc8da81313a35c18f6f2739d2f4044c0 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 27 Dec 2017 14:12:26 +0100 Subject: [PATCH 251/642] Manually refresh commands states. --- plugins/easyimage/plugin.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 74f2b78c487..b6875710974 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -183,6 +183,9 @@ } else { this.removeClass( editor.config.easyimage_sideClass ); } + + editor.getCommand( 'easyimageFull' ).refresh( editor ); + editor.getCommand( 'easyimageSide' ).refresh( editor ); } }; From 4bc7c4c7fcb2654ad88f6061bf041e0b8bae0ec5 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 27 Dec 2017 14:13:53 +0100 Subject: [PATCH 252/642] Add unit test. --- tests/plugins/easyimage/commands.js | 35 ++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/commands.js b/tests/plugins/easyimage/commands.js index 2406862921a..0f104464123 100644 --- a/tests/plugins/easyimage/commands.js +++ b/tests/plugins/easyimage/commands.js @@ -1,5 +1,5 @@ /* bender-tags: editor,widget */ -/* bender-ckeditor-plugins: easyimage,toolbar */ +/* bender-ckeditor-plugins: easyimage,toolbar,contextmenu,undo */ ( function() { 'use strict'; @@ -135,6 +135,39 @@ assert.areSame( 'side', widget.data.type, 'Widget has correct type data' ); } ); + }, + + 'test balloontoolbar integration': function( editor, bot ) { + bot.setData( widgetHtml, function() { + var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ), + toolbar = editor.balloonToolbars._contexts[ 0 ].toolbar; + + toolbar._view.once( 'show', function() { + resume( function() { + assertCommandsState( editor, { + easyimageFull: CKEDITOR.TRISTATE_ON, + easyimageSide: CKEDITOR.TRISTATE_OFF, + easyimageAlt: CKEDITOR.TRISTATE_OFF + } ); + + editor.once( 'afterCommandExec', function() { + resume( function() { + assertCommandsState( editor, { + easyimageFull: CKEDITOR.TRISTATE_OFF, + easyimageSide: CKEDITOR.TRISTATE_ON, + easyimageAlt: CKEDITOR.TRISTATE_OFF + } ); + } ); + } ); + + editor.execCommand( 'easyimageSide' ); + wait(); + } ); + } ); + + widget.focus(); + wait(); + } ); } }; From 641ad2952b8bc0be80e8a66e7826f00cef469f58 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 27 Dec 2017 15:35:31 +0100 Subject: [PATCH 253/642] Tests: inlcuded undo plugin in Easy Image upload test. Without this no change event is triggered, thus Ballon Toolbar has a buggy positioning. --- tests/plugins/easyimage/manual/upload.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/manual/upload.md b/tests/plugins/easyimage/manual/upload.md index e957b48f69e..027d5772eb5 100644 --- a/tests/plugins/easyimage/manual/upload.md +++ b/tests/plugins/easyimage/manual/upload.md @@ -1,6 +1,6 @@ @bender-tags: 4.8.0, feature, 932 @bender-ui: collapsed -@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, undo ## Easy Image Upload From 724ca00dbaa9c272ec28afa7658fe7d3fb1dc6b5 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 28 Dec 2017 12:11:32 +0100 Subject: [PATCH 254/642] Simplify async test. --- tests/plugins/easyimage/commands.js | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/tests/plugins/easyimage/commands.js b/tests/plugins/easyimage/commands.js index 0f104464123..8af15d4941e 100644 --- a/tests/plugins/easyimage/commands.js +++ b/tests/plugins/easyimage/commands.js @@ -143,26 +143,23 @@ toolbar = editor.balloonToolbars._contexts[ 0 ].toolbar; toolbar._view.once( 'show', function() { - resume( function() { - assertCommandsState( editor, { - easyimageFull: CKEDITOR.TRISTATE_ON, - easyimageSide: CKEDITOR.TRISTATE_OFF, - easyimageAlt: CKEDITOR.TRISTATE_OFF - } ); + assertCommandsState( editor, { + easyimageFull: CKEDITOR.TRISTATE_ON, + easyimageSide: CKEDITOR.TRISTATE_OFF, + easyimageAlt: CKEDITOR.TRISTATE_OFF + } ); - editor.once( 'afterCommandExec', function() { - resume( function() { - assertCommandsState( editor, { - easyimageFull: CKEDITOR.TRISTATE_OFF, - easyimageSide: CKEDITOR.TRISTATE_ON, - easyimageAlt: CKEDITOR.TRISTATE_OFF - } ); + editor.once( 'afterCommandExec', function() { + resume( function() { + assertCommandsState( editor, { + easyimageFull: CKEDITOR.TRISTATE_OFF, + easyimageSide: CKEDITOR.TRISTATE_ON, + easyimageAlt: CKEDITOR.TRISTATE_OFF } ); } ); - - editor.execCommand( 'easyimageSide' ); - wait(); } ); + + editor.execCommand( 'easyimageSide' ); } ); widget.focus(); From ee3e43ae7890eb3daa58219d7c49b1d15e080c2a Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 29 Dec 2017 13:02:57 +0100 Subject: [PATCH 255/642] Refactoring: some Easy Image commands should force selection check. More info on that in commments / PR related to this branch. --- plugins/easyimage/plugin.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index b6875710974..ee0a8c0e8da 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -33,7 +33,7 @@ }; } - function createCommand( exec, refreshCheck ) { + function createCommand( exec, refreshCheck, forceSelectionCheck ) { return { startDisabled: true, contextSensitive: true, @@ -43,9 +43,12 @@ exec( widget ); - // We have to manually force refresh commands as refresh seems - // to be executed prior to exec. - editor.forceNextSelectionCheck(); + if ( forceSelectionCheck ) { + // We have to manually force refresh commands as refresh seems to be executed prior to exec. + // Without this command states would be outdated. + editor.forceNextSelectionCheck(); + editor.selectionChange( true ); + } }, refresh: createCommandRefresh( refreshCheck ) @@ -56,13 +59,13 @@ widget.setData( 'type', 'full' ); }, function( widget ) { return isFullImage( widget ); - } ) ); + }, true ) ); editor.addCommand( 'easyimageSide', createCommand( function( widget ) { widget.setData( 'type', 'side' ); }, function( widget ) { return isSideImage( widget ); - } ) ); + }, true ) ); editor.addCommand( 'easyimageAlt', new CKEDITOR.dialogCommand( 'easyimageAlt', { startDisabled: true, @@ -183,9 +186,6 @@ } else { this.removeClass( editor.config.easyimage_sideClass ); } - - editor.getCommand( 'easyimageFull' ).refresh( editor ); - editor.getCommand( 'easyimageSide' ).refresh( editor ); } }; From 538fcefa4e95c12804e24527698c7ef540a6c9cd Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 29 Dec 2017 14:52:23 +0100 Subject: [PATCH 256/642] Added button as an explicit Easy Image dependency. --- plugins/easyimage/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index ee0a8c0e8da..cb8bf82ecba 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -396,7 +396,7 @@ }; CKEDITOR.plugins.add( 'easyimage', { - requires: 'imagebase,uploadwidget,balloontoolbar,dialog,cloudservices', + requires: 'imagebase,uploadwidget,balloontoolbar,button,dialog,cloudservices', lang: 'en', icons: 'easyimagefull,easyimageside,easyimagealt', // %REMOVE_LINE_CORE% hidpi: true, // %REMOVE_LINE_CORE% From b6599161c54f38e4fb9a6a4c93cf6556a9b02734 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 29 Dec 2017 15:03:56 +0100 Subject: [PATCH 257/642] Adjusted Easy Image sample. --- plugins/easyimage/samples/easyimage.html | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/easyimage/samples/easyimage.html b/plugins/easyimage/samples/easyimage.html index 19c9ab6f769..fa5cc8aa09c 100644 --- a/plugins/easyimage/samples/easyimage.html +++ b/plugins/easyimage/samples/easyimage.html @@ -40,7 +40,6 @@

Easy Image Demo

It shows our progress of work on Easy Image plugin.

-

At the moment commands could be invoked via context menu.

@@ -50,7 +49,7 @@

Easy Image Demo

Apollo 11

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

-
+
Saturn V carrying Apollo 11
Saturn V carrying Apollo 11
@@ -109,6 +108,14 @@

Apollo 11

getToken( function( token ) { CKEDITOR.replace( 'editor', { + plugins: 'sourcearea,toolbar,undo,wysiwygarea,list,liststyle,format,link,basicstyles', + toolbar: [ + { name: 'document', items: [ 'Source', 'Undo', 'Redo' ] }, + { name: 'basicstyles', items: [ 'Bold', 'Italic', 'Strike', '-', 'RemoveFormat' ] }, + { name: 'paragraph', items: [ 'NumberedList', 'BulletedList' ] }, + { name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] }, + { name: 'styles', items: [ 'Format' ] } + ], extraPlugins: 'easyimage', cloudServices_url: 'https://files.cke-cs.com/upload/', cloudServices_token: token, From 3c31adaad3db31edd351f406977a989c790351c8 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 29 Dec 2017 10:57:34 +0100 Subject: [PATCH 258/642] Add width attribute. --- plugins/easyimage/plugin.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 79d1a519a7c..83339b4630f 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -115,7 +115,7 @@ }, img: { - attributes: '!src,srcset,alt' + attributes: '!src,srcset,alt,width,sizes' } }, @@ -197,10 +197,11 @@ }, onUploaded: function( upload ) { - var srcset = CKEDITOR.plugins.easyimage._parseSrcSet( upload.responseData.response ); + var srcset = CKEDITOR.plugins.easyimage._parseSrcSet( upload.responseData.response ), + width = this.parts.img.$.naturalWidth; this.replaceWith( '
' ); + upload.responseData.response[ 'default' ] + '" srcset="' + srcset + '" sizes="100vw" width="' + width + '">
' ); } }; From 175cd901ca44fa27da005c84b0b41b6fc27f9e5d Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 29 Dec 2017 11:00:06 +0100 Subject: [PATCH 259/642] Update unit tests. --- tests/plugins/easyimage/uploadwidget.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index c0a765be592..419fb8b6357 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -12,7 +12,7 @@ DATA_IMG = 'data:', BLOB_IMG = 'blob:', WIDGET_HTML = '
' + - '' + + '' + '
' + '
', commonConfig = { @@ -141,7 +141,7 @@ loader.url = IMG_URL; loader.changeStatus( 'uploaded' ); - assert.sameData( WIDGET_HTML, editor.getData() ); + assert.beautified.html( WIDGET_HTML, editor.getData() ); assert.areSame( 1, editor.editable().find( '[data-widget="easyimage"]' ).count(), 'Easy Image widgets count' ); assert.areSame( 0, loadAndUploadCount ); @@ -170,7 +170,7 @@ loader.url = IMG_URL; loader.changeStatus( 'uploaded' ); - assert.sameData( '

x

' + WIDGET_HTML + '

x

', editor.getData() ); + assert.beautified.html( '

x

' + WIDGET_HTML + '

x

', editor.getData() ); assert.areSame( 1, editor.editable().find( '[data-widget="easyimage"]' ).count() ); assert.areSame( 0, loadAndUploadCount ); From 679d365c93ea50651114514cd6cfabb37165ebc1 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 29 Dec 2017 11:54:39 +0100 Subject: [PATCH 260/642] Add manual test. --- .../easyimage/manual/imagestretch.html | 81 +++++++++++++++++++ .../plugins/easyimage/manual/imagestretch.md | 15 ++++ 2 files changed, 96 insertions(+) create mode 100644 tests/plugins/easyimage/manual/imagestretch.html create mode 100644 tests/plugins/easyimage/manual/imagestretch.md diff --git a/tests/plugins/easyimage/manual/imagestretch.html b/tests/plugins/easyimage/manual/imagestretch.html new file mode 100644 index 00000000000..ae0cb6b5305 --- /dev/null +++ b/tests/plugins/easyimage/manual/imagestretch.html @@ -0,0 +1,81 @@ +

Note, this test uses a real Cloud Service connection, so you might want to be on-line 😉.

+ +

Classic editor

+ +
+

Sample editor

+

Go on, put some content here.

+
+ +

Divarea editor

+ +
+

Sample editor

+

Go on, put some content here.

+
+ +

Inline editor

+ +
+

Sample editor

+

Go on, put some content here.

+
+ + diff --git a/tests/plugins/easyimage/manual/imagestretch.md b/tests/plugins/easyimage/manual/imagestretch.md new file mode 100644 index 00000000000..6cd0dcd8e45 --- /dev/null +++ b/tests/plugins/easyimage/manual/imagestretch.md @@ -0,0 +1,15 @@ +@bender-tags: 4.9.0, feature, 932, tp3301 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage + +## Easy Image Upload + +Upload some small image, e.g. [`foo.png`](%BASE_PATH%plugins/image2/_assets/foo.png). + +### Expected + +Image has its natural dimensions. + +### Unexpected + +Image is stretched to fill whole editor's width. From 7574845c14346fa50910a17f91f36a0a02812c03 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 29 Dec 2017 17:47:52 +0100 Subject: [PATCH 261/642] Get natural width of image after loading it. --- plugins/easyimage/plugin.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 83339b4630f..8b924b1d0ff 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -170,6 +170,21 @@ } function registerUploadWidget( editor ) { + // Natural width of the image can be fetched only after image is loaded. + // However cached images won't fire `load` event, but just mark themselves + // as complete. + function getNaturalWidth( image, callback ) { + var $image = image.$; + + if ( $image.complete && $image.naturalWidth ) { + return callback( $image.naturalWidth ); + } + + image.once( 'load', function() { + callback( $image.naturalWidth ); + } ); + } + var uploadWidgetDefinition = { supportedTypes: /image\/(jpeg|png|gif|bmp)/, @@ -198,10 +213,12 @@ onUploaded: function( upload ) { var srcset = CKEDITOR.plugins.easyimage._parseSrcSet( upload.responseData.response ), - width = this.parts.img.$.naturalWidth; + widget = this; - this.replaceWith( '
' ); + } ); } }; From 62aff4b0c37c749d92c1cf4322459560f378232e Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 29 Dec 2017 17:57:19 +0100 Subject: [PATCH 262/642] Move getToken to external file. --- .../easyimage/manual/_helpers/tools.js | 42 +++++++++++++++++++ .../easyimage/manual/imagestretch.html | 41 +----------------- tests/plugins/easyimage/manual/upload.html | 41 +----------------- 3 files changed, 44 insertions(+), 80 deletions(-) create mode 100644 tests/plugins/easyimage/manual/_helpers/tools.js diff --git a/tests/plugins/easyimage/manual/_helpers/tools.js b/tests/plugins/easyimage/manual/_helpers/tools.js new file mode 100644 index 00000000000..e80f83a007f --- /dev/null +++ b/tests/plugins/easyimage/manual/_helpers/tools.js @@ -0,0 +1,42 @@ +/* exported getToken */ +/* global console */ + +// WARNING: The URL below should not be used for any other purpose than Easy Image plugin development. +// Images uploaded using the testing token service may be deleted automatically at any moment. +// If you would like to try the Easy Image service, please wait until the official launch of Easy Image and sign up for a free trial. +// Images uploaded during the free trial will not be deleted for the whole trial period and additionally the trial service can be converted +// into a subscription at any moment, allowing you to preserve all uploaded images. +var CLOUD_SERVICES_TOKEN_URL = 'https://j2sns7jmy0.execute-api.eu-central-1.amazonaws.com/prod/token'; + +function getToken( callback ) { + function uid() { + var uuid = 'e'; // Make sure that id does not start with number. + + for ( var i = 0; i < 8; i++ ) { + uuid += Math.floor( ( 1 + Math.random() ) * 0x10000 ).toString( 16 ).substring( 1 ); + } + + return uuid; + } + + var xhr = new XMLHttpRequest(), + userId = uid(); + + xhr.open( 'GET', CLOUD_SERVICES_TOKEN_URL + '?user.id=' + userId ); + + xhr.onload = function() { + if ( xhr.status >= 200 && xhr.status < 300 ) { + var response = JSON.parse( xhr.responseText ); + + callback( response.token ); + } else { + console.error( xhr.status ); + } + }; + + xhr.onerror = function( error ) { + console.error( error ); + }; + + xhr.send( null ); +} diff --git a/tests/plugins/easyimage/manual/imagestretch.html b/tests/plugins/easyimage/manual/imagestretch.html index ae0cb6b5305..e1e93894435 100644 --- a/tests/plugins/easyimage/manual/imagestretch.html +++ b/tests/plugins/easyimage/manual/imagestretch.html @@ -21,51 +21,12 @@

Sample editor

Go on, put some content here.

+ + diff --git a/tests/plugins/easyimage/manual/undo.md b/tests/plugins/easyimage/manual/undo.md new file mode 100644 index 00000000000..3b3349ed586 --- /dev/null +++ b/tests/plugins/easyimage/manual/undo.md @@ -0,0 +1,23 @@ +@bender-tags: 4.9.0, feature, 932, tp3183 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, undo + +## Easy Image Upload + +Upload some images: + +1. Execute one of the following steps: + 1. Make a screenshot, copy a graphic to the clipboard and paste using `ctrl/cmd+v`. + 1. Drag and drop an jpg/png/bmp/gif image from your OS explorer to the editable. + 1. Firefox only: Copy an image file (from your OS explorer) into the clipboard, and paste into the editable. +2. Click "Undo" button + +### Expected + +* Widget is removed from the editor. +* There is only one undo step. + +### Unexpected + +* Widget still exists after pressing "Undo". +* There are more than one undo steps. From 6ae23ced1fc889cf144152ee2f0a559f40858115 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 9 Jan 2018 16:47:29 +0100 Subject: [PATCH 270/642] Add unit test. --- tests/plugins/easyimage/uploadwidget.js | 31 ++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index e586fc9e16c..fcc7fb33b1f 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -1,5 +1,5 @@ /* bender-tags: editor,clipboard,widget */ -/* bender-ckeditor-plugins: easyimage,toolbar, */ +/* bender-ckeditor-plugins: easyimage,toolbar,undo */ /* bender-include: %BASE_PATH%/plugins/clipboard/_helpers/pasting.js */ /* bender-include: %BASE_PATH%/plugins/uploadfile/_helpers/waitForImage.js */ /* global pasteFiles, waitForImage */ @@ -157,6 +157,35 @@ } ); }, + // #tp3183 + 'test undo steps (integration test)': function( editor ) { + var file = bender.tools.srcToFile( DATA_IMG ); + file.name = 'foo.gif'; + pasteFiles( editor, [ file ] ); + + var loader = editor.uploadRepository.loaders[ 0 ]; + + loader.data = DATA_IMG; + loader.uploadTotal = 10; + loader.changeStatus( 'uploading' ); + + var image = editor.editable().find( 'img[data-widget="uploadeasyimage"]' ).getItem( 0 ); + + loader.url = IMG_URL; + loader.changeStatus( 'uploaded' ); + + waitForImage( image, function() { + setTimeout( function() { + resume( function() { + assert.isFalse( editor.undoManager.undoable(), 'undo state' ); + } ); + }, 0 ); + + editor.execCommand( 'undo' ); + wait(); + } ); + }, + 'test paste img as html (integration test)': function( editor, bot ) { bot.setData( '', function() { pasteFiles( editor, [], '

xx

' ); From 65a4f65cf75f45ba04e6ca051dab2503f2ab2f84 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 9 Jan 2018 16:50:54 +0100 Subject: [PATCH 271/642] Lock snapshots during widget replacement. --- plugins/easyimage/plugin.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 3d71d4646fc..7c23ee2428d 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -248,11 +248,15 @@ widget = this; getNaturalWidth( widget.parts.img, function( width ) { + editor.fire( 'lockSnapshot' ); + widget.replaceWith( '
' + '' + '
' + '
' ); + + editor.fire( 'unlockSnapshot' ); } ); } }; From d746e8cc9919ed77dfcef2dd8efecda130fa9968 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 9 Jan 2018 16:57:22 +0100 Subject: [PATCH 272/642] Lock snapshot during updating progressbar. --- plugins/easyimage/plugin.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 7c23ee2428d..ec32a150797 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -360,7 +360,10 @@ if ( progressBar && loader.uploadTotal ) { percentage = ( loader.uploaded / loader.uploadTotal ) * 100; + + editor.fire( 'lockSnapshot' ); progressBar.setStyle( 'width', percentage + '%' ); + editor.fire( 'unlockSnapshot' ); } }, this ); From ed6d3bd795bd8a1778d2a0b98cd1e3e072a045a8 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 10 Jan 2018 12:36:11 +0100 Subject: [PATCH 273/642] Fix unit test. --- tests/plugins/easyimage/uploadwidget.js | 36 ++++++++++++++++--------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/tests/plugins/easyimage/uploadwidget.js b/tests/plugins/easyimage/uploadwidget.js index fcc7fb33b1f..2f9e32d98a8 100644 --- a/tests/plugins/easyimage/uploadwidget.js +++ b/tests/plugins/easyimage/uploadwidget.js @@ -159,6 +159,8 @@ // #tp3183 'test undo steps (integration test)': function( editor ) { + editor.resetUndo(); + var file = bender.tools.srcToFile( DATA_IMG ); file.name = 'foo.gif'; pasteFiles( editor, [ file ] ); @@ -166,24 +168,34 @@ var loader = editor.uploadRepository.loaders[ 0 ]; loader.data = DATA_IMG; + loader.uploaded = 0; loader.uploadTotal = 10; loader.changeStatus( 'uploading' ); - var image = editor.editable().find( 'img[data-widget="uploadeasyimage"]' ).getItem( 0 ); + // We need timeout to omit progressbar throttling to force refresh of progressbar. + setTimeout( function() { + resume( function() { + loader.uploaded += 7; + loader.update(); - loader.url = IMG_URL; - loader.changeStatus( 'uploaded' ); + var image = editor.editable().find( 'img[data-widget="uploadeasyimage"]' ).getItem( 0 ); - waitForImage( image, function() { - setTimeout( function() { - resume( function() { - assert.isFalse( editor.undoManager.undoable(), 'undo state' ); - } ); - }, 0 ); + loader.url = IMG_URL; + loader.changeStatus( 'uploaded' ); - editor.execCommand( 'undo' ); - wait(); - } ); + waitForImage( image, function() { + editor.once( 'afterCommandExec', function() { + resume( function() { + assert.isFalse( editor.undoManager.undoable(), 'undo state' ); + } ); + } ); + + editor.execCommand( 'undo' ); + wait(); + } ); + } ); + }, 150 ); + wait(); }, 'test paste img as html (integration test)': function( editor, bot ) { From e8be7d659212f06ebc88a1044103b170f34ce2c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Thu, 11 Jan 2018 17:07:12 +0100 Subject: [PATCH 274/642] Rewording. --- tests/plugins/easyimage/manual/undo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/manual/undo.md b/tests/plugins/easyimage/manual/undo.md index 3b3349ed586..01f41cf7825 100644 --- a/tests/plugins/easyimage/manual/undo.md +++ b/tests/plugins/easyimage/manual/undo.md @@ -20,4 +20,4 @@ Upload some images: ### Unexpected * Widget still exists after pressing "Undo". -* There are more than one undo steps. +* There are more than one undo step. From 0a10f59b87ad6c1c12d3a19c94e91312cfb10bb4 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 11 Jan 2018 17:26:50 +0100 Subject: [PATCH 275/642] Add info about Safari. --- tests/plugins/easyimage/manual/undo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/manual/undo.md b/tests/plugins/easyimage/manual/undo.md index 01f41cf7825..8dcad4ecc94 100644 --- a/tests/plugins/easyimage/manual/undo.md +++ b/tests/plugins/easyimage/manual/undo.md @@ -7,7 +7,7 @@ Upload some images: 1. Execute one of the following steps: - 1. Make a screenshot, copy a graphic to the clipboard and paste using `ctrl/cmd+v`. + 1. Make a screenshot, copy a graphic to the clipboard and paste using `ctrl/cmd+v`. This method does not work in Safari at the moment. 1. Drag and drop an jpg/png/bmp/gif image from your OS explorer to the editable. 1. Firefox only: Copy an image file (from your OS explorer) into the clipboard, and paste into the editable. 2. Click "Undo" button From 8419270af20f4d3b6d9d6c2d6e26009264590c79 Mon Sep 17 00:00:00 2001 From: Jacek Bogdanski Date: Fri, 12 Jan 2018 15:56:35 +0100 Subject: [PATCH 276/642] Bender version tags update. --- tests/plugins/easyimage/manual/dndimagetype.md | 2 +- tests/plugins/easyimage/manual/easyimage.md | 2 +- tests/plugins/easyimage/manual/figuresnoclass.md | 2 +- tests/plugins/easyimage/manual/pasteimagetype.md | 2 +- tests/plugins/easyimage/manual/progressbar.md | 2 +- tests/plugins/easyimage/manual/styles.md | 2 +- tests/plugins/easyimage/manual/upload.md | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/plugins/easyimage/manual/dndimagetype.md b/tests/plugins/easyimage/manual/dndimagetype.md index eb9f2f62178..3f4a06f9c7f 100644 --- a/tests/plugins/easyimage/manual/dndimagetype.md +++ b/tests/plugins/easyimage/manual/dndimagetype.md @@ -1,4 +1,4 @@ -@bender-tags: 4.8.0, bug, easyimage, 932, tp3163 +@bender-tags: 4.9.0, bug, easyimage, 932, tp3163 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, htmlwriter, elementspath diff --git a/tests/plugins/easyimage/manual/easyimage.md b/tests/plugins/easyimage/manual/easyimage.md index ec479308208..c5a9f996093 100644 --- a/tests/plugins/easyimage/manual/easyimage.md +++ b/tests/plugins/easyimage/manual/easyimage.md @@ -1,4 +1,4 @@ -@bender-tags: 4.8.0, feature, 932 +@bender-tags: 4.9.0, feature, 932 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage diff --git a/tests/plugins/easyimage/manual/figuresnoclass.md b/tests/plugins/easyimage/manual/figuresnoclass.md index 4c8c9b0ad7f..2bd89efb7bc 100644 --- a/tests/plugins/easyimage/manual/figuresnoclass.md +++ b/tests/plugins/easyimage/manual/figuresnoclass.md @@ -1,4 +1,4 @@ -@bender-tags: 4.8.0, feature, config, 932 +@bender-tags: 4.9.0, feature, config, 932 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, htmlwriter, elementspath diff --git a/tests/plugins/easyimage/manual/pasteimagetype.md b/tests/plugins/easyimage/manual/pasteimagetype.md index cbf37e2bb2d..4d298ad42fe 100644 --- a/tests/plugins/easyimage/manual/pasteimagetype.md +++ b/tests/plugins/easyimage/manual/pasteimagetype.md @@ -1,4 +1,4 @@ -@bender-tags: 4.8.0, bug, easyimage, 932, tp3162 +@bender-tags: 4.9.0, bug, easyimage, 932, tp3162 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, htmlwriter, elementspath diff --git a/tests/plugins/easyimage/manual/progressbar.md b/tests/plugins/easyimage/manual/progressbar.md index d46f2799fc7..8270ab61a8d 100644 --- a/tests/plugins/easyimage/manual/progressbar.md +++ b/tests/plugins/easyimage/manual/progressbar.md @@ -1,4 +1,4 @@ -@bender-tags: 4.8.0, feature, 932 +@bender-tags: 4.9.0, feature, 932 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage @bender-include: ../../uploadwidget/manual/_helpers/xhr.js diff --git a/tests/plugins/easyimage/manual/styles.md b/tests/plugins/easyimage/manual/styles.md index f6314f805e7..ac815dabec4 100644 --- a/tests/plugins/easyimage/manual/styles.md +++ b/tests/plugins/easyimage/manual/styles.md @@ -1,4 +1,4 @@ -@bender-tags: 4.8.0, feature, 932 +@bender-tags: 4.9.0, feature, 932 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage diff --git a/tests/plugins/easyimage/manual/upload.md b/tests/plugins/easyimage/manual/upload.md index 027d5772eb5..05e0ef5e3bc 100644 --- a/tests/plugins/easyimage/manual/upload.md +++ b/tests/plugins/easyimage/manual/upload.md @@ -1,4 +1,4 @@ -@bender-tags: 4.8.0, feature, 932 +@bender-tags: 4.9.0, feature, 932 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, undo From 981e5460576adab5742c5e0f5b0f04f32dc399a1 Mon Sep 17 00:00:00 2001 From: Kajetan Litwinowicz Date: Fri, 12 Jan 2018 14:00:04 +0100 Subject: [PATCH 277/642] Refactoring: link feature definition moved to separate method getLinkFeature. --- plugins/imagebase/plugin.js | 128 ++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 58 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 907bdca9155..09efac64c4c 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -27,6 +27,16 @@ } } + function appendMenuItems( editor ) { + editor.addMenuGroup( 'imagebase', 10 ); + + editor.addMenuItem( 'imagebase', { + label: editor.lang.link.menu, + command: 'link', + group: 'imagebase' + } ); + } + function createLink( editor, img, linkData ) { var link = img.getAscendant( 'a' ) || editor.document.createElement( 'a' ); @@ -44,8 +54,56 @@ return CKEDITOR.plugins.link.parseLinkAttributes( widget.editor, widget.parts.link ); } - var featuresDefinitions = { - link: { + function getLinkFeature() { + function isNotLinkableOrIsLink( widget, dialog ) { + return !isLinkable( widget ) || dialog._.name !== 'link'; + } + + function registerOkListener( dialog, widget ) { + return ( + dialog.once( 'ok', function( evt ) { + if ( !isLinkable( widget ) ) { + return; + } + + evt.stop(); + + var data = {}; + + dialog.commitContent( data ); + widget.setData( 'link', data ); + }, null, null, 9 ) ); + } + + function unlinkChangeDefault( editor, evtType ) { + editor.getCommand( 'unlink' ).on( evtType, function( evt ) { + var widget = getFocusedWidget( editor ); + + // Override unlink only when link truly belongs to the widget. + // If wrapped inline widget in a link, let default unlink work (http://dev.ckeditor.com/ticket/11814). + if ( !isLinkable( widget ) ) { + return; + } + + evt.stop(); + + switch ( evtType ) { + case 'exec': + widget.setData( 'link' , null ); + // Selection (which is fake) may not change if unlinked image in focused widget, + // i.e. if captioned image. Let's refresh command state manually here. + this.refresh( editor, editor.elementPath() ); + break; + case 'refresh': + this.setState( widget.parts.link ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED ); + break; + } + + evt.cancel(); + } ); + } + + return { allowedContent: { a: { attributes: '!href' @@ -71,13 +129,7 @@ } if ( editor.contextMenu ) { - editor.addMenuGroup( 'imagebase', 10 ); - - editor.addMenuItem( 'imagebase', { - label: editor.lang.link.menu, - command: 'link', - group: 'imagebase' - } ); + appendMenuItems( editor ); } editor.on( 'dialogShow', function( evt ) { @@ -86,7 +138,7 @@ displayTextField, okListener; - if ( !isLinkable( widget ) || dialog._.name !== 'link' ) { + if ( isNotLinkableOrIsLink( widget, dialog ) ) { return; } @@ -99,18 +151,7 @@ // It gets the user input and set appropriate data in the widget. // `evt.stop` and higher priority are necessary to prevent adding unwanted link to // widget's caption. - okListener = dialog.once( 'ok', function( evt ) { - if ( !isLinkable( widget ) ) { - return; - } - - evt.stop(); - - var data = {}; - - dialog.commitContent( data ); - widget.setData( 'link', data ); - }, null, null, 9 ); + okListener = registerOkListener( dialog, widget ); dialog.once( 'hide', function() { okListener.removeListener(); @@ -119,42 +160,9 @@ } ); // Overwrite default behaviour of unlink command. - editor.getCommand( 'unlink' ).on( 'exec', function( evt ) { - var widget = getFocusedWidget( editor ); - - // Override unlink only when link truly belongs to the widget. - // If wrapped inline widget in a link, let default unlink work (http://dev.ckeditor.com/ticket/11814). - if ( !isLinkable( widget ) ) { - return; - } - - evt.stop(); - - widget.setData( 'link', null ); - - // Selection (which is fake) may not change if unlinked image in focused widget, - // i.e. if captioned image. Let's refresh command state manually here. - this.refresh( editor, editor.elementPath() ); - - evt.cancel(); - } ); - + unlinkChangeDefault( editor, 'exec' ); // Overwrite default refresh of unlink command. - editor.getCommand( 'unlink' ).on( 'refresh', function( evt ) { - var widget = getFocusedWidget( editor ); - - if ( !isLinkable( widget ) ) { - return; - } - - evt.stop(); - - // Note that widget may be wrapped in a link, which - // does not belong to that widget (http://dev.ckeditor.com/ticket/11814). - this.setState( widget.parts.link ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED ); - - evt.cancel(); - } ); + unlinkChangeDefault( editor, 'refresh' ); }, data: function( evt ) { @@ -182,7 +190,11 @@ this.parts.link = createLink( editor, img, link ); } } - } + }; + } + + var featuresDefinitions = { + link: getLinkFeature() }; function createWidgetDefinition( editor, definition ) { From c0e4f971ef481dc029ee6ce721ee04e6b0efe60d Mon Sep 17 00:00:00 2001 From: Kajetan Litwinowicz Date: Mon, 15 Jan 2018 13:50:32 +0100 Subject: [PATCH 278/642] Further refactoring --- plugins/imagebase/plugin.js | 101 +++++++++++++++++------------------- 1 file changed, 47 insertions(+), 54 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 09efac64c4c..2ddd22514e7 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -10,58 +10,53 @@ return editor.widgets.focused; } - function isLinkable( widget ) { - return widget && widget.features && CKEDITOR.tools.array.indexOf( widget.features, 'link' ) !== -1; - } + function getLinkFeature() { + function isLinkable( widget ) { + return widget && widget.features && CKEDITOR.tools.array.indexOf( widget.features, 'link' ) !== -1; + } - function addLinkAttributes( editor, linkElement, linkData ) { - // Set and remove all attributes associated with this state. - var attributes = CKEDITOR.plugins.link.getLinkAttributes( editor, linkData ); + function addLinkAttributes( editor, linkElement, linkData ) { + // Set and remove all attributes associated with this state. + var attributes = CKEDITOR.plugins.link.getLinkAttributes( editor, linkData ); - if ( !CKEDITOR.tools.isEmpty( attributes.set ) ) { - linkElement.setAttributes( attributes.set ); - } + if ( !CKEDITOR.tools.isEmpty( attributes.set ) ) { + linkElement.setAttributes( attributes.set ); + } - if ( attributes.removed.length ) { - linkElement.removeAttributes( attributes.removed ); + if ( attributes.removed.length ) { + linkElement.removeAttributes( attributes.removed ); + } } - } - function appendMenuItems( editor ) { - editor.addMenuGroup( 'imagebase', 10 ); - - editor.addMenuItem( 'imagebase', { - label: editor.lang.link.menu, - command: 'link', - group: 'imagebase' - } ); - } + function createLink( editor, img, linkData ) { + var link = img.getAscendant( 'a' ) || editor.document.createElement( 'a' ); - function createLink( editor, img, linkData ) { - var link = img.getAscendant( 'a' ) || editor.document.createElement( 'a' ); + addLinkAttributes( editor, link, linkData ); - addLinkAttributes( editor, link, linkData ); + if ( !link.contains( img ) ) { + link.replace( img ); + img.move( link ); + } - if ( !link.contains( img ) ) { - link.replace( img ); - img.move( link ); + return link; } - return link; - } + function getLinkData( widget ) { + return CKEDITOR.plugins.link.parseLinkAttributes( widget.editor, widget.parts.link ); + } - function getLinkData( widget ) { - return CKEDITOR.plugins.link.parseLinkAttributes( widget.editor, widget.parts.link ); - } + function appendMenuItems( editor ) { + editor.addMenuGroup( 'imagebase', 10 ); - function getLinkFeature() { - function isNotLinkableOrIsLink( widget, dialog ) { - return !isLinkable( widget ) || dialog._.name !== 'link'; + editor.addMenuItem( 'imagebase', { + label: editor.lang.link.menu, + command: 'link', + group: 'imagebase' + } ); } - function registerOkListener( dialog, widget ) { - return ( - dialog.once( 'ok', function( evt ) { + function createOkListener( evt, dialog, widget ) { + return function() { if ( !isLinkable( widget ) ) { return; } @@ -72,10 +67,10 @@ dialog.commitContent( data ); widget.setData( 'link', data ); - }, null, null, 9 ) ); + }; } - function unlinkChangeDefault( editor, evtType ) { + function addUnlinkListener( editor, evtType, callback ) { editor.getCommand( 'unlink' ).on( evtType, function( evt ) { var widget = getFocusedWidget( editor ); @@ -87,16 +82,8 @@ evt.stop(); - switch ( evtType ) { - case 'exec': - widget.setData( 'link' , null ); - // Selection (which is fake) may not change if unlinked image in focused widget, - // i.e. if captioned image. Let's refresh command state manually here. - this.refresh( editor, editor.elementPath() ); - break; - case 'refresh': - this.setState( widget.parts.link ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED ); - break; + if ( callback && typeof callback === 'function' ) { + callback( this, widget, editor ); } evt.cancel(); @@ -138,7 +125,7 @@ displayTextField, okListener; - if ( isNotLinkableOrIsLink( widget, dialog ) ) { + if ( !isLinkable( widget ) || dialog._.name !== 'link' ) { return; } @@ -151,7 +138,7 @@ // It gets the user input and set appropriate data in the widget. // `evt.stop` and higher priority are necessary to prevent adding unwanted link to // widget's caption. - okListener = registerOkListener( dialog, widget ); + okListener = dialog.once( 'ok', createOkListener( evt, dialog, widget ), null, null, 9 ); dialog.once( 'hide', function() { okListener.removeListener(); @@ -159,10 +146,16 @@ } ); } ); + // Overwrite default behaviour of unlink command. - unlinkChangeDefault( editor, 'exec' ); + addUnlinkListener( editor, 'exec', function( _this, widget, editor ) { + widget.setData( 'link' , null ); + _this.refresh( editor, editor.elementPath() ); + } ); // Overwrite default refresh of unlink command. - unlinkChangeDefault( editor, 'refresh' ); + addUnlinkListener( editor, 'refresh', function( _this, widget ) { + _this.setState( widget.parts.link ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED ); + } ); }, data: function( evt ) { From ee029831616c666dafa95a9e644ff70fe1bb5ae8 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 16:20:24 +0100 Subject: [PATCH 279/642] Rename _this parameter to command. --- plugins/imagebase/plugin.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 2ddd22514e7..37ee6ab99af 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -148,13 +148,13 @@ // Overwrite default behaviour of unlink command. - addUnlinkListener( editor, 'exec', function( _this, widget, editor ) { + addUnlinkListener( editor, 'exec', function( command, widget, editor ) { widget.setData( 'link' , null ); - _this.refresh( editor, editor.elementPath() ); + command.refresh( editor, editor.elementPath() ); } ); - // Overwrite default refresh of unlink command. - addUnlinkListener( editor, 'refresh', function( _this, widget ) { - _this.setState( widget.parts.link ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED ); + + addUnlinkListener( editor, 'refresh', function( command, widget ) { + command.setState( widget.parts.link ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED ); } ); }, From 59321eadf098f6e3bb2da543854065a1a5aae330 Mon Sep 17 00:00:00 2001 From: Jacek Bogdanski Date: Fri, 12 Jan 2018 13:36:07 +0100 Subject: [PATCH 280/642] Fixed styles. --- plugins/easyimage/styles/easyimage.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index 608e0b999bd..7576cc26d60 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -11,6 +11,15 @@ For licensing, see LICENSE.md or http://ckeditor.com/license clear: both; } +/* +The outline is not a part of the element's dimensions, we have to use a border as an outline to align linked image with a caption. +*/ +.easyimage a > img{ + outline: none; + border: 1px solid #0782C1; + box-sizing: border-box; +} + .easyimage img, .cke_widget_uploadeasyimage img { display: block; height: auto; From 24522fcc1df246f9812a5a833a96bc85a5707cd4 Mon Sep 17 00:00:00 2001 From: Jacek Bogdanski Date: Fri, 12 Jan 2018 14:45:18 +0100 Subject: [PATCH 281/642] Added manual tests. --- .../easyimage/manual/imageoutline.html | 43 +++++++++++++++++++ .../plugins/easyimage/manual/imageoutline.md | 13 ++++++ 2 files changed, 56 insertions(+) create mode 100644 tests/plugins/easyimage/manual/imageoutline.html create mode 100644 tests/plugins/easyimage/manual/imageoutline.md diff --git a/tests/plugins/easyimage/manual/imageoutline.html b/tests/plugins/easyimage/manual/imageoutline.html new file mode 100644 index 00000000000..21cb7233723 --- /dev/null +++ b/tests/plugins/easyimage/manual/imageoutline.html @@ -0,0 +1,43 @@ +

Classic editor

+
+
+ foo +
Test image
+
+
+ foo +
Test image
+
+
+ +

Divarea editor

+
+
+ foo +
Test image
+
+
+ foo +
Test image
+
+
+ +

Inline editor

+
+
+ foo +
Test image
+
+
+ foo +
Test image
+
+
+ + \ No newline at end of file diff --git a/tests/plugins/easyimage/manual/imageoutline.md b/tests/plugins/easyimage/manual/imageoutline.md new file mode 100644 index 00000000000..45b1f6bb868 --- /dev/null +++ b/tests/plugins/easyimage/manual/imageoutline.md @@ -0,0 +1,13 @@ +@bender-tags: 4.9.0, bug, 3302 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, link + +Add a link to the selected image. + +## Expected + +Linked image should have correct outline aligned nicely with the rest of a widget (caption background especially). + +## Unexpected + +The outline link is overflowing the widget, thus not aligning perfectly with the caption. \ No newline at end of file From 2c576ce64b3327449c94ea7c770492a550e7efb4 Mon Sep 17 00:00:00 2001 From: Jacek Bogdanski Date: Fri, 12 Jan 2018 15:20:26 +0100 Subject: [PATCH 282/642] Fixed inline and divarea padding. --- plugins/easyimage/styles/easyimage.css | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index 7576cc26d60..49ed86daa02 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -18,6 +18,7 @@ The outline is not a part of the element's dimensions, we have to use a border a outline: none; border: 1px solid #0782C1; box-sizing: border-box; + padding: 1px; } .easyimage img, .cke_widget_uploadeasyimage img { From a4a1e256b52e5375272c6b6193c22a49ca2f8f41 Mon Sep 17 00:00:00 2001 From: Jacek Bogdanski Date: Mon, 15 Jan 2018 12:44:00 +0100 Subject: [PATCH 283/642] Fixed styles and tests. --- plugins/easyimage/styles/easyimage.css | 2 +- .../easyimage/manual/imageoutline.html | 44 ++++++++++++------- .../plugins/easyimage/manual/imageoutline.md | 4 +- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index 49ed86daa02..7dfda923cb1 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -14,7 +14,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license /* The outline is not a part of the element's dimensions, we have to use a border as an outline to align linked image with a caption. */ -.easyimage a > img{ +.easyimage a > img { outline: none; border: 1px solid #0782C1; box-sizing: border-box; diff --git a/tests/plugins/easyimage/manual/imageoutline.html b/tests/plugins/easyimage/manual/imageoutline.html index 21cb7233723..578c682963d 100644 --- a/tests/plugins/easyimage/manual/imageoutline.html +++ b/tests/plugins/easyimage/manual/imageoutline.html @@ -1,11 +1,15 @@

Classic editor

- foo + + foo +
Test image
- foo + + foo +
Test image
@@ -13,25 +17,33 @@

Classic editor

Divarea editor

- foo -
Test image
-
-
- foo -
Test image
-
+ + foo + +
Test image
+ +
+ + foo + +
Test image
+

Inline editor

- foo -
Test image
-
-
- foo -
Test image
-
+ + foo + +
Test image
+ +
+ + foo + +
Test image
+
\ No newline at end of file From b94cbfa6471fd3ccc42ff2140cefd038327a8670 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 12 Jan 2018 15:28:34 +0100 Subject: [PATCH 285/642] Fix for tests in IE. --- tests/plugins/easyimage/commands.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/commands.js b/tests/plugins/easyimage/commands.js index 8af15d4941e..75bd8027a5f 100644 --- a/tests/plugins/easyimage/commands.js +++ b/tests/plugins/easyimage/commands.js @@ -36,15 +36,33 @@ } } - var widgetHtml = '
foo
Test image
', + var originalGetClientRect = CKEDITOR.dom.element.prototype.getClientRect, + widgetHtml = '
foo
Test image
', sideWidgetHtml = '
foo
Test image
', tests = { + setUp: function() { + if ( CKEDITOR.env.ie ) { + CKEDITOR.dom.element.prototype.getClientRect = function() { + return { + width: 0, + height: 0, + left: 0, + top: 0 + }; + }; + } + }, + tearDown: function() { var currentDialog = CKEDITOR.dialog.getCurrent(); if ( currentDialog ) { currentDialog.hide(); } + + if ( CKEDITOR.env.ie ) { + CKEDITOR.dom.element.prototype.getClientRect = originalGetClientRect; + } }, 'test commands are enabled only on widget': function( editor, bot ) { From a3b9aea398bd63a34a3fdbcecbfe9d0ae168cb68 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 15:23:57 +0100 Subject: [PATCH 286/642] Force Edge to run every unit test in new CKEditor's instance. --- tests/plugins/easyimage/commands.js | 35 ++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/commands.js b/tests/plugins/easyimage/commands.js index 75bd8027a5f..8d96fa92d91 100644 --- a/tests/plugins/easyimage/commands.js +++ b/tests/plugins/easyimage/commands.js @@ -18,6 +18,39 @@ } }; + // Force Edge to run every test in new CKEditor's instance. + function createTestsForEditors( editors, tests ) { + var generatedTests = {}, + test, + i = 0; + + function generateTest( name ) { + CKEDITOR.tools.array.forEach( editors, function( editor ) { + var options = CKEDITOR.tools.object.merge( bender.editors[ editor ], { + name: editor + i++ + } ); + + generatedTests[ name + ' (' + editor + ')' ] = function() { + bender.editorBot.create( options, function( bot ) { + tests[ name ]( bot.editor, bot ); + } ); + }; + } ); + } + + if ( !CKEDITOR.env.edge ) { + return bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); + } + + for ( test in tests ) { + if ( test.indexOf( 'test' ) === 0 ) { + generateTest( test ); + } + } + + return generatedTests; + } + function assertMenuItemsState( items, asserts ) { CKEDITOR.tools.array.forEach( items, function( item ) { if ( asserts[ item.command ] ) { @@ -186,6 +219,6 @@ } }; - tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); + tests = createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); bender.test( tests ); } )(); From 7a21b4eca66a6eca3e6a7a9d7c2da77e7602583f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Fri, 19 Jan 2018 14:23:34 +0100 Subject: [PATCH 287/642] Prevent caption flickering on focus. --- plugins/easyimage/styles/easyimage.css | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index 7dfda923cb1..d73354cbc16 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -11,7 +11,7 @@ For licensing, see LICENSE.md or http://ckeditor.com/license clear: both; } -/* +/* The outline is not a part of the element's dimensions, we have to use a border as an outline to align linked image with a caption. */ .easyimage a > img { @@ -39,6 +39,8 @@ The outline is not a part of the element's dimensions, we have to use a border a .easyimage .cke_widget_editable { background-color: #f7f7f7; + /* Add border so when caption is focused, blue border does not cause flickering. */ + border: 1px solid #f7f7f7; color: #333; padding: .8em; } @@ -49,7 +51,7 @@ The outline is not a part of the element's dimensions, we have to use a border a .cke_widget_wrapper .easyimage .cke_widget_editable.cke_widget_editable_focused { background-color: #fff; - border: 1px solid #48a3f5; + border-color: #48a3f5; outline: none; } @@ -65,4 +67,4 @@ The outline is not a part of the element's dimensions, we have to use a border a height: 10px; background: #6a9ed1; width: 0; -} \ No newline at end of file +} From 3af6b60efe632163c1426195f0f0da756e51a7e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Fri, 19 Jan 2018 15:30:23 +0100 Subject: [PATCH 288/642] Tests: caption flickering manual test. --- .../easyimage/manual/captionflickering.html | 49 +++++++++++++++++++ .../easyimage/manual/captionflickering.md | 13 +++++ 2 files changed, 62 insertions(+) create mode 100644 tests/plugins/easyimage/manual/captionflickering.html create mode 100644 tests/plugins/easyimage/manual/captionflickering.md diff --git a/tests/plugins/easyimage/manual/captionflickering.html b/tests/plugins/easyimage/manual/captionflickering.html new file mode 100644 index 00000000000..de483b02d74 --- /dev/null +++ b/tests/plugins/easyimage/manual/captionflickering.html @@ -0,0 +1,49 @@ +

Classic editor

+
+
+ foo +
Test image
+
+

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

+
+ foo +
Test image
+
+

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

+
+ +

Divarea editor

+
+
+ foo +
Test image
+
+

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

+
+ foo +
Test image
+
+

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

+
+ +

Inline editor

+
+
+ foo +
Test image
+
+

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

+
+ foo +
Test image
+
+

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

+
+ + diff --git a/tests/plugins/easyimage/manual/captionflickering.md b/tests/plugins/easyimage/manual/captionflickering.md new file mode 100644 index 00000000000..4e34860e7a1 --- /dev/null +++ b/tests/plugins/easyimage/manual/captionflickering.md @@ -0,0 +1,13 @@ +@bender-tags: 4.9.0, bug, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage + +## Caption flickering + +_Proceed with all editors_: + +1. Focus and blur caption of each image. + +## Expected + +Caption is not flickering, image and caption container does not change its size on focus or blur. From 955abe719cdc638744dd52c55c4808b805f06cd2 Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Mon, 29 Jan 2018 12:02:54 +0100 Subject: [PATCH 289/642] Update license header for files related to easyimage. --- dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt | 4 ++-- plugins/balloontoolbar/plugin.js | 2 +- plugins/balloontoolbar/skins/default.css | 2 +- plugins/balloontoolbar/skins/kama/balloontoolbar.css | 2 +- .../balloontoolbar/skins/moono-lisa/balloontoolbar.css | 2 +- plugins/balloontoolbar/skins/moono/balloontoolbar.css | 2 +- plugins/cloudservices/plugin.js | 6 +++--- plugins/easyimage/dialogs/easyimagealt.js | 4 ++-- plugins/easyimage/lang/en.js | 8 ++++---- plugins/easyimage/plugin.js | 4 ++-- plugins/easyimage/samples/easyimage.html | 4 ++-- plugins/easyimage/styles/easyimage.css | 4 ++-- plugins/imagebase/lang/en.js | 9 +++++---- plugins/imagebase/plugin.js | 4 ++-- 14 files changed, 29 insertions(+), 28 deletions(-) diff --git a/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt b/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt index 8e5d106c410..bf239264cd5 100644 --- a/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt +++ b/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt @@ -1,5 +1,5 @@ -# Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. -# For licensing, see LICENSE.md or http://ckeditor.com/license +# Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. +# For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license altText = Label for button converting image to assign an alternative text. fullImage = Label for button converting image to a full width. diff --git a/plugins/balloontoolbar/plugin.js b/plugins/balloontoolbar/plugin.js index 72fb8804a8e..afa6987cdbf 100644 --- a/plugins/balloontoolbar/plugin.js +++ b/plugins/balloontoolbar/plugin.js @@ -1,6 +1,6 @@ /** * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ ( function() { diff --git a/plugins/balloontoolbar/skins/default.css b/plugins/balloontoolbar/skins/default.css index 615357fe6e1..5e64da8b15e 100644 --- a/plugins/balloontoolbar/skins/default.css +++ b/plugins/balloontoolbar/skins/default.css @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or https://ckeditor.com/license +For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ .cke_balloon.cke_balloontoolbar diff --git a/plugins/balloontoolbar/skins/kama/balloontoolbar.css b/plugins/balloontoolbar/skins/kama/balloontoolbar.css index 7be62dfae49..a83aea1f168 100644 --- a/plugins/balloontoolbar/skins/kama/balloontoolbar.css +++ b/plugins/balloontoolbar/skins/kama/balloontoolbar.css @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license +For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ .cke_balloon.cke_balloontoolbar diff --git a/plugins/balloontoolbar/skins/moono-lisa/balloontoolbar.css b/plugins/balloontoolbar/skins/moono-lisa/balloontoolbar.css index d7a0e97dc8a..8c48d1ae9bf 100644 --- a/plugins/balloontoolbar/skins/moono-lisa/balloontoolbar.css +++ b/plugins/balloontoolbar/skins/moono-lisa/balloontoolbar.css @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license +For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ .cke_balloon.cke_balloontoolbar span:last-child a:last-child::after, diff --git a/plugins/balloontoolbar/skins/moono/balloontoolbar.css b/plugins/balloontoolbar/skins/moono/balloontoolbar.css index af8d13df1a9..a4a8a697712 100644 --- a/plugins/balloontoolbar/skins/moono/balloontoolbar.css +++ b/plugins/balloontoolbar/skins/moono/balloontoolbar.css @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license +For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ .cke_balloon.cke_balloontoolbar diff --git a/plugins/cloudservices/plugin.js b/plugins/cloudservices/plugin.js index e60db74aa21..1e99def5f6e 100644 --- a/plugins/cloudservices/plugin.js +++ b/plugins/cloudservices/plugin.js @@ -1,6 +1,6 @@ /** - * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license + * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ ( function() { @@ -134,4 +134,4 @@ * @cfg {String} [cloudServices_token=''] * @member CKEDITOR.config */ -} )(); \ No newline at end of file +} )(); diff --git a/plugins/easyimage/dialogs/easyimagealt.js b/plugins/easyimage/dialogs/easyimagealt.js index 87629f2f653..ceb103c8c93 100644 --- a/plugins/easyimage/dialogs/easyimagealt.js +++ b/plugins/easyimage/dialogs/easyimagealt.js @@ -1,6 +1,6 @@ /** - * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license + * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.dialog.add( 'easyimageAlt', function( editor ) { diff --git a/plugins/easyimage/lang/en.js b/plugins/easyimage/lang/en.js index 5b12eb14d03..f5f3d57dbcb 100644 --- a/plugins/easyimage/lang/en.js +++ b/plugins/easyimage/lang/en.js @@ -1,7 +1,7 @@ -/* -Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ +/** + * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ CKEDITOR.plugins.setLang( 'easyimage', 'en', { commands: { diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index ec32a150797..966e67dbdcd 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -1,6 +1,6 @@ /** - * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license + * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ ( function() { diff --git a/plugins/easyimage/samples/easyimage.html b/plugins/easyimage/samples/easyimage.html index fa5cc8aa09c..9506f22159c 100644 --- a/plugins/easyimage/samples/easyimage.html +++ b/plugins/easyimage/samples/easyimage.html @@ -1,7 +1,7 @@ diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index d73354cbc16..bb6997dab89 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -1,6 +1,6 @@ /* -Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license +Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ .easyimage, .cke_widget_wrapper_easyimage { diff --git a/plugins/imagebase/lang/en.js b/plugins/imagebase/lang/en.js index a31bd76c322..18ccf9a3e50 100644 --- a/plugins/imagebase/lang/en.js +++ b/plugins/imagebase/lang/en.js @@ -1,7 +1,8 @@ -/* -Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.md or http://ckeditor.com/license -*/ +/** + * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + CKEDITOR.plugins.setLang( 'imagebase', 'en', { captionPlaceholder: 'Caption' } ); diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 37ee6ab99af..0ca8701c990 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -1,6 +1,6 @@ /** - * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license + * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ ( function() { From b574104ea1c7ae39f79eb6db8bc0d953f98f1637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Mon, 29 Jan 2018 13:27:26 +0100 Subject: [PATCH 290/642] Update license header in easyimage sample. --- plugins/easyimage/samples/easyimage.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/samples/easyimage.html b/plugins/easyimage/samples/easyimage.html index 9506f22159c..6a6afb0cc23 100644 --- a/plugins/easyimage/samples/easyimage.html +++ b/plugins/easyimage/samples/easyimage.html @@ -66,7 +66,7 @@

Apollo 11

CKEditor – The text editor for the Internet – http://ckeditor.com

- Copyright © 2003-2017, CKSource – Frederico Knabben. All rights reserved. + Copyright © 2003-2018, CKSource – Frederico Knabben. All rights reserved.

From e4aa2d97f29bfd86f02429a238f444ac9ab3a857 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 16 Jan 2018 23:39:50 +0100 Subject: [PATCH 291/642] First mocks to get the new upload working. So far it's messy PoC concept with some logs and ugly commented code. --- plugins/easyimage/plugin.js | 6 ++- plugins/imagebase/plugin.js | 83 +++++++++++++++++++++++++++++++++---- 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 966e67dbdcd..60041134995 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -148,11 +148,13 @@ img: { attributes: '!src,srcset,alt,width,sizes' - } + }, }, requiredContent: 'figure; img[!src]', + supportedTypes: /image\/(jpeg|png|gif|bmp)/, + upcasts: { figure: function( element ) { if ( ( !figureClass || element.hasClass( figureClass ) ) && @@ -198,6 +200,8 @@ widgetDefinition = CKEDITOR.plugins.imagebase.addFeature( editor, 'link', widgetDefinition ); } + widgetDefinition = CKEDITOR.plugins.imagebase.addFeature( editor, 'upload', widgetDefinition ); + CKEDITOR.plugins.imagebase.addImageWidget( editor, 'easyimage', widgetDefinition ); } diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 0ca8701c990..e5f3810ab4e 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -186,17 +186,83 @@ }; } + function getUploadFeature() { + var ret = { + setUp: function( editor, definition ) { + console.log( 'added' ); + editor.on( 'paste', function( evt ) { + if ( evt.data.method === 'drop' ) { + console.log( 'dropped' ); + + var dataTransfer = evt.data.dataTransfer, + filesCount = dataTransfer.getFilesCount(), + blobUrls = [], + files = [], + curFile; + + console.log( definition ); + + for ( var i = 0; i < filesCount; i++ ) { + curFile = dataTransfer.getFile( i ); + + if ( CKEDITOR.fileTools.isTypeSupported( curFile, definition.supportedTypes ) ) { + files.push( curFile ); + blobUrls.push( URL.createObjectURL( curFile ) ); + } + } + + // Refetch the definition... original definition looks like an outdated copy, it doesn't things inherited form imagebase. + definition = editor.widgets.registered.easyimage; + + if ( files.length ) { + evt.cancel(); + // This should not be required, let's leave it for development time to make sure + // that nothing else affects the listeners: + evt.stop(); + + console.log( 'inserting the widget' ); + ret._insertWidget( editor, definition, files[ 0 ], blobUrls[ 0 ] ); + + // @todo: make sure balloon toolbar is repositioned once img[src="blob:*"] is loaded or at least its height is available. + } + + } else { + console.log( 'unsupported ' + evt.data.method + ' method.' ); + } + } ); + }, + _insertWidget: function( editor, widgetDef, file, blobUrl ) { + var defaults = ( typeof widgetDef.defaults == 'function' ? widgetDef.defaults() : widgetDef.defaults ) || { + src: blobUrl, + alt: '', + caption: '' + }, + element = CKEDITOR.dom.element.createFromHtml( widgetDef.template.output( defaults ) ), + wrapper = editor.widgets.wrapElement( element, widgetDef.name ), + temp = new CKEDITOR.dom.documentFragment( wrapper.getDocument() ), + instance; + + // Append wrapper to a temporary document. This will unify the environment + // in which #data listeners work when creating and editing widget. + temp.append( wrapper ); + instance = editor.widgets.initOn( element, widgetDef ); + + editor.widgets.finalizeCreation( temp ); + + console.log( 'done' ); + } + }; + + return ret; + } + var featuresDefinitions = { + upload: getUploadFeature(), link: getLinkFeature() }; function createWidgetDefinition( editor, definition ) { - var defaultTemplate = new CKEDITOR.template( - '
' + - '' + - '
{captionPlaceholder}
' + - '
' ), - baseDefinition; + var baseDefinition; /** * This is an abstract class that describes a definition of a basic image widget @@ -215,7 +281,10 @@ baseDefinition = { pathName: editor.lang.imagebase.pathName, - template: defaultTemplate, + template: '
' + + '{alt}' + + '
{captionPlaceholder}
' + + '
', allowedContent: { img: { From a3ce5f8db6d2746c249a0b78ac37a3570d37849f Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 17 Jan 2018 01:01:25 +0100 Subject: [PATCH 292/642] Another round of this fabolous (and dirty) PoC to bring reusable widget upload feature. --- plugins/easyimage/plugin.js | 2 + plugins/imagebase/plugin.js | 121 ++++++++++++++++++++++++++++++++---- plugins/widget/plugin.js | 2 + 3 files changed, 113 insertions(+), 12 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 60041134995..8e934a390bb 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -155,6 +155,8 @@ supportedTypes: /image\/(jpeg|png|gif|bmp)/, + loaderType: CKEDITOR.plugins.cloudservices.cloudServicesLoader, + upcasts: { figure: function( element ) { if ( ( !figureClass || element.hasClass( figureClass ) ) && diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index e5f3810ab4e..9149511d4b0 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -187,6 +187,21 @@ } function getUploadFeature() { + // Natural width of the image can be fetched only after image is loaded. + // However cached images won't fire `load` event, but just mark themselves + // as complete. + function getNaturalWidth( image, callback ) { + var $image = image.$; + + if ( $image.complete && $image.naturalWidth ) { + return callback( $image.naturalWidth ); + } + + image.once( 'load', function() { + callback( $image.naturalWidth ); + } ); + } + var ret = { setUp: function( editor, definition ) { console.log( 'added' ); @@ -221,9 +236,12 @@ evt.stop(); console.log( 'inserting the widget' ); - ret._insertWidget( editor, definition, files[ 0 ], blobUrls[ 0 ] ); + var widgetInstance = ret._insertWidget( editor, definition, files[ 0 ], blobUrls[ 0 ] ); + + ret._loadWidget( editor, widgetInstance, definition, files[ 0 ] ); // @todo: make sure balloon toolbar is repositioned once img[src="blob:*"] is loaded or at least its height is available. + // @todo: handle more than one dropped image } } else { @@ -231,13 +249,87 @@ } } ); }, + + init: function() { + // @todo: this code should be actually moved to easyimage (core) widget init function, as it's a EI plugin responsibility + // to tell exactly how the image should be loaded. + function setImageWidth( widget, height ) { + if ( !widget.parts.image.hasAttribute( 'width' ) ) { + widget.editor.fire( 'lockSnapshot' ); + + widget.parts.image.setAttribute( 'width', height ); + + widget.editor.fire( 'unlockSnapshot' ); + } + } + + this.on( 'uploadDone', function( evt ) { + var loader = evt.data.sender, + resp = loader.responseData.response; + + var srcset = CKEDITOR.plugins.easyimage._parseSrcSet( resp ), + widget = this; + + widget.parts.image.setAttributes( { + src: resp[ 'default' ], + srcset: srcset, + sizes: '100vw', + // @todo: currently there's a race condition, if the with has not been fetched for `img[blob:*]` it will not be set. + width: widget.parts.image.getAttribute( 'width' ) + } ); + + console.log( 'updated the image' ); + } ); + + this.on( 'uploadBegan', function() { + var widget = this; + // Attempt to pick width from the img[src="blob:*"]. + getNaturalWidth( widget.parts.image, function( width ) { + setImageWidth( widget, width ); + } ); + } ); + }, + + _loadWidget: function( editor, widget, def, file ) { + var uploads = editor.uploadRepository, + loadMethod = def.loadMethod || 'loadAndUpload', + loader = uploads.create( file, undefined, def.loaderType ); + + function failHandling( evt ) { + console.warn( 'Could not load Easy Image widget', evt ); + if ( widget.fire( 'uploadError', evt ) !== false ) { + widget.destroy( true ); + } + } + + function uploadComplete( evt ) { + console.log( 'all good, image uploaded' ); + + widget.fire( 'uploadDone', evt ); + } + + loader.on( 'abort', failHandling ); + loader.on( 'error', failHandling ); + loader.on( 'uploaded', uploadComplete ); + + loader[ loadMethod ]( def.uploadUrl, def.additionalRequestParameters ); + + widget.fire( 'uploadBegan', loader ); + + // @todo: It make sense to mark the widget at this point as incomplete. Similarly as fileTools.markElement does. + + if ( ( loadMethod == 'loadAndUpload' || loadMethod == 'upload' ) && !def.skipNotifications ) { + // Todo: bind notifications. + // CKEDITOR.fileTools.bindNotifications( editor, loader ); + } + }, + _insertWidget: function( editor, widgetDef, file, blobUrl ) { - var defaults = ( typeof widgetDef.defaults == 'function' ? widgetDef.defaults() : widgetDef.defaults ) || { - src: blobUrl, - alt: '', - caption: '' - }, - element = CKEDITOR.dom.element.createFromHtml( widgetDef.template.output( defaults ) ), + var tplParams = ( typeof widgetDef.defaults == 'function' ? widgetDef.defaults() : widgetDef.defaults ) || {}; + + tplParams.src = blobUrl; + + var element = CKEDITOR.dom.element.createFromHtml( widgetDef.template.output( tplParams ) ), wrapper = editor.widgets.wrapElement( element, widgetDef.name ), temp = new CKEDITOR.dom.documentFragment( wrapper.getDocument() ), instance; @@ -247,9 +339,7 @@ temp.append( wrapper ); instance = editor.widgets.initOn( element, widgetDef ); - editor.widgets.finalizeCreation( temp ); - - console.log( 'done' ); + return editor.widgets.finalizeCreation( temp ); } }; @@ -281,9 +371,16 @@ baseDefinition = { pathName: editor.lang.imagebase.pathName, - template: '
' + + defaults: { + imageClass: ( editor.config.easyimage_class || '' ), + alt: '', + src: '', + caption: '' + }, + + template: '
' + '{alt}' + - '
{captionPlaceholder}
' + + '
{caption}
' + '
', allowedContent: { diff --git a/plugins/widget/plugin.js b/plugins/widget/plugin.js index 08ad8da4afe..46c4d2fa7e3 100644 --- a/plugins/widget/plugin.js +++ b/plugins/widget/plugin.js @@ -438,6 +438,8 @@ widget.ready = true; widget.fire( 'ready' ); widget.focus(); + + return widget; } }, From 44dbff45095f677051ab73c62db366dcffe51487 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 17 Jan 2018 02:02:09 +0100 Subject: [PATCH 293/642] An attempt to integrate our custom EI progress bar with the upload widget feature. --- plugins/easyimage/plugin.js | 121 ++++++++++++++++++------- plugins/easyimage/styles/easyimage.css | 4 + 2 files changed, 91 insertions(+), 34 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 8e934a390bb..0f1d9eda4e8 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -176,6 +176,22 @@ if ( editor.config.easyimage_class ) { this.addClass( editor.config.easyimage_class ); } + + if ( !this.definition._createProgressBar ) { + // Do it only once. + mixinProgressBarToWidgetDef( this.definition ); + } + + this.on( 'uploadBegan', function( evt ) { + attachProgressBarToLoader( evt.data, this ); + } ); + + this.once( 'uploadDone', function( evt ) { + if ( this.parts.progressBar ) { + this.parts.progressBar.remove(); + this.parts.progressBar = null; + } + } ); }, data: function( evt ) { @@ -315,6 +331,74 @@ } ); } + function mixinProgressBarToWidgetDef( definition ) { + definition.parts.loader = '.cke_loader'; + + /* + * Creates a progress bar in a given widget. + * + * Also puts it in it's {@link CKEDITOR.plugins.widget#parts} structure as `progressBar` + * + * @private + * @param {CKEDITOR.plugins.widget} widget + */ + definition._createProgressBar = function( widget, progressBarWrapper ) { + progressBarWrapper = progressBarWrapper || widget.element; + + widget.parts.progressBar = CKEDITOR.dom.element.createFromHtml( '
' + + '
' + + '
' ); + + progressBarWrapper.append( widget.parts.progressBar, true ); + }; + } + + /* + * Attaches a progress bar to a given loader. + * + * @param {CKEDITOR.fileTools.fileLoader} loader + * @param {CKEDITOR.plugins.widget} widget + */ + function attachProgressBarToLoader( loader, widget ) { + var progressListeners = []; + + // Add a progress bar. + widget.definition._createProgressBar( widget ); + + function removeProgressListeners() { + if ( progressListeners ) { + CKEDITOR.tools.array.forEach( progressListeners, function( listener ) { + listener.removeListener(); + } ); + + progressListeners = null; + } + } + + var updateListener = CKEDITOR.tools.eventsBuffer( UPLOAD_PROGRESS_THROTTLING, function() { + if ( !widget.parts.progressBar ) { + return; + } + + var progressBar = widget.parts.progressBar.findOne( '.cke_bar' ), + percentage; + + if ( progressBar && loader.uploadTotal ) { + percentage = ( loader.uploaded / loader.uploadTotal ) * 100; + + widget.editor.fire( 'lockSnapshot' ); + progressBar.setStyle( 'width', percentage + '%' ); + widget.editor.fire( 'unlockSnapshot' ); + } + }, widget ); + + progressListeners.push( loader.on( 'update', updateListener.input ) ); + + progressListeners.push( loader.once( 'abort', removeProgressListeners ) ); + progressListeners.push( loader.once( 'error', removeProgressListeners ) ); + progressListeners.push( loader.once( 'uploaded', removeProgressListeners ) ); + } + // Extends given uploadWidget `definition` with an upload progress bar, added within wrapper. function addUploadProgressBar( editor, definition ) { definition.skipNotifications = true; @@ -330,7 +414,7 @@ */ definition._createProgressBar = function( widget ) { widget.parts.progressBar = CKEDITOR.dom.element.createFromHtml( '
' + - '
' + + '
' + '
' ); widget.wrapper.append( widget.parts.progressBar, true ); }; @@ -344,40 +428,9 @@ baseInit = definition.init; definition.init = function() { - var loader = this._getLoader( this ), - progressListeners = []; - - function removeProgressListeners() { - if ( progressListeners ) { - CKEDITOR.tools.array.forEach( progressListeners, function( listener ) { - listener.removeListener(); - } ); - - progressListeners = null; - } - } - - // Add a progress bar. - this.definition._createProgressBar( this ); - - var updateListener = CKEDITOR.tools.eventsBuffer( UPLOAD_PROGRESS_THROTTLING, function() { - var progressBar = this.parts.progressBar.findOne( '.cke_bar' ), - percentage; - - if ( progressBar && loader.uploadTotal ) { - percentage = ( loader.uploaded / loader.uploadTotal ) * 100; - - editor.fire( 'lockSnapshot' ); - progressBar.setStyle( 'width', percentage + '%' ); - editor.fire( 'unlockSnapshot' ); - } - }, this ); - - progressListeners.push( loader.on( 'update', updateListener.input ) ); + var loader = this._getLoader( this ); - progressListeners.push( loader.once( 'abort', removeProgressListeners ) ); - progressListeners.push( loader.once( 'error', removeProgressListeners ) ); - progressListeners.push( loader.once( 'uploaded', removeProgressListeners ) ); + attachProgressBarToLoader( this, loader ); // Call base init implementation. baseInit.call( this ); diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index bb6997dab89..3942117c690 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -57,6 +57,10 @@ The outline is not a part of the element's dimensions, we have to use a border a /* Loaders */ +.cke_widget_element.easyimage { + position: relative; +} + .cke_loader { position: absolute; left: 0px; From da24e0da6538d44ce63528cb0a0989b4fd3acfb4 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 17 Jan 2018 23:35:02 +0100 Subject: [PATCH 294/642] Added a ProgressBar type, so far it's going to be placed in Easy Image plugin.It's going to be extracted later. This type will be passed into Upload Widget Feature. The Idea is to have the ability to implement a different progress indicators for other widgets. --- plugins/imagebase/plugin.js | 82 +++++++++++- tests/plugins/easyimage/balloontoolbar.js | 152 ++++++++++++++++++++++ tests/plugins/imagebase/progressbar.html | 26 ++++ 3 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 tests/plugins/easyimage/balloontoolbar.js create mode 100644 tests/plugins/imagebase/progressbar.html diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 9149511d4b0..ff84d4b6823 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -437,6 +437,84 @@ return definition; } + var UPLOAD_PROGRESS_THROTTLING = 100; + + /** + * This is a base class for progress bars. + * + * Progress bars could be updated: + * + * * Automatically, by binding it to a existing {@link CKEDITOR.fileTools.fileLoader} instance. + * * Manually, using {@link #updated}, {@link #done}, {@link #failed} and {@link #aborted} methods. + * + * @class CKEDITOR.plugins.imagebase.progressBar + * @constructor + */ + function ProgressBar() { + /** + * @property {CKEDITOR.dom.element} wrapper An element created for wrapping the progress bar. + */ + this.wrapper = CKEDITOR.dom.element.createFromHtml( '
' + + '
' + + '
' ); + + this.bar = this.wrapper.getFirst(); + } + + /** + * @param {CKEDITOR.dom.element} wrapper Element where the progress bar will be **prepended**. + * @returns {CKEDITOR.plugins.imagebase.progressBar} + */ + ProgressBar.createForElement = function( wrapper ) { + var ret = new ProgressBar(); + + wrapper.append( ret.wrapper, true ); + + return ret; + }; + + ProgressBar.prototype = { + bindToLoader: function( loader ) { + // pass + }, + /** + * Marks a progress on the progress bar. + * + * @param {Number} progress Progress representation where `1.0` is a complete and `0` means no progress. + */ + updated: function( progress ) { + var percentage = Math.round( progress * 100 ); + + percentage = Math.max( percentage, 0 ); + percentage = Math.min( percentage, 100 ); + + // widget.editor.fire( 'lockSnapshot' ); + this.bar.setStyle( 'width', percentage + '%' ); + // widget.editor.fire( 'unlockSnapshot' ); + }, + + /** + * To be called when the progress should be marked as complete. + */ + done: function() { + this.wrapper.remove(); + }, + + /** + * To be called when the progress should be marked as aborted. + */ + aborted: function() { + this.failed(); + }, + + /** + * To be called when the progress should be marked as failed. + */ + failed: function() { + this.wrapper.remove(); + } + }; + CKEDITOR.plugins.add( 'imagebase', { requires: 'widget', lang: 'en' @@ -516,6 +594,8 @@ ret.features.push( name ); return ret; - } + }, + + progressBar: ProgressBar }; }() ); diff --git a/tests/plugins/easyimage/balloontoolbar.js b/tests/plugins/easyimage/balloontoolbar.js new file mode 100644 index 00000000000..c9813063323 --- /dev/null +++ b/tests/plugins/easyimage/balloontoolbar.js @@ -0,0 +1,152 @@ +/* bender-tags: editor,widget */ +/* bender-ckeditor-plugins: easyimage,toolbar,undo */ +/* bender-include: _helpers/tools.js */ +/* global easyImageTools */ + +( function() { + 'use strict'; + + bender.editors = { + classic: {}, + + divarea: { + config: { + extraPlugins: 'divarea' + } + }, + + inline: { + creator: 'inline' + } + }; + + function getEasyImageBalloonContext( editor ) { + return editor.balloonToolbars._contexts[ 0 ]; + } + + // Forces the Balloon Toolbar to be always drawn below the target. + function patchBalloonPositioning( toolbar ) { + var original = toolbar._view._getAlignments; + + toolbar._view._getAlignments = function() { + var ret = original.apply( this, arguments ); + + return { + 'bottom hcenter': ret[ 'bottom hcenter' ] + }; + }; + } + + /* + * Returns an expected balloon Y position for a given widget. + * + * @param {CKEDITOR.plugins.widget} widget + * @returns {Number} + */ + function getExpectedYOffset( widget ) { + var editor = widget.editor, + wrapperRect = widget.element.getClientRect(), + toolbar = getEasyImageBalloonContext( editor ).toolbar, + ret = wrapperRect.bottom + toolbar._view.triangleHeight; + + if ( !editor.editable().isInline() ) { + // In case of classic editor we also need to include position of the editor iframe too. + ret += editor.window.getFrame().getClientRect().top; + } + + return ret; + } + + var testSuiteIframe = CKEDITOR.document.getWindow().getFrame(), + initialFrameHeight = testSuiteIframe && testSuiteIframe.getStyle( 'height' ), + tests = { + setUp: function() { + // This test checks real balloon panel positioning. To avoid affecting position with scroll offset, set the parent iframe height + // enough to contain entire content. Note that iframe is not present if the test suite is open in a separate window, or ran on IEs. + if ( testSuiteIframe ) { + testSuiteIframe.setStyle( 'height', '3000px' ); + } + }, + + tearDown: function() { + if ( testSuiteIframe ) { + testSuiteIframe.setStyle( 'height', initialFrameHeight ); + } + }, + + 'test balloontoolbar integration': function( editor, bot ) { + var widgetHtml = '
foo
Test image
'; + + bot.setData( widgetHtml, function() { + var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ), + toolbar = getEasyImageBalloonContext( editor ).toolbar; + + toolbar._view.once( 'show', function() { + easyImageTools.assertCommandsState( editor, { + easyimageFull: CKEDITOR.TRISTATE_ON, + easyimageSide: CKEDITOR.TRISTATE_OFF, + easyimageAlt: CKEDITOR.TRISTATE_OFF + } ); + + editor.once( 'afterCommandExec', function() { + resume( function() { + easyImageTools.assertCommandsState( editor, { + easyimageFull: CKEDITOR.TRISTATE_OFF, + easyimageSide: CKEDITOR.TRISTATE_ON, + easyimageAlt: CKEDITOR.TRISTATE_OFF + } ); + } ); + } ); + + editor.execCommand( 'easyimageSide' ); + } ); + + widget.focus(); + wait(); + } ); + }, + + 'test balloontoolbar positioning': function( editor, bot ) { + var source = '
foo
'; + + bot.setData( source, function() { + var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ), + toolbar = getEasyImageBalloonContext( editor ).toolbar; + + patchBalloonPositioning( toolbar ); + + widget.once( 'focus', function() { + setTimeout( function() { + var expectedY = getExpectedYOffset( widget ), + moveSpy = sinon.spy( toolbar._view, 'move' ); + + widget.parts.caption.focus(); + + widget.focus(); + + setTimeout( function() { + resume( function() { + moveSpy.restore(); + // We care only about y axis. + var actual = moveSpy.args[ 0 ][ 0 ]; + + if ( CKEDITOR.env.ie && CKEDITOR.env.ie <= 11 ) { + // IE11 tends to be off by a fraction of a pixel on high DPI displays. + assert.isNumberInRange( actual, expectedY - 1, expectedY + 1, 'Balloon y position' ); + } else { + assert.areSame( expectedY, actual, 'Balloon y position' ); + } + } ); + }, 0 ); + }, 0 ); + } ); + + widget.focus(); + wait(); + } ); + } + }; + + tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); + bender.test( tests ); +} )(); diff --git a/tests/plugins/imagebase/progressbar.html b/tests/plugins/imagebase/progressbar.html new file mode 100644 index 00000000000..d1224b35e35 --- /dev/null +++ b/tests/plugins/imagebase/progressbar.html @@ -0,0 +1,26 @@ +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
From efb325e77c8eb6f574025ad97178376be059b285 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 18 Jan 2018 00:41:05 +0100 Subject: [PATCH 295/642] Generic loader integration for ProgressBar type. Added unit tests coverage. --- plugins/imagebase/plugin.js | 49 ++++++- tests/plugins/imagebase/progressbar.js | 194 +++++++++++++++++++++++++ 2 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 tests/plugins/imagebase/progressbar.js diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index ff84d4b6823..e08d7f89149 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -440,6 +440,9 @@ var UPLOAD_PROGRESS_THROTTLING = 100; /** + * + * @TODO: rename type to ProgressIndicator. Bar implies, well... bar. + * * This is a base class for progress bars. * * Progress bars could be updated: @@ -474,9 +477,6 @@ }; ProgressBar.prototype = { - bindToLoader: function( loader ) { - // pass - }, /** * Marks a progress on the progress bar. * @@ -512,7 +512,48 @@ */ failed: function() { this.wrapper.remove(); - } + }, + + /** + * Binds progress indicator to a given loader. + * + * It will automatically remove its listeners when the `loader` has triggered one of following events: + * + * * {@link CKEDITOR.fileTools.fileLoader#abort} + * * {@link CKEDITOR.fileTools.fileLoader#error} + * * {@link CKEDITOR.fileTools.fileLoader#uploaded} + * + * @param {CKEDITOR.fileTools.fileLoader} loader Loader that should be observed. + */ + bindToLoader: function( loader ) { + var progressListeners = []; + + function removeProgressListeners() { + if ( progressListeners ) { + CKEDITOR.tools.array.forEach( progressListeners, function( listener ) { + listener.removeListener(); + } ); + + progressListeners = null; + } + } + + var updateListener = CKEDITOR.tools.eventsBuffer( UPLOAD_PROGRESS_THROTTLING, function() { + if ( loader.uploadTotal ) { + this.updated( loader.uploaded / loader.uploadTotal ); + } + }, this ); + + progressListeners.push( loader.on( 'uploading', updateListener.input, this ) ); + progressListeners.push( loader.once( 'abort', this.aborted, this ) ); + progressListeners.push( loader.once( 'uploaded', this.done, this ) ); + progressListeners.push( loader.once( 'error', this.failed, this ) ); + + // Some events should cause all listeners to be removed. + progressListeners.push( loader.once( 'abort', removeProgressListeners ) ); + progressListeners.push( loader.once( 'uploaded', removeProgressListeners ) ); + progressListeners.push( loader.once( 'error', removeProgressListeners ) ); + }, }; CKEDITOR.plugins.add( 'imagebase', { diff --git a/tests/plugins/imagebase/progressbar.js b/tests/plugins/imagebase/progressbar.js new file mode 100644 index 00000000000..b5d711cb6de --- /dev/null +++ b/tests/plugins/imagebase/progressbar.js @@ -0,0 +1,194 @@ +/* bender-tags: editor */ +/* bender-ckeditor-plugins: imagebase */ + +( function() { + 'use strict'; + + var ProgressBar, + doc = CKEDITOR.document, + loaderMock = {}, + tests = { + init: function() { + ProgressBar = CKEDITOR.plugins.imagebase.progressBar; + + CKEDITOR.event.implementOn( loaderMock ); + + // Store the content of #nested-sandbox - it will be used to restore original HTML + // before each test case. + this.nestedSandbox = doc.getById( 'nested-sandbox' ); + this._nestedSandboxContent = this.nestedSandbox.getHtml(); + }, + + setUp: function() { + this.nestedSandbox.setHtml( this._nestedSandboxContent ); + + this.dummyProgress = new ProgressBar(); + + sinon.stub( this.dummyProgress, 'aborted' ); + sinon.stub( this.dummyProgress, 'done' ); + sinon.stub( this.dummyProgress, 'failed' ); + sinon.stub( this.dummyProgress, 'updated' ); + }, + + 'test createForElement()': function() { + var ret = ProgressBar.createForElement( this.nestedSandbox.findOne( '.nested2' ) ); + + assert.isInstanceOf( ProgressBar, ret, 'Returned type' ); + + assert.beautified.html( doc.getById( 'expected-create-from-element' ).getHtml(), this.nestedSandbox.getHtml() ); + }, + + 'test createForElement() creates proper elements': function() { + var ret = ProgressBar.createForElement( this.nestedSandbox.findOne( '.nested2' ) ); + + assert.areSame( this.nestedSandbox.findOne( '.cke_loader' ), ret.wrapper, 'ret.wrapper' ); + assert.areSame( this.nestedSandbox.findOne( '.cke_bar' ), ret.bar, 'ret.bar' ); + }, + + 'test createForElement() prepends the element': function() { + ProgressBar.createForElement( this.nestedSandbox ); + + assert.beautified.html( doc.getById( 'expected-create-from-element-prepend' ).getHtml(), this.nestedSandbox.getHtml() ); + }, + + 'test update()': function() { + var values = [ + [ 0.0, '0%' ], + [ 0.2, '20%' ], + [ 0.25, '25%' ], + [ 0.301, '30%' ], + [ 0.309, '31%' ], + [ 1.0, '100%' ], + [ -1.0, '0%' ], + [ 1.1, '100%' ] + ], + ret = ProgressBar.createForElement( this.nestedSandbox ); + + CKEDITOR.tools.array.forEach( values, function( assertSet ) { + ret.updated( assertSet[ 0 ] ); + assert.areSame( assertSet[ 1 ], ret.bar.getStyle( 'width', assertSet[ 0 ] ), 'Width for ' + assertSet[ 0 ] ); + } ) + }, + + // 'test update() locks the snapshot': function() { + // // todo + // }, + + 'test failed()': function() { + var ret = ProgressBar.createForElement( this.nestedSandbox ); + + ret.failed(); + + assert.isNull( ret.wrapper.getParent(), 'Parent element' ); + }, + + 'test aborted()': function() { + var ret = ProgressBar.createForElement( this.nestedSandbox ); + + ret.aborted(); + + assert.isNull( ret.wrapper.getParent(), 'Parent element' ); + }, + + 'test done()': function() { + var ret = ProgressBar.createForElement( this.nestedSandbox ); + + ret.done(); + + assert.isNull( ret.wrapper.getParent(), 'Parent element' ); + }, + + 'test bindToLoader() abort event removes listeners': function() { + this.dummyProgress.bindToLoader( loaderMock ); + + loaderMock.fire( 'abort' ); + + sinon.assert.calledOnce( this.dummyProgress.aborted ); + sinon.assert.calledOn( this.dummyProgress.aborted, this.dummyProgress ); + + // Subsequent calls should not result with more calls. + loaderMock.fire( 'abort' ); + loaderMock.fire( 'abort' ); + + assert.areSame( 1, this.dummyProgress.aborted.callCount, 'Aborted call count' ); + + // Uploaded event should not trigger done too. + loaderMock.fire( 'uploaded' ); + assert.areSame( 0, this.dummyProgress.done.callCount, 'Done call count' ); + }, + + 'test bindToLoader() uploaded event removes listeners': function() { + this.dummyProgress.bindToLoader( loaderMock ); + + loaderMock.fire( 'uploaded' ); + + sinon.assert.calledOnce( this.dummyProgress.done ); + sinon.assert.calledOn( this.dummyProgress.done, this.dummyProgress ); + + // Subsequent calls should not result with more calls. + loaderMock.fire( 'uploaded' ); + loaderMock.fire( 'uploaded' ); + + assert.areSame( 1, this.dummyProgress.done.callCount, 'Done call count' ); + }, + + 'test bindToLoader() uploading event is throttled': function() { + this.dummyProgress.bindToLoader( loaderMock ); + // Make sure that if file loader spams uploading events, progress does not go crazy. + + loaderMock.fire( 'uploading' ); + loaderMock.fire( 'uploading' ); + loaderMock.fire( 'uploading' ); + loaderMock.fire( 'uploading' ); + + assert.areSame( 1, this.dummyProgress.updated.callCount, 'Updated call count' ); + }, + + 'test bindToLoader() uploading event is throttled': function() { + this.dummyProgress.bindToLoader( loaderMock ); + // Make sure that if file loader spams uploading events, progress does not go crazy. + + loaderMock.uploadTotal = 5; + + loaderMock.fire( 'uploading' ); + loaderMock.fire( 'uploading' ); + loaderMock.fire( 'uploading' ); + + delete loaderMock.uploadTotal; + + assert.areSame( 1, this.dummyProgress.updated.callCount, 'Updated call count' ); + }, + + 'test bindToLoader() uploading argument translation': function() { + this.dummyProgress.bindToLoader( loaderMock ); + + loaderMock.uploaded = 3; + loaderMock.uploadTotal = 5; + + loaderMock.fire( 'uploading' ); + + delete loaderMock.uploaded; + delete loaderMock.uploadTotal; + + sinon.assert.calledWithExactly( this.dummyProgress.updated, 0.6 ); + assert.areSame( 1, this.dummyProgress.updated.callCount, 'Call count' ); + }, + + 'test bindToLoader() error event removes listeners': function() { + this.dummyProgress.bindToLoader( loaderMock ); + + loaderMock.fire( 'error' ); + + sinon.assert.calledOnce( this.dummyProgress.failed ); + sinon.assert.calledOn( this.dummyProgress.failed, this.dummyProgress ); + + // Subsequent calls should not result with more calls. + loaderMock.fire( 'error' ); + loaderMock.fire( 'error' ); + + assert.areSame( 1, this.dummyProgress.failed.callCount, 'Failed call count' ); + } + }; + + bender.test( tests ); +} )(); From 3bf94fb715cffbc1a75bb27d578e9bb50f61b2c3 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 18 Jan 2018 01:29:01 +0100 Subject: [PATCH 296/642] Added ProgressBar#remove and a basic manual test. --- plugins/imagebase/plugin.js | 9 +- .../plugins/imagebase/manual/progressbar.html | 89 +++++++++++++++++++ tests/plugins/imagebase/manual/progressbar.md | 9 ++ tests/plugins/imagebase/progressbar.js | 8 ++ 4 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 tests/plugins/imagebase/manual/progressbar.html create mode 100644 tests/plugins/imagebase/manual/progressbar.md diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index e08d7f89149..c83f169559a 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -504,7 +504,7 @@ * To be called when the progress should be marked as aborted. */ aborted: function() { - this.failed(); + this.remove(); }, /** @@ -514,6 +514,13 @@ this.wrapper.remove(); }, + /** + * Removes the progress indicator from DOM. + */ + remove: function() { + this.wrapper.remove(); + }, + /** * Binds progress indicator to a given loader. * diff --git a/tests/plugins/imagebase/manual/progressbar.html b/tests/plugins/imagebase/manual/progressbar.html new file mode 100644 index 00000000000..529563e53c2 --- /dev/null +++ b/tests/plugins/imagebase/manual/progressbar.html @@ -0,0 +1,89 @@ +
+
+

line

+

line

+

line

+
+

Above div will gain your progress indicator.

+
+ + + + + + diff --git a/tests/plugins/imagebase/manual/progressbar.md b/tests/plugins/imagebase/manual/progressbar.md new file mode 100644 index 00000000000..f69d3eede93 --- /dev/null +++ b/tests/plugins/imagebase/manual/progressbar.md @@ -0,0 +1,9 @@ +@bender-tags: 4.9.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: wysiwygarea, imagebase + +# Progress Indicator + +The progress bar should be drawn within a green div inside of the editor. + +Use inputs below the editor to control the state of progress bar. See how it reacts. \ No newline at end of file diff --git a/tests/plugins/imagebase/progressbar.js b/tests/plugins/imagebase/progressbar.js index b5d711cb6de..baa3ee8c697 100644 --- a/tests/plugins/imagebase/progressbar.js +++ b/tests/plugins/imagebase/progressbar.js @@ -51,6 +51,14 @@ assert.beautified.html( doc.getById( 'expected-create-from-element-prepend' ).getHtml(), this.nestedSandbox.getHtml() ); }, + 'test remove()': function() { + var ret = ProgressBar.createForElement( this.nestedSandbox ); + + ret.remove(); + + assert.isNull( ret.wrapper.getParent(), 'Parent node' ); + }, + 'test update()': function() { var values = [ [ 0.0, '0%' ], From 5950c71101d88ee9f3f3ae7025511df6ff1acd0b Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 18 Jan 2018 01:52:54 +0100 Subject: [PATCH 297/642] Tests: implemented a different type of progress indicator in manual test. --- .../plugins/imagebase/manual/progressbar.html | 61 ++++++++++++++++--- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/tests/plugins/imagebase/manual/progressbar.html b/tests/plugins/imagebase/manual/progressbar.html index 529563e53c2..7ec93ca25da 100644 --- a/tests/plugins/imagebase/manual/progressbar.html +++ b/tests/plugins/imagebase/manual/progressbar.html @@ -1,5 +1,6 @@
-
+
+

line

line

line

line

@@ -16,6 +17,20 @@ width: 100%; } + .progress-range-legend { + position: relative; + height: 1em; + } + + .progress-range-legend span { + position: absolute; + top: 0px; + } + + .progress-range-legend .done { + right: 0px; + } + + diff --git a/tests/plugins/easyimage/manual/customprogressbar.md b/tests/plugins/easyimage/manual/customprogressbar.md new file mode 100644 index 00000000000..2c2e7e3a9bc --- /dev/null +++ b/tests/plugins/easyimage/manual/customprogressbar.md @@ -0,0 +1,19 @@ +@bender-tags: 4.9.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: wysiwygarea, easyimage, autogrow + +# Custom Progress + +This manual test shows an example of different progress indicators. + +1. Drag and drop any image file into "Default progress bar" editor. +1. Observe progress indicator. + ## Expected + + Progress indicator matches editor name and is different from other editors. +1. Repeat above steps for remaining editors. + + +Note: it might not work on **Edge** due to an [upstream bug](https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12224510/). + +Pro tip: you might want to [use browser throttling](https://developers.google.com/web/tools/chrome-devtools/network-performance/reference?hl=en#throttling) to make uploads longer. \ No newline at end of file diff --git a/tests/plugins/imagebase/manual/progressbar.html b/tests/plugins/imagebase/manual/progressbar.html index 7ec93ca25da..eeeecc1d7fd 100644 --- a/tests/plugins/imagebase/manual/progressbar.html +++ b/tests/plugins/imagebase/manual/progressbar.html @@ -62,38 +62,19 @@

+ + diff --git a/tests/plugins/imagebase/features/manual/upload.md b/tests/plugins/imagebase/features/manual/upload.md new file mode 100644 index 00000000000..7f95e6eed8a --- /dev/null +++ b/tests/plugins/imagebase/features/manual/upload.md @@ -0,0 +1,15 @@ +@bender-tags: 4.9.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: wysiwygarea, toolbar, imagebase, elementspath, placeholder, cloudservices + +## Upload Feature + +1. Drop any file from your file system to the editable. + +## Expected + +A placeholder widget is created, containing file name. + +**Note:** at the time of writing Cloud Service accepts only images, and return `400` code for any other resource type. + +_If you're truly curious about the actual URL returned by Cloud Services, you can find it in console log._ \ No newline at end of file From 2f38b6a001d4a2fbf85a91824cd0607e478c2f02 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 21 Jan 2018 13:31:17 +0100 Subject: [PATCH 323/642] Tests: extracted common assertion. --- tests/plugins/easyimage/uploadintegrations.js | 261 +++---- .../imagebase/features/_helpers/tools.js | 48 ++ tests/plugins/imagebase/features/upload.js | 695 +++++++++--------- 3 files changed, 487 insertions(+), 517 deletions(-) create mode 100644 tests/plugins/imagebase/features/_helpers/tools.js diff --git a/tests/plugins/easyimage/uploadintegrations.js b/tests/plugins/easyimage/uploadintegrations.js index bfa9cb0d284..de3698ba287 100644 --- a/tests/plugins/easyimage/uploadintegrations.js +++ b/tests/plugins/easyimage/uploadintegrations.js @@ -1,167 +1,128 @@ /* bender-tags: editor, clipboard, upload */ /* bender-ckeditor-plugins: sourcearea, wysiwygarea, easyimage */ -/* bender-include: %BASE_PATH%/plugins/clipboard/_helpers/pasting.js */ -/* global pasteFiles */ +/* bender-include: %BASE_PATH%/plugins/clipboard/_helpers/pasting.js, %BASE_PATH%/plugins/imagebase/features/_helpers/tools.js */ +/* global imageBaseFeaturesTools */ ( function() { 'use strict'; bender.editor = true; - function objToArray( obj ) { - var tools = CKEDITOR.tools; - - return tools.array.map( tools.objectKeys( obj ), function( key ) { - return obj[ key ]; - } ); - } - // Loader mock that successes asynchronously. function AsyncSuccessFileLoader( editor, fileOrData, fileName ) { CKEDITOR.fileTools.fileLoader.call( this, editor, fileOrData, fileName ); } - var tests = { - init: function() { - var sampleCloudServicesResponse = { - 210: '%BASE_PATH%/_assets/logo.png?w=210', - 420: '%BASE_PATH%/_assets/logo.png?w=420', - 630: '%BASE_PATH%/_assets/logo.png?w=630', - 840: '%BASE_PATH%/_assets/logo.png?w=840', - 1050: '%BASE_PATH%/_assets/logo.png?w=1050', - 1260: '%BASE_PATH%/_assets/logo.png?w=1260', - 1470: '%BASE_PATH%/_assets/logo.png?w=1470', - 1680: '%BASE_PATH%/_assets/logo.png?w=1680', - 1890: '%BASE_PATH%/_assets/logo.png?w=1890', - 2048: '%BASE_PATH%/_assets/logo.png?w=2048', - 'default': '%BASE_PATH%/_assets/logo.png' - }; - - // Array of listeners to be cleared after each TC. - this.listeners = []; - - this.editor.widgets.registered.easyimage.loaderType = AsyncSuccessFileLoader; - - this.editor.on( 'fileUploadResponse', function( evt ) { - // Prevent this guy from picking up https://github.com/ckeditor/ckeditor-dev/blob/565d9c3a3613f35167d6555123b6ca316ead7ab9/plugins/filetools/plugin.js#L93-L122 - // it would complain about missing uploaded/error properties. - evt.cancel(); - }, null, null, 5 ); - - AsyncSuccessFileLoader.prototype = CKEDITOR.tools.extend( { - upload: function() { - var that = this; - - setTimeout( function() { - that.changeStatus( 'uploading' ); - }, 0 ); - - setTimeout( function() { - that.update(); - }, 200 ); - - setTimeout( function() { - that.update(); - }, 400 ); - - setTimeout( function() { - var evtData = { - sender: that - }; - - that.responseData = { - response: sampleCloudServicesResponse - }; - - that.editor.fire( 'fileUploadResponse', evtData ); - that.changeStatus( 'uploaded' ); - }, 1000 ); - } - }, CKEDITOR.fileTools.fileLoader.prototype ); - }, - - tearDown: function() { - // Clean up the listeners so it doesn't affect subsequent tests. - CKEDITOR.tools.array.forEach( this.listeners, function( listener ) { - listener.removeListener(); - } ); - - this.editor.widgets.destroyAll( true ); - - this.listeners = []; - this.editor.uploadRepository.loaders = []; - }, - - setUp: function() { - this.editorBot.setHtmlWithSelection( '

^

' ); - }, - - // To test - edge case: changing mode during upload. - 'test nothing explodes when upload finishes in a different mode': function() { - var editor = this.editor, - disposableListeners = this.listeners; - - this._assertPasteFiles( editor, { - files: [ bender.tools.getTestPngFile() ], - callback: function( widgets ) { - assert.areSame( 1, widgets.length, 'Widgets count' ); - - var doneSpy = sinon.spy(); - disposableListeners.push( widgets[ 0 ].on( 'uploadDone', doneSpy ) ); - - editor.setMode( 'source', function() { - resume( function() { - // It's unlikely, but theoretically possible that upload will complete before - // the mode is changed. Inform about this case. - assert.isFalse( doneSpy.called, 'Race condition didn\'t occur' ); - - disposableListeners.push( widgets[ 0 ].once( 'uploadDone', function() { - resume( function() { - assert.isTrue( true ); - } ); - } ) ); - - wait(); + var assertPasteFiles = imageBaseFeaturesTools.assertPasteFiles, + tests = { + init: function() { + var sampleCloudServicesResponse = { + 210: '%BASE_PATH%/_assets/logo.png?w=210', + 420: '%BASE_PATH%/_assets/logo.png?w=420', + 630: '%BASE_PATH%/_assets/logo.png?w=630', + 840: '%BASE_PATH%/_assets/logo.png?w=840', + 1050: '%BASE_PATH%/_assets/logo.png?w=1050', + 1260: '%BASE_PATH%/_assets/logo.png?w=1260', + 1470: '%BASE_PATH%/_assets/logo.png?w=1470', + 1680: '%BASE_PATH%/_assets/logo.png?w=1680', + 1890: '%BASE_PATH%/_assets/logo.png?w=1890', + 2048: '%BASE_PATH%/_assets/logo.png?w=2048', + 'default': '%BASE_PATH%/_assets/logo.png' + }; + + // Array of listeners to be cleared after each TC. + this.listeners = []; + + this.editor.widgets.registered.easyimage.loaderType = AsyncSuccessFileLoader; + + this.editor.on( 'fileUploadResponse', function( evt ) { + // Prevent this guy from picking up https://github.com/ckeditor/ckeditor-dev/blob/565d9c3a3613f35167d6555123b6ca316ead7ab9/plugins/filetools/plugin.js#L93-L122 + // it would complain about missing uploaded/error properties. + evt.cancel(); + }, null, null, 5 ); + + AsyncSuccessFileLoader.prototype = CKEDITOR.tools.extend( { + upload: function() { + var that = this; + + setTimeout( function() { + that.changeStatus( 'uploading' ); + }, 0 ); + + setTimeout( function() { + that.update(); + }, 200 ); + + setTimeout( function() { + that.update(); + }, 400 ); + + setTimeout( function() { + var evtData = { + sender: that + }; + + that.responseData = { + response: sampleCloudServicesResponse + }; + + that.editor.fire( 'fileUploadResponse', evtData ); + that.changeStatus( 'uploaded' ); + }, 1000 ); + } + }, CKEDITOR.fileTools.fileLoader.prototype ); + }, + + tearDown: function() { + // Clean up the listeners so it doesn't affect subsequent tests. + CKEDITOR.tools.array.forEach( this.listeners, function( listener ) { + listener.removeListener(); + } ); + + this.editor.widgets.destroyAll( true ); + + this.listeners = []; + this.editor.uploadRepository.loaders = []; + }, + + setUp: function() { + this.editorBot.setHtmlWithSelection( '

^

' ); + }, + + // To test - edge case: changing mode during upload. + 'test nothing explodes when upload finishes in a different mode': function() { + var editor = this.editor, + disposableListeners = this.listeners; + + assertPasteFiles( editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function( widgets ) { + assert.areSame( 1, widgets.length, 'Widgets count' ); + + var doneSpy = sinon.spy(); + disposableListeners.push( widgets[ 0 ].on( 'uploadDone', doneSpy ) ); + + editor.setMode( 'source', function() { + resume( function() { + // It's unlikely, but theoretically possible that upload will complete before + // the mode is changed. Inform about this case. + assert.isFalse( doneSpy.called, 'Race condition didn\'t occur' ); + + disposableListeners.push( widgets[ 0 ].once( 'uploadDone', function() { + resume( function() { + assert.isTrue( true ); + } ); + } ) ); + + wait(); + } ); } ); - } ); - - wait(); - } - } ); - }, - - /* - * Main assertion for pasting files. - * - * @param {CKEDITOR.editor} editor - * @param {Object} options - * @param {File[]} [options.files=[]] Files to be dropped. - * @param {Function} options.callback Function to be called after the paste event. - * Params: - * - * * `CKEDITOR.plugins.widget[]` widgets - Array of widgets in a given editor. - * * `CKEDITOR.eventInfo` evt - Paste event. - */ - _assertPasteFiles: function( editor, options ) { - var files = options.files || [], - callback = options.callback; - - editor.once( 'paste', function( evt ) { - // Unfortunately at the time being we need to do additional timeout here, as - // the paste event gets cancelled. - setTimeout( function() { - resume( function() { - callback( objToArray( editor.widgets.instances ), evt ); - } ); - }, 0 ); - }, null, null, -1 ); - - - pasteFiles( editor, files ); - - wait(); - } - }; + + wait(); + } + } ); + } + }; bender.test( tests ); } )(); diff --git a/tests/plugins/imagebase/features/_helpers/tools.js b/tests/plugins/imagebase/features/_helpers/tools.js new file mode 100644 index 00000000000..f8bc4af30fb --- /dev/null +++ b/tests/plugins/imagebase/features/_helpers/tools.js @@ -0,0 +1,48 @@ +/* exported imageBaseFeaturesTools */ +/* global pasteFiles */ + +( function() { + 'use strict'; + + function objToArray( obj ) { + var tools = CKEDITOR.tools; + + return tools.array.map( tools.objectKeys( obj ), function( key ) { + return obj[ key ]; + } ); + } + + window.imageBaseFeaturesTools = { + /* + * Main assertion for pasting files. + * + * @param {CKEDITOR.editor} editor + * @param {Object} options + * @param {File[]} [options.files=[]] Files to be dropped. + * @param {Function} options.callback Function to be called after the paste event. + * Params: + * + * * `CKEDITOR.plugins.widget[]` widgets - Array of widgets in a given editor. + * * `CKEDITOR.eventInfo` evt - Paste event. + */ + assertPasteFiles: function( editor, options ) { + var files = options.files || [], + callback = options.callback; + + editor.once( 'paste', function( evt ) { + // Unfortunately at the time being we need to do additional timeout here, as + // the paste event gets cancelled. + setTimeout( function() { + resume( function() { + callback( objToArray( editor.widgets.instances ), evt ); + } ); + }, 0 ); + }, null, null, -1 ); + + // pasteFiles is defined in filetools plugin helper. + pasteFiles( editor, files ); + + wait(); + } + }; +} )(); diff --git a/tests/plugins/imagebase/features/upload.js b/tests/plugins/imagebase/features/upload.js index fc64a6d3e84..16c7caff741 100644 --- a/tests/plugins/imagebase/features/upload.js +++ b/tests/plugins/imagebase/features/upload.js @@ -1,21 +1,13 @@ /* bender-tags: editor, clipboard, upload */ /* bender-ckeditor-plugins: imagebase */ -/* bender-include: %BASE_PATH%/plugins/clipboard/_helpers/pasting.js */ -/* global pasteFiles */ +/* bender-include: %BASE_PATH%/plugins/clipboard/_helpers/pasting.js, _helpers/tools.js */ +/* global imageBaseFeaturesTools */ ( function() { 'use strict'; bender.editor = true; - function objToArray( obj ) { - var tools = CKEDITOR.tools; - - return tools.array.map( tools.objectKeys( obj ), function( key ) { - return obj[ key ]; - } ); - } - function getTestHtmlFile( fileName ) { var file = bender.tools.srcToFile( 'data:text/html;base64,Zm9v' ); file.name = fileName ? fileName : 'name.html'; @@ -32,365 +24,334 @@ CKEDITOR.fileTools.fileLoader.call( this, editor, fileOrData, fileName ); } - var tests = { - init: function() { - var plugin = CKEDITOR.plugins.imagebase, - editor = this.editor, - imageWidgetDef = { - name: 'testImageWidget', - supportedTypes: /image\/(jpeg|png)/, - loaderType: SuccessFileLoader - }, - textWidgetDef = { - name: 'testTextWidget', - supportedTypes: /text\/plain/, - loaderType: SuccessFileLoader - }; - - // Array of listeners to be cleared after each TC. - this.listeners = []; - this.sandbox = sinon.sandbox.create(); - - plugin.addImageWidget( editor, imageWidgetDef.name, plugin.addFeature( editor, 'upload', imageWidgetDef ) ); - - plugin.addImageWidget( editor, textWidgetDef.name, plugin.addFeature( editor, 'upload', textWidgetDef ) ); - - SuccessFileLoader.prototype = CKEDITOR.tools.extend( { - upload: function() { - this.changeStatus( 'uploaded' ); - } - }, CKEDITOR.fileTools.fileLoader.prototype ); - - FailFileLoader.prototype = CKEDITOR.tools.extend( { - upload: function() { - this.changeStatus( 'error' ); - } - }, CKEDITOR.fileTools.fileLoader.prototype ); - }, - - tearDown: function() { - // Clean up the listeners so it doesn't affect subsequent tests. - CKEDITOR.tools.array.forEach( this.listeners, function( listener ) { - listener.removeListener(); - } ); - - this.sandbox.restore(); - this.editor.widgets.destroyAll( true ); - - this.listeners = []; - this.editor.uploadRepository.loaders = []; - }, - - setUp: function() { - this.editorBot.setHtmlWithSelection( '

^

' ); - }, - - // To test - test mixed dropped files types (e.g. 1 image, 1 text, 1 unsupported). - - 'test dropping supported file type creates a widget': function() { - var editor = this.editor; - - this._assertPasteFiles( editor, { - files: [ bender.tools.getTestPngFile() ], - callback: function( widgets ) { - assert.areSame( 1, widgets.length, 'Widgets count' ); - assert.areSame( widgets[ 0 ].name, 'testImageWidget', 'Widget name' ); - } - } ); - }, - - 'test dropping unsupported file does not create a widget': function() { - var editor = this.editor; - - this._assertPasteFiles( editor, { - files: [ getTestHtmlFile() ], - callback: function( widgets ) { - assert.areSame( 0, widgets.length, 'Widgets count' ); - } - } ); - }, - - 'test multiple files create multiple widgets': function() { - var editor = this.editor; - - this._assertPasteFiles( editor, { - files: [ - bender.tools.getTestPngFile(), - bender.tools.getTestPngFile(), - bender.tools.getTestPngFile() - ], - callback: function( widgets ) { - assert.areSame( 3, widgets.length, 'Widgets count' ); - assert.areSame( widgets[ 0 ].name, 'testImageWidget', 'Widget 0 name' ); - assert.areSame( widgets[ 1 ].name, 'testImageWidget', 'Widget 1 name' ); - assert.areSame( widgets[ 2 ].name, 'testImageWidget', 'Widget 2 name' ); - } - } ); - }, - - 'test loader can be customized': function() { - var editor = this.editor, - originalLoader = editor.widgets.registered.testImageWidget.loaderType, - CustomDummyType = sinon.spy( SuccessFileLoader ); - - // Force a dummy loader. - editor.widgets.registered.testImageWidget.loaderType = CustomDummyType; - - this._assertPasteFiles( editor, { - files: [ bender.tools.getTestPngFile() ], - callback: function() { - // Restore original loader. - editor.widgets.registered.testImageWidget.loaderType = originalLoader; - - assert.areSame( 1, CustomDummyType.callCount, 'CustomDummyType constructor calls' ); - } - } ); - }, - - 'test events': function() { - var editor = this.editor, - stubs = { - uploadBegan: sinon.stub(), - uploadDone: sinon.stub(), - uploadFailed: sinon.stub() - }, - that = this; - - this.listeners.push( editor.widgets.on( 'instanceCreated', function( evt ) { - // Add spies to the widget. - for ( var i in stubs ) { - that.listeners.push( evt.data.on( i, stubs[ i ] ) ); - } - } ) ); - - this._assertPasteFiles( editor, { - files: [ bender.tools.getTestPngFile() ], - callback: function() { - assert.areSame( 1, stubs.uploadBegan.callCount, 'uploadBegan event count' ); - sinon.assert.calledWithExactly( stubs.uploadBegan, sinon.match.has( 'data', editor.uploadRepository.loaders[ 0 ] ) ); - - assert.areSame( 1, stubs.uploadDone.callCount, 'uploadDone event count' ); - - assert.areSame( 0, stubs.uploadFailed.callCount, 'uploadFailed event count' ); - } - } ); - }, - - 'test upload error': function() { - var editor = this.editor, - stubs = { - uploadBegan: sinon.stub(), - uploadDone: sinon.stub(), - uploadFailed: sinon.stub() - }, - that = this, - originalLoader = editor.widgets.registered.testImageWidget.loaderType; - - // Force a loader that will fail. - editor.widgets.registered.testImageWidget.loaderType = FailFileLoader; - - this.listeners.push( editor.widgets.on( 'instanceCreated', function( evt ) { - // Add spies to the widget. - for ( var i in stubs ) { - that.listeners.push( evt.data.on( i, stubs[ i ] ) ); - } - } ) ); - - this._assertPasteFiles( editor, { - files: [ bender.tools.getTestPngFile() ], - callback: function( widgets ) { - // Restore original loader. - editor.widgets.registered.testImageWidget.loaderType = originalLoader; - - var loaderInstance = editor.uploadRepository.loaders[ 0 ]; - - assert.areSame( 1, stubs.uploadBegan.callCount, 'uploadBegan event count' ); - sinon.assert.calledWithExactly( stubs.uploadBegan, sinon.match.has( 'data', loaderInstance ) ); - - assert.areSame( 0, stubs.uploadDone.callCount, 'uploadDone event count' ); - - assert.areSame( 1, stubs.uploadFailed.callCount, 'uploadFailed event count' ); - assert.areSame( loaderInstance, stubs.uploadFailed.args[ 0 ][ 0 ].data.sender, 'Event data.sender' ); - - assert.areSame( 0, widgets.length, 'Widget count' ); - } - } ); - }, - - 'test upload error event is cancelable': function() { - var editor = this.editor, - that = this, - originalLoader = editor.widgets.registered.testImageWidget.loaderType; - - // Force a loader that will fail. - editor.widgets.registered.testImageWidget.loaderType = FailFileLoader; - - this.listeners.push( editor.widgets.on( 'instanceCreated', function( evt ) { - that.listeners.push( evt.data.on( 'uploadFailed', function( evt ) { - evt.cancel(); + var assertPasteFiles = imageBaseFeaturesTools.assertPasteFiles, + tests = { + init: function() { + var plugin = CKEDITOR.plugins.imagebase, + editor = this.editor, + imageWidgetDef = { + name: 'testImageWidget', + supportedTypes: /image\/(jpeg|png)/, + loaderType: SuccessFileLoader + }, + textWidgetDef = { + name: 'testTextWidget', + supportedTypes: /text\/plain/, + loaderType: SuccessFileLoader + }; + + // Array of listeners to be cleared after each TC. + this.listeners = []; + this.sandbox = sinon.sandbox.create(); + + plugin.addImageWidget( editor, imageWidgetDef.name, plugin.addFeature( editor, 'upload', imageWidgetDef ) ); + + plugin.addImageWidget( editor, textWidgetDef.name, plugin.addFeature( editor, 'upload', textWidgetDef ) ); + + SuccessFileLoader.prototype = CKEDITOR.tools.extend( { + upload: function() { + this.changeStatus( 'uploaded' ); + } + }, CKEDITOR.fileTools.fileLoader.prototype ); + + FailFileLoader.prototype = CKEDITOR.tools.extend( { + upload: function() { + this.changeStatus( 'error' ); + } + }, CKEDITOR.fileTools.fileLoader.prototype ); + }, + + tearDown: function() { + // Clean up the listeners so it doesn't affect subsequent tests. + CKEDITOR.tools.array.forEach( this.listeners, function( listener ) { + listener.removeListener(); + } ); + + this.sandbox.restore(); + this.editor.widgets.destroyAll( true ); + + this.listeners = []; + this.editor.uploadRepository.loaders = []; + }, + + setUp: function() { + this.editorBot.setHtmlWithSelection( '

^

' ); + }, + + // To test - test mixed dropped files types (e.g. 1 image, 1 text, 1 unsupported). + + 'test dropping supported file type creates a widget': function() { + var editor = this.editor; + + assertPasteFiles( editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function( widgets ) { + assert.areSame( 1, widgets.length, 'Widgets count' ); + assert.areSame( widgets[ 0 ].name, 'testImageWidget', 'Widget name' ); + } + } ); + }, + + 'test dropping unsupported file does not create a widget': function() { + var editor = this.editor; + + assertPasteFiles( editor, { + files: [ getTestHtmlFile() ], + callback: function( widgets ) { + assert.areSame( 0, widgets.length, 'Widgets count' ); + } + } ); + }, + + 'test multiple files create multiple widgets': function() { + var editor = this.editor; + + assertPasteFiles( editor, { + files: [ + bender.tools.getTestPngFile(), + bender.tools.getTestPngFile(), + bender.tools.getTestPngFile() + ], + callback: function( widgets ) { + assert.areSame( 3, widgets.length, 'Widgets count' ); + assert.areSame( widgets[ 0 ].name, 'testImageWidget', 'Widget 0 name' ); + assert.areSame( widgets[ 1 ].name, 'testImageWidget', 'Widget 1 name' ); + assert.areSame( widgets[ 2 ].name, 'testImageWidget', 'Widget 2 name' ); + } + } ); + }, + + 'test loader can be customized': function() { + var editor = this.editor, + originalLoader = editor.widgets.registered.testImageWidget.loaderType, + CustomDummyType = sinon.spy( SuccessFileLoader ); + + // Force a dummy loader. + editor.widgets.registered.testImageWidget.loaderType = CustomDummyType; + + assertPasteFiles( editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function() { + // Restore original loader. + editor.widgets.registered.testImageWidget.loaderType = originalLoader; + + assert.areSame( 1, CustomDummyType.callCount, 'CustomDummyType constructor calls' ); + } + } ); + }, + + 'test events': function() { + var editor = this.editor, + stubs = { + uploadBegan: sinon.stub(), + uploadDone: sinon.stub(), + uploadFailed: sinon.stub() + }, + that = this; + + this.listeners.push( editor.widgets.on( 'instanceCreated', function( evt ) { + // Add spies to the widget. + for ( var i in stubs ) { + that.listeners.push( evt.data.on( i, stubs[ i ] ) ); + } } ) ); - } ) ); - - this._assertPasteFiles( editor, { - files: [ bender.tools.getTestPngFile() ], - callback: function( widgets ) { - editor.widgets.registered.testImageWidget.loaderType = originalLoader; - - assert.areSame( 1, widgets.length, 'Widget was not removed' ); - } - } ); - }, - - 'test widgets can coexist side by side': function() { - // In other tests we're using image widget, if text widget works it means they work side - // by side just fine. - var editor = this.editor; - - this._assertPasteFiles( editor, { - files: [ bender.tools.getTestTxtFile() ], - callback: function( widgets ) { - assert.areSame( 1, widgets.length, 'Widgets count' ); - assert.areSame( 'testTextWidget', widgets[ 0 ].name, 'Widget name' ); - } - } ); - }, - - 'test default progress reporter': function() { - var imageBase = CKEDITOR.plugins.imagebase, - createForElementSpy = this.sandbox.spy( imageBase.progressBar, 'createForElement' ), - bindLoaderSpy = this.sandbox.spy( imageBase.progressBar.prototype, 'bindLoader' ), - editor = this.editor; - - this._assertPasteFiles( this.editor, { - files: [ bender.tools.getTestPngFile() ], - callback: function( widgets ) { - assert.areSame( 1, createForElementSpy.callCount, 'ProgressBar.createForElement call count' ); - - sinon.assert.calledWithExactly( createForElementSpy, widgets[ 0 ].element ); - - sinon.assert.calledWithExactly( bindLoaderSpy, editor.uploadRepository.loaders[ 0 ] ); - } - } ); - }, - - 'test progress reporter customization': function() { - var CustomProgress = this.sandbox.spy( CKEDITOR.plugins.imagebase, 'progressBar' ), - widgetDefinition = this.editor.widgets.registered.testImageWidget, - originalProgress = widgetDefinition.progressIndicatorType; - - CustomProgress.createForElement = sinon.spy( function() { - return new CustomProgress(); - } ); - - widgetDefinition.progressIndicatorType = CustomProgress; - - - this._assertPasteFiles( this.editor, { - files: [ bender.tools.getTestPngFile() ], - callback: function() { - widgetDefinition.progressIndicatorType = originalProgress; - - assert.areSame( 1, CustomProgress.callCount, 'ProgressBar.createForElement call count' ); - } - } ); - }, - - 'test preventing default progress reporter with event': function() { - // This test is a bit tricky, we need to add a new widget so that we can hook to widget.init method because - // widget#instanceCreated event is fired too late for this assertion. - var imageBase = CKEDITOR.plugins.imagebase, - createForElementSpy = this.sandbox.spy( imageBase.progressBar, 'createForElement' ), - editor = this.editor, - disposableListeners = this.listeners, - def = { - name: 'progressPrevent', - supportedTypes: /text\/html/, - init: function() { - disposableListeners.push( this.on( 'uploadBegan', function( evt ) { - evt.cancel(); - } ) ); + + assertPasteFiles( editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function() { + assert.areSame( 1, stubs.uploadBegan.callCount, 'uploadBegan event count' ); + sinon.assert.calledWithExactly( stubs.uploadBegan, sinon.match.has( 'data', editor.uploadRepository.loaders[ 0 ] ) ); + + assert.areSame( 1, stubs.uploadDone.callCount, 'uploadDone event count' ); + + assert.areSame( 0, stubs.uploadFailed.callCount, 'uploadFailed event count' ); + } + } ); + }, + + 'test upload error': function() { + var editor = this.editor, + stubs = { + uploadBegan: sinon.stub(), + uploadDone: sinon.stub(), + uploadFailed: sinon.stub() + }, + that = this, + originalLoader = editor.widgets.registered.testImageWidget.loaderType; + + // Force a loader that will fail. + editor.widgets.registered.testImageWidget.loaderType = FailFileLoader; + + this.listeners.push( editor.widgets.on( 'instanceCreated', function( evt ) { + // Add spies to the widget. + for ( var i in stubs ) { + that.listeners.push( evt.data.on( i, stubs[ i ] ) ); + } + } ) ); + + assertPasteFiles( editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function( widgets ) { + // Restore original loader. + editor.widgets.registered.testImageWidget.loaderType = originalLoader; + + var loaderInstance = editor.uploadRepository.loaders[ 0 ]; + + assert.areSame( 1, stubs.uploadBegan.callCount, 'uploadBegan event count' ); + sinon.assert.calledWithExactly( stubs.uploadBegan, sinon.match.has( 'data', loaderInstance ) ); + + assert.areSame( 0, stubs.uploadDone.callCount, 'uploadDone event count' ); + + assert.areSame( 1, stubs.uploadFailed.callCount, 'uploadFailed event count' ); + assert.areSame( loaderInstance, stubs.uploadFailed.args[ 0 ][ 0 ].data.sender, 'Event data.sender' ); + + assert.areSame( 0, widgets.length, 'Widget count' ); + } + } ); + }, + + 'test upload error event is cancelable': function() { + var editor = this.editor, + that = this, + originalLoader = editor.widgets.registered.testImageWidget.loaderType; + + // Force a loader that will fail. + editor.widgets.registered.testImageWidget.loaderType = FailFileLoader; + + this.listeners.push( editor.widgets.on( 'instanceCreated', function( evt ) { + that.listeners.push( evt.data.on( 'uploadFailed', function( evt ) { + evt.cancel(); + } ) ); + } ) ); + + assertPasteFiles( editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function( widgets ) { + editor.widgets.registered.testImageWidget.loaderType = originalLoader; + + assert.areSame( 1, widgets.length, 'Widget was not removed' ); + } + } ); + }, + + 'test widgets can coexist side by side': function() { + // In other tests we're using image widget, if text widget works it means they work side + // by side just fine. + var editor = this.editor; + + assertPasteFiles( editor, { + files: [ bender.tools.getTestTxtFile() ], + callback: function( widgets ) { + assert.areSame( 1, widgets.length, 'Widgets count' ); + assert.areSame( 'testTextWidget', widgets[ 0 ].name, 'Widget name' ); + } + } ); + }, + + 'test default progress reporter': function() { + var imageBase = CKEDITOR.plugins.imagebase, + createForElementSpy = this.sandbox.spy( imageBase.progressBar, 'createForElement' ), + bindLoaderSpy = this.sandbox.spy( imageBase.progressBar.prototype, 'bindLoader' ), + editor = this.editor; + + assertPasteFiles( this.editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function( widgets ) { + assert.areSame( 1, createForElementSpy.callCount, 'ProgressBar.createForElement call count' ); + + sinon.assert.calledWithExactly( createForElementSpy, widgets[ 0 ].element ); + + sinon.assert.calledWithExactly( bindLoaderSpy, editor.uploadRepository.loaders[ 0 ] ); + } + } ); + }, + + 'test progress reporter customization': function() { + var CustomProgress = this.sandbox.spy( CKEDITOR.plugins.imagebase, 'progressBar' ), + widgetDefinition = this.editor.widgets.registered.testImageWidget, + originalProgress = widgetDefinition.progressIndicatorType; + + CustomProgress.createForElement = sinon.spy( function() { + return new CustomProgress(); + } ); + + widgetDefinition.progressIndicatorType = CustomProgress; + + + assertPasteFiles( this.editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function() { + widgetDefinition.progressIndicatorType = originalProgress; + + assert.areSame( 1, CustomProgress.callCount, 'ProgressBar.createForElement call count' ); + } + } ); + }, + + 'test preventing default progress reporter with event': function() { + // This test is a bit tricky, we need to add a new widget so that we can hook to widget.init method because + // widget#instanceCreated event is fired too late for this assertion. + var imageBase = CKEDITOR.plugins.imagebase, + createForElementSpy = this.sandbox.spy( imageBase.progressBar, 'createForElement' ), + editor = this.editor, + disposableListeners = this.listeners, + def = { + name: 'progressPrevent', + supportedTypes: /text\/html/, + init: function() { + disposableListeners.push( this.on( 'uploadBegan', function( evt ) { + evt.cancel(); + } ) ); + } + }; + + imageBase.addImageWidget( editor, def.name, imageBase.addFeature( editor, 'upload', def ) ); + + assertPasteFiles( editor, { + files: [ getTestHtmlFile() ], + callback: function() { + // Remove progressPrevent widget, not to affect other test cases. + editor.widgets.destroyAll( true ); + delete editor.widgets.registered.progressPrevent; + + assert.areSame( 0, createForElementSpy.callCount, 'ProgressBar.createForElement call count' ); + } + } ); + }, + + 'test preventing default progress reporter with widgetDefinition.progressIndicatorType': function() { + var createForElementSpy = this.sandbox.spy( CKEDITOR.plugins.imagebase.progressBar, 'createForElement' ), + widgetDefinition = this.editor.widgets.registered.testImageWidget, + originalProgress = widgetDefinition.progressIndicatorType; + + // Setting to null will disable loading bar. + widgetDefinition.progressIndicatorType = null; + + assertPasteFiles( this.editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function() { + widgetDefinition.progressIndicatorType = originalProgress; + + assert.areSame( 0, createForElementSpy.callCount, 'ProgressBar.createForElement call count' ); + } + } ); + }, + + 'test dropping file into a readonly does not create a widget': function() { + var editor = this.editor; + + editor.setReadOnly( true ); + + assertPasteFiles( editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function( widgets ) { + editor.setReadOnly( false ); + + assert.areSame( 0, widgets.length, 'Widgets count' ); } - }; - - imageBase.addImageWidget( editor, def.name, imageBase.addFeature( editor, 'upload', def ) ); - - this._assertPasteFiles( editor, { - files: [ getTestHtmlFile() ], - callback: function() { - // Remove progressPrevent widget, not to affect other test cases. - editor.widgets.destroyAll( true ); - delete editor.widgets.registered.progressPrevent; - - assert.areSame( 0, createForElementSpy.callCount, 'ProgressBar.createForElement call count' ); - } - } ); - }, - - 'test preventing default progress reporter with widgetDefinition.progressIndicatorType': function() { - var createForElementSpy = this.sandbox.spy( CKEDITOR.plugins.imagebase.progressBar, 'createForElement' ), - widgetDefinition = this.editor.widgets.registered.testImageWidget, - originalProgress = widgetDefinition.progressIndicatorType; - - // Setting to null will disable loading bar. - widgetDefinition.progressIndicatorType = null; - - this._assertPasteFiles( this.editor, { - files: [ bender.tools.getTestPngFile() ], - callback: function() { - widgetDefinition.progressIndicatorType = originalProgress; - - assert.areSame( 0, createForElementSpy.callCount, 'ProgressBar.createForElement call count' ); - } - } ); - }, - - 'test dropping file into a readonly does not create a widget': function() { - var editor = this.editor; - - editor.setReadOnly( true ); - - this._assertPasteFiles( editor, { - files: [ bender.tools.getTestPngFile() ], - callback: function( widgets ) { - editor.setReadOnly( false ); - - assert.areSame( 0, widgets.length, 'Widgets count' ); - } - } ); - }, - - /* - * Main assertion for pasting files. - * - * @param {CKEDITOR.editor} editor - * @param {Object} options - * @param {File[]} [options.files=[]] Files to be dropped. - * @param {Function} options.callback Function to be called after the paste event. - * Params: - * - * * `CKEDITOR.plugins.widget[]` widgets - Array of widgets in a given editor. - * * `CKEDITOR.eventInfo` evt - Paste event. - */ - _assertPasteFiles: function( editor, options ) { - var files = options.files || [], - callback = options.callback; - - editor.once( 'paste', function( evt ) { - // Unfortunately at the time being we need to do additional timeout here, as - // the paste event gets cancelled. - setTimeout( function() { - resume( function() { - callback( objToArray( editor.widgets.instances ), evt ); - } ); - }, 0 ); - }, null, null, -1 ); - - - pasteFiles( editor, files ); - - wait(); - } - }; + } ); + } + }; bender.test( tests ); } )(); From 1bf08cd77bdf7929cca050676c9e67c2e726537e Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 21 Jan 2018 21:57:48 +0100 Subject: [PATCH 324/642] Major API change in ProgressReporter types: removed static createForElement(), progress bar is now stored directly in the widget wrapper (so that it doesnt leak to output). First: static createForElement() was not really a greatest idea in terms of DX. When extending the ProgressReporter type it required to reimplement it - mostly without any change other than changing the returned type. Instead one should simply create it using constructor, and then manually put the wrapper where they see it fit. Second: Placing inside a wrapper rather than element makes more sense, so it's being placed where the widget "guts" are. However this caused some styling issues it looks like people implementing the progress bars will have to pay attention to styling. --- plugins/easyimage/styles/easyimage.css | 13 +++++ plugins/imagebase/plugin.js | 16 +----- .../easyimage/manual/_helpers/tools.js | 36 ++++--------- .../plugins/easyimage/uploadintegrations.html | 7 +++ tests/plugins/easyimage/uploadintegrations.js | 28 ++++++++-- tests/plugins/imagebase/features/upload.js | 30 +++++------ .../plugins/imagebase/manual/progressbar.html | 3 +- tests/plugins/imagebase/progressbar.html | 18 ------- tests/plugins/imagebase/progressbar.js | 51 +++++++++---------- 9 files changed, 96 insertions(+), 106 deletions(-) create mode 100644 tests/plugins/easyimage/uploadintegrations.html diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index 3942117c690..dfe0832f714 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -21,6 +21,12 @@ The outline is not a part of the element's dimensions, we have to use a border a padding: 1px; } +.cke_widget_wrapper_easyimage figure { + margin-top: 0px; + margin-left: 40px; + margin-right: 40px; +} + .easyimage img, .cke_widget_uploadeasyimage img { display: block; height: auto; @@ -63,6 +69,7 @@ The outline is not a part of the element's dimensions, we have to use a border a .cke_loader { position: absolute; + top: 0px; left: 0px; right: 0px; } @@ -72,3 +79,9 @@ The outline is not a part of the element's dimensions, we have to use a border a background: #6a9ed1; width: 0; } + +/* It's important to have top, left, right in sync with figure margins, to algin the loader nicely. */ +.cke_widget_wrapper_easyimage .cke_loader { + left: 40px; + right: 40px; +} diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 575c6d0bd85..0445a58abaa 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -267,7 +267,8 @@ loader[ loadMethod ]( def.uploadUrl, def.additionalRequestParameters ); if ( widget.fire( 'uploadBegan', loader ) !== false && widget.progressIndicatorType ) { - var progress = widget.progressIndicatorType.createForElement( widget.element ); + var progress = new widget.progressIndicatorType(); + widget.wrapper.append( progress.wrapper ); progress.bindLoader( loader ); } @@ -527,19 +528,6 @@ this.bar = this.wrapper.getFirst(); } - /** - * @static - * @param {CKEDITOR.dom.element} wrapper Element where the progress bar will be **prepended**. - * @returns {CKEDITOR.plugins.imagebase.progressBar} - */ - ProgressBar.createForElement = function( wrapper ) { - var ret = new ProgressBar(); - - wrapper.append( ret.wrapper, true ); - - return ret; - }; - ProgressBar.prototype = new ProgressReporter(); ProgressReporter.prototype.updated = function( progress ) { diff --git a/tests/plugins/easyimage/manual/_helpers/tools.js b/tests/plugins/easyimage/manual/_helpers/tools.js index bfd1dccc471..cc189e9ba7a 100644 --- a/tests/plugins/easyimage/manual/_helpers/tools.js +++ b/tests/plugins/easyimage/manual/_helpers/tools.js @@ -50,37 +50,27 @@ var easyImageTools = { * on a image, and removes it indicating the progress. * * @param {CKEDITOR.editor} editor - * @param {Function} ProgressBar Base type for progress indicator - * {@link CKEDITOR.plugins.imageBase.progressBar}. + * @param {Function} ProgressReporter Base type for progress indicator + * {@link CKEDITOR.plugins.imageBase.progressReporter}. * @returns {Function} */ - getProgressOverlapType: function( editor, ProgressBar ) { + getProgressOverlapType: function( editor, ProgressReporter ) { if ( this._cache.ProgressOverlap ) { return this._cache.ProgressOverlap; } - function ProgressOverlap( totalHeight ) { - ProgressBar.call( this ); + function ProgressOverlap() { + ProgressReporter.call( this ); this.wrapper.addClass( 'cke_progress_overlap' ); - - this.totalHeight = totalHeight; } - ProgressOverlap.prototype = new ProgressBar(); + ProgressOverlap.prototype = new ProgressReporter(); ProgressOverlap.prototype.updated = function( progress ) { this.wrapper.setStyle( 'height', 100 - Math.round( progress * 100 ) + '%' ); }; - ProgressOverlap.createForElement = function( wrapper ) { - var ret = new ProgressOverlap( wrapper.getClientRect().height ); - - wrapper.append( ret.wrapper, true ); - - return ret; - }; - this._cache.ProgressOverlap = ProgressOverlap; return ProgressOverlap; @@ -92,7 +82,7 @@ var easyImageTools = { * * @returns {Function} */ - getProgressCircleType: function( editor, ProgressBar ) { + getProgressCircleType: function( editor, ProgressReporter ) { if ( this._cache.ProgressCircle ) { return this._cache.ProgressCircle; } @@ -117,7 +107,7 @@ var easyImageTools = { ' ' + '
' ); - ProgressBar.call( this ); + ProgressReporter.call( this ); this.wrapper.addClass( 'cke_progress_circle' ); @@ -134,7 +124,7 @@ var easyImageTools = { this.wrapper.append( this.circle ); } - ProgressCircle.prototype = new ProgressBar(); + ProgressCircle.prototype = new ProgressReporter(); ProgressCircle.prototype.updated = function( progress ) { var percentage = Math.round( progress * 100 ), @@ -146,14 +136,6 @@ var easyImageTools = { this.circle.data( 'pct', percentage ); }; - ProgressCircle.createForElement = function( wrapper ) { - var ret = new ProgressCircle(); - - wrapper.append( ret.wrapper, true ); - - return ret; - }; - this._cache.ProgressCircle = ProgressCircle; return ProgressCircle; diff --git a/tests/plugins/easyimage/uploadintegrations.html b/tests/plugins/easyimage/uploadintegrations.html new file mode 100644 index 00000000000..07008a87af6 --- /dev/null +++ b/tests/plugins/easyimage/uploadintegrations.html @@ -0,0 +1,7 @@ +
+
+ +
+
+

 

+
\ No newline at end of file diff --git a/tests/plugins/easyimage/uploadintegrations.js b/tests/plugins/easyimage/uploadintegrations.js index de3698ba287..819f15559aa 100644 --- a/tests/plugins/easyimage/uploadintegrations.js +++ b/tests/plugins/easyimage/uploadintegrations.js @@ -6,7 +6,12 @@ ( function() { 'use strict'; - bender.editor = true; + bender.editor = { + config: { + // Disable ACF, we want to catch any uncontrolled junk. + allwoedContent: true + } + }; // Loader mock that successes asynchronously. function AsyncSuccessFileLoader( editor, fileOrData, fileName ) { @@ -32,6 +37,7 @@ // Array of listeners to be cleared after each TC. this.listeners = []; + this.sandbox = sinon.sandbox.create(); this.editor.widgets.registered.easyimage.loaderType = AsyncSuccessFileLoader; @@ -79,6 +85,7 @@ listener.removeListener(); } ); + this.sandbox.restore(); this.editor.widgets.destroyAll( true ); this.listeners = []; @@ -89,6 +96,19 @@ this.editorBot.setHtmlWithSelection( '

^

' ); }, + 'test downcast does not include progress bar': function() { + var editor = this.editor; + + this.sandbox.stub( URL, 'createObjectURL' ).returns( '%BASE_PATH%_assets/logo.png' ); + + assertPasteFiles( editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function() { + assert.beautified.html( CKEDITOR.document.getById( 'expected-progress-bar-downcast' ).getHtml(), editor.getData() ); + } + } ); + }, + // To test - edge case: changing mode during upload. 'test nothing explodes when upload finishes in a different mode': function() { var editor = this.editor, @@ -109,8 +129,10 @@ assert.isFalse( doneSpy.called, 'Race condition didn\'t occur' ); disposableListeners.push( widgets[ 0 ].once( 'uploadDone', function() { - resume( function() { - assert.isTrue( true ); + editor.setMode( 'wysiwyg', function() { + resume( function() { + assert.isTrue( true ); + } ); } ); } ) ); diff --git a/tests/plugins/imagebase/features/upload.js b/tests/plugins/imagebase/features/upload.js index 16c7caff741..eac1c4b1b40 100644 --- a/tests/plugins/imagebase/features/upload.js +++ b/tests/plugins/imagebase/features/upload.js @@ -44,6 +44,8 @@ this.listeners = []; this.sandbox = sinon.sandbox.create(); + this.ProgressBarSpy = sinon.spy( plugin, 'progressBar' ); + plugin.addImageWidget( editor, imageWidgetDef.name, plugin.addFeature( editor, 'upload', imageWidgetDef ) ); plugin.addImageWidget( editor, textWidgetDef.name, plugin.addFeature( editor, 'upload', textWidgetDef ) ); @@ -68,6 +70,7 @@ } ); this.sandbox.restore(); + this.ProgressBarSpy.reset(); this.editor.widgets.destroyAll( true ); this.listeners = []; @@ -250,16 +253,14 @@ 'test default progress reporter': function() { var imageBase = CKEDITOR.plugins.imagebase, - createForElementSpy = this.sandbox.spy( imageBase.progressBar, 'createForElement' ), + ProgressBarSpy = this.sandbox.spy( this.editor.widgets.registered.testImageWidget, 'progressIndicatorType' ), bindLoaderSpy = this.sandbox.spy( imageBase.progressBar.prototype, 'bindLoader' ), editor = this.editor; assertPasteFiles( this.editor, { files: [ bender.tools.getTestPngFile() ], - callback: function( widgets ) { - assert.areSame( 1, createForElementSpy.callCount, 'ProgressBar.createForElement call count' ); - - sinon.assert.calledWithExactly( createForElementSpy, widgets[ 0 ].element ); + callback: function() { + assert.areSame( 1, ProgressBarSpy.callCount, 'ProgressBar constructor call count' ); sinon.assert.calledWithExactly( bindLoaderSpy, editor.uploadRepository.loaders[ 0 ] ); } @@ -267,23 +268,20 @@ }, 'test progress reporter customization': function() { - var CustomProgress = this.sandbox.spy( CKEDITOR.plugins.imagebase, 'progressBar' ), + var CustomProgress = sinon.spy( CKEDITOR.plugins.imagebase.progressBar ), widgetDefinition = this.editor.widgets.registered.testImageWidget, originalProgress = widgetDefinition.progressIndicatorType; - CustomProgress.createForElement = sinon.spy( function() { - return new CustomProgress(); - } ); + CustomProgress.prototype = new CKEDITOR.plugins.imagebase.progressBar(); widgetDefinition.progressIndicatorType = CustomProgress; - assertPasteFiles( this.editor, { files: [ bender.tools.getTestPngFile() ], callback: function() { widgetDefinition.progressIndicatorType = originalProgress; - assert.areSame( 1, CustomProgress.callCount, 'ProgressBar.createForElement call count' ); + assert.areSame( 1, CustomProgress.callCount, 'CustomProgress constructor call count' ); } } ); }, @@ -292,7 +290,7 @@ // This test is a bit tricky, we need to add a new widget so that we can hook to widget.init method because // widget#instanceCreated event is fired too late for this assertion. var imageBase = CKEDITOR.plugins.imagebase, - createForElementSpy = this.sandbox.spy( imageBase.progressBar, 'createForElement' ), + ProgressBarSpy = this.ProgressBarSpy, editor = this.editor, disposableListeners = this.listeners, def = { @@ -307,6 +305,8 @@ imageBase.addImageWidget( editor, def.name, imageBase.addFeature( editor, 'upload', def ) ); + editor.widgets.registered.progressPrevent.progressIndicatorType = ProgressBarSpy; + assertPasteFiles( editor, { files: [ getTestHtmlFile() ], callback: function() { @@ -314,13 +314,13 @@ editor.widgets.destroyAll( true ); delete editor.widgets.registered.progressPrevent; - assert.areSame( 0, createForElementSpy.callCount, 'ProgressBar.createForElement call count' ); + assert.areSame( 0, ProgressBarSpy.callCount, 'ProgressBar constructor call count' ); } } ); }, 'test preventing default progress reporter with widgetDefinition.progressIndicatorType': function() { - var createForElementSpy = this.sandbox.spy( CKEDITOR.plugins.imagebase.progressBar, 'createForElement' ), + var ProgressBarSpy = this.ProgressBarSpy, widgetDefinition = this.editor.widgets.registered.testImageWidget, originalProgress = widgetDefinition.progressIndicatorType; @@ -332,7 +332,7 @@ callback: function() { widgetDefinition.progressIndicatorType = originalProgress; - assert.areSame( 0, createForElementSpy.callCount, 'ProgressBar.createForElement call count' ); + assert.areSame( 0, ProgressBarSpy.callCount, 'ProgressBar constructor call count' ); } } ); }, diff --git a/tests/plugins/imagebase/manual/progressbar.html b/tests/plugins/imagebase/manual/progressbar.html index 41fa288e02b..f85b259bbed 100644 --- a/tests/plugins/imagebase/manual/progressbar.html +++ b/tests/plugins/imagebase/manual/progressbar.html @@ -83,7 +83,8 @@ loader.remove(); } - loader = Constructor.createForElement( editor.editable().findOne( 'div' ) ); + loader = new Constructor(); + editor.editable().findOne( 'div' ).append( loader.wrapper, true ); loader.updated( CKEDITOR.document.getById( 'progress-range' ).getValue() ); window.gLoader = loader; diff --git a/tests/plugins/imagebase/progressbar.html b/tests/plugins/imagebase/progressbar.html index d1224b35e35..9f58ea28e8c 100644 --- a/tests/plugins/imagebase/progressbar.html +++ b/tests/plugins/imagebase/progressbar.html @@ -1,26 +1,8 @@
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
diff --git a/tests/plugins/imagebase/progressbar.js b/tests/plugins/imagebase/progressbar.js index 052bd9c911b..f87d7d02669 100644 --- a/tests/plugins/imagebase/progressbar.js +++ b/tests/plugins/imagebase/progressbar.js @@ -13,14 +13,11 @@ CKEDITOR.event.implementOn( loaderMock ); - // Store the content of #nested-sandbox - it will be used to restore original HTML - // before each test case. - this.nestedSandbox = doc.getById( 'nested-sandbox' ); - this._nestedSandboxContent = this.nestedSandbox.getHtml(); + this.sandbox = doc.getById( 'sandbox' ); }, setUp: function() { - this.nestedSandbox.setHtml( this._nestedSandboxContent ); + this.sandbox.setHtml( '' ); this.dummyProgress = new ProgressBar(); @@ -30,29 +27,20 @@ sinon.stub( this.dummyProgress, 'updated' ); }, - 'test createForElement()': function() { - var ret = ProgressBar.createForElement( this.nestedSandbox.findOne( '.nested2' ) ); + 'test constructor creates proper elements': function() { + var ret = new ProgressBar(); + this.sandbox.append( ret.wrapper, true ); - assert.isInstanceOf( ProgressBar, ret, 'Returned type' ); + assert.areSame( this.sandbox.findOne( '.cke_loader' ), ret.wrapper, 'ret.wrapper' ); + assert.areSame( this.sandbox.findOne( '.cke_bar' ), ret.bar, 'ret.bar' ); - assert.beautified.html( doc.getById( 'expected-create-from-element' ).getHtml(), this.nestedSandbox.getHtml() ); - }, - - 'test createForElement() creates proper elements': function() { - var ret = ProgressBar.createForElement( this.nestedSandbox.findOne( '.nested2' ) ); - - assert.areSame( this.nestedSandbox.findOne( '.cke_loader' ), ret.wrapper, 'ret.wrapper' ); - assert.areSame( this.nestedSandbox.findOne( '.cke_bar' ), ret.bar, 'ret.bar' ); - }, - - 'test createForElement() prepends the element': function() { - ProgressBar.createForElement( this.nestedSandbox ); - - assert.beautified.html( doc.getById( 'expected-create-from-element-prepend' ).getHtml(), this.nestedSandbox.getHtml() ); + assert.beautified.html( doc.getById( 'expected-create-from-element' ).getHtml(), this.sandbox.getHtml() ); }, 'test remove()': function() { - var ret = ProgressBar.createForElement( this.nestedSandbox ); + var ret = new ProgressBar( this.sandbox ); + + this.sandbox.append( ret.wrapper ); ret.remove(); @@ -70,7 +58,7 @@ [ -1.0, '0%' ], [ 1.1, '100%' ] ], - ret = ProgressBar.createForElement( this.nestedSandbox ); + ret = new ProgressBar( this.sandbox ); CKEDITOR.tools.array.forEach( values, function( assertSet ) { ret.updated( assertSet[ 0 ] ); @@ -79,11 +67,11 @@ }, // 'test update() locks the snapshot': function() { - // // todo + // @todo: add coverage. // }, 'test failed()': function() { - var ret = ProgressBar.createForElement( this.nestedSandbox ); + var ret = this._createProgressBar(); ret.failed(); @@ -91,7 +79,7 @@ }, 'test aborted()': function() { - var ret = ProgressBar.createForElement( this.nestedSandbox ); + var ret = this._createProgressBar(); ret.aborted(); @@ -99,7 +87,7 @@ }, 'test done()': function() { - var ret = ProgressBar.createForElement( this.nestedSandbox ); + var ret = this._createProgressBar(); ret.done(); @@ -183,6 +171,13 @@ loaderMock.fire( 'error' ); assert.areSame( 1, this.dummyProgress.failed.callCount, 'Failed call count' ); + }, + + // Adds the progress bar straight into DOM and returns ProgressBar instance. + _createProgressBar: function() { + var ret = new ProgressBar(); + this.sandbox.append( ret.wrapper ); + return ret; } }; From 074f89b65854363735d02feadb25016e879cbf1d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 21 Jan 2018 22:07:05 +0100 Subject: [PATCH 325/642] Docs: added an API listing for ProgressBar constructor. --- plugins/imagebase/plugin.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 0445a58abaa..6611a4fe1b5 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -511,7 +511,11 @@ }; /** - * Vertical progress bar. + * Type adding a vertical progress bar. + * + * var progress = new CKEDITOR.plugins.imagebase.progressBar(); + * myWrapper.append( progress.wrapper, true ); + * progress.bindLoader( myFileLoader ); * * @class CKEDITOR.plugins.imagebase.progressBar * @extends CKEDITOR.plugins.imagebase.progressReporter From 7fa923e09315bb6fc5d42c50e5206f4ac043f1c6 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 21 Jan 2018 22:14:35 +0100 Subject: [PATCH 326/642] Renamed last remaining "progress indicator" into "progress reporter" which sounds much better for a generic class. --- plugins/easyimage/plugin.js | 2 +- plugins/imagebase/plugin.js | 10 +++++----- .../easyimage/manual/customprogressbar.html | 8 ++++---- .../imagebase/features/manual/upload.html | 2 +- tests/plugins/imagebase/features/upload.js | 18 +++++++++--------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 6dc68f9063f..5eacd999096 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -156,7 +156,7 @@ loaderType: CKEDITOR.plugins.cloudservices.cloudServicesLoader, - progressIndicatorType: CKEDITOR.plugins.imagebase.progressBar, + progressReporterType: CKEDITOR.plugins.imagebase.progressBar, upcasts: { figure: function( element ) { diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 6611a4fe1b5..d8900febe45 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -188,7 +188,7 @@ function getUploadFeature() { var ret = { - progressIndicatorType: ProgressBar, + progressReporterType: ProgressBar, setUp: function( editor, definition ) { editor.on( 'paste', function( evt ) { @@ -266,8 +266,8 @@ loader[ loadMethod ]( def.uploadUrl, def.additionalRequestParameters ); - if ( widget.fire( 'uploadBegan', loader ) !== false && widget.progressIndicatorType ) { - var progress = new widget.progressIndicatorType(); + if ( widget.fire( 'uploadBegan', loader ) !== false && widget.progressReporterType ) { + var progress = new widget.progressReporterType(); widget.wrapper.append( progress.wrapper ); progress.bindLoader( loader ); } @@ -462,14 +462,14 @@ }, /** - * Removes the progress indicator from DOM. + * Removes the progress reporter from DOM. */ remove: function() { this.wrapper.remove(); }, /** - * Binds this progress indicator to a given `loader`. + * Binds this progress reporter to a given `loader`. * * It will automatically remove its listeners when the `loader` has triggered one of following events: * diff --git a/tests/plugins/easyimage/manual/customprogressbar.html b/tests/plugins/easyimage/manual/customprogressbar.html index 3b6cf5700d9..3ea0f5c1505 100644 --- a/tests/plugins/easyimage/manual/customprogressbar.html +++ b/tests/plugins/easyimage/manual/customprogressbar.html @@ -7,14 +7,14 @@

Default progress bar

-

Cricular progress indicator

+

Cricular progress reporter

Drop an image below:

-

Overlapping progress indicator

+

Overlapping progress reporter

Drop an image below:

@@ -35,7 +35,7 @@

Overlapping progress indicator

var widgetDef = evt.data, progressHelper = easyImageTools.progress, imageBasePlugin = CKEDITOR.plugins.imagebase, - // Each editor uses a different progress indicator. + // Each editor uses a different progress reporter. mapping = { editor1: imageBasePlugin.progressBar, editor2: progressHelper.getProgressCircleType( this, imageBasePlugin.progressReporter ), @@ -43,7 +43,7 @@

Overlapping progress indicator

}; if ( widgetDef.name === 'easyimage' ) { - widgetDef.progressIndicatorType = mapping[ this.name ]; + widgetDef.progressReporterType = mapping[ this.name ]; } } } diff --git a/tests/plugins/imagebase/features/manual/upload.html b/tests/plugins/imagebase/features/manual/upload.html index b9238a4e03b..58e85cee4ed 100644 --- a/tests/plugins/imagebase/features/manual/upload.html +++ b/tests/plugins/imagebase/features/manual/upload.html @@ -32,7 +32,7 @@ // Match any file type. def.supportedTypes = /^.+$/; - def.progressIndicatorType = CKEDITOR.plugins.imagebase.progressBar; + def.progressReporterType = CKEDITOR.plugins.imagebase.progressBar; } } ); diff --git a/tests/plugins/imagebase/features/upload.js b/tests/plugins/imagebase/features/upload.js index eac1c4b1b40..538bfb469e6 100644 --- a/tests/plugins/imagebase/features/upload.js +++ b/tests/plugins/imagebase/features/upload.js @@ -253,7 +253,7 @@ 'test default progress reporter': function() { var imageBase = CKEDITOR.plugins.imagebase, - ProgressBarSpy = this.sandbox.spy( this.editor.widgets.registered.testImageWidget, 'progressIndicatorType' ), + ProgressBarSpy = this.sandbox.spy( this.editor.widgets.registered.testImageWidget, 'progressReporterType' ), bindLoaderSpy = this.sandbox.spy( imageBase.progressBar.prototype, 'bindLoader' ), editor = this.editor; @@ -270,16 +270,16 @@ 'test progress reporter customization': function() { var CustomProgress = sinon.spy( CKEDITOR.plugins.imagebase.progressBar ), widgetDefinition = this.editor.widgets.registered.testImageWidget, - originalProgress = widgetDefinition.progressIndicatorType; + originalProgress = widgetDefinition.progressReporterType; CustomProgress.prototype = new CKEDITOR.plugins.imagebase.progressBar(); - widgetDefinition.progressIndicatorType = CustomProgress; + widgetDefinition.progressReporterType = CustomProgress; assertPasteFiles( this.editor, { files: [ bender.tools.getTestPngFile() ], callback: function() { - widgetDefinition.progressIndicatorType = originalProgress; + widgetDefinition.progressReporterType = originalProgress; assert.areSame( 1, CustomProgress.callCount, 'CustomProgress constructor call count' ); } @@ -305,7 +305,7 @@ imageBase.addImageWidget( editor, def.name, imageBase.addFeature( editor, 'upload', def ) ); - editor.widgets.registered.progressPrevent.progressIndicatorType = ProgressBarSpy; + editor.widgets.registered.progressPrevent.progressReporterType = ProgressBarSpy; assertPasteFiles( editor, { files: [ getTestHtmlFile() ], @@ -319,18 +319,18 @@ } ); }, - 'test preventing default progress reporter with widgetDefinition.progressIndicatorType': function() { + 'test preventing default progress reporter with widgetDefinition.progressReporterType': function() { var ProgressBarSpy = this.ProgressBarSpy, widgetDefinition = this.editor.widgets.registered.testImageWidget, - originalProgress = widgetDefinition.progressIndicatorType; + originalProgress = widgetDefinition.progressReporterType; // Setting to null will disable loading bar. - widgetDefinition.progressIndicatorType = null; + widgetDefinition.progressReporterType = null; assertPasteFiles( this.editor, { files: [ bender.tools.getTestPngFile() ], callback: function() { - widgetDefinition.progressIndicatorType = originalProgress; + widgetDefinition.progressReporterType = originalProgress; assert.areSame( 0, ProgressBarSpy.callCount, 'ProgressBar constructor call count' ); } From 62fe3376eff8c68a17ccf5d35287820c5fb7b5ca Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 21 Jan 2018 22:17:05 +0100 Subject: [PATCH 327/642] Tests: fixed failing manual test. --- tests/plugins/easyimage/manual/progressbar.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/manual/progressbar.html b/tests/plugins/easyimage/manual/progressbar.html index 96186f51265..15494d28e34 100644 --- a/tests/plugins/easyimage/manual/progressbar.html +++ b/tests/plugins/easyimage/manual/progressbar.html @@ -30,7 +30,8 @@

Sample editor

var IMG_URL = '%BASE_PATH%_assets/logo.png', commonConfig = { - cloudServices_url: 'https://files.cke-cs.com/upload/' + cloudServices_url: 'https://files.cke-cs.com/upload/', + cloudServices_token: 'dummy-token' }; window.XMLHttpRequest.responseData = { From ddab0ecfff5ed164ef5ee7bfb652bd112f918af1 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 21 Jan 2018 22:38:10 +0100 Subject: [PATCH 328/642] Tests: added manual test for progress bar being displayed with right-to-left languages. --- .../imagebase/manual/progressbarrtl.html | 28 +++++++++++++++++++ .../imagebase/manual/progressbarrtl.md | 17 +++++++++++ 2 files changed, 45 insertions(+) create mode 100644 tests/plugins/imagebase/manual/progressbarrtl.html create mode 100644 tests/plugins/imagebase/manual/progressbarrtl.md diff --git a/tests/plugins/imagebase/manual/progressbarrtl.html b/tests/plugins/imagebase/manual/progressbarrtl.html new file mode 100644 index 00000000000..d0e26737d13 --- /dev/null +++ b/tests/plugins/imagebase/manual/progressbarrtl.html @@ -0,0 +1,28 @@ +
+
+

line

+

line

+
+

Above div will gain your progress indicator.

+
+ + + diff --git a/tests/plugins/imagebase/manual/progressbarrtl.md b/tests/plugins/imagebase/manual/progressbarrtl.md new file mode 100644 index 00000000000..0e4aea51354 --- /dev/null +++ b/tests/plugins/imagebase/manual/progressbarrtl.md @@ -0,0 +1,17 @@ +@bender-tags: 4.9.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: wysiwygarea, imagebase + +# Progress Reporter RTL + +The editor uses right-to-left language editor, and shows 30% progress. + +1. Take a look at the progress bar. + +## Expected + +Progress bar starts from right side of the screen. + +## Unexpected + +Progress bar starts from left side of the screen. \ No newline at end of file From 1fa7f0e5ca91b924c0101b74cb713bb55b6b2578 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 21 Jan 2018 22:57:10 +0100 Subject: [PATCH 329/642] Tests: ignore unsupported environments in upload widget feature / progress bar tests. Also spotted two minor CSS code style issues, fixed it together. --- tests/plugins/easyimage/balloontoolbar.js | 4 ++++ tests/plugins/easyimage/uploadintegrations.js | 4 ++++ tests/plugins/imagebase/features/manual/upload.html | 4 ++++ tests/plugins/imagebase/features/upload.js | 4 ++++ tests/plugins/imagebase/manual/progressbar.html | 6 +++++- tests/plugins/imagebase/manual/progressbarrtl.html | 6 +++++- tests/plugins/imagebase/progressbar.js | 4 ++++ 7 files changed, 30 insertions(+), 2 deletions(-) diff --git a/tests/plugins/easyimage/balloontoolbar.js b/tests/plugins/easyimage/balloontoolbar.js index c9813063323..2d51d61b6b1 100644 --- a/tests/plugins/easyimage/balloontoolbar.js +++ b/tests/plugins/easyimage/balloontoolbar.js @@ -61,6 +61,10 @@ initialFrameHeight = testSuiteIframe && testSuiteIframe.getStyle( 'height' ), tests = { setUp: function() { + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 11 ) { + assert.ignore(); + } + // This test checks real balloon panel positioning. To avoid affecting position with scroll offset, set the parent iframe height // enough to contain entire content. Note that iframe is not present if the test suite is open in a separate window, or ran on IEs. if ( testSuiteIframe ) { diff --git a/tests/plugins/easyimage/uploadintegrations.js b/tests/plugins/easyimage/uploadintegrations.js index 819f15559aa..329b242d22a 100644 --- a/tests/plugins/easyimage/uploadintegrations.js +++ b/tests/plugins/easyimage/uploadintegrations.js @@ -93,6 +93,10 @@ }, setUp: function() { + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 11 ) { + assert.ignore(); + } + this.editorBot.setHtmlWithSelection( '

^

' ); }, diff --git a/tests/plugins/imagebase/features/manual/upload.html b/tests/plugins/imagebase/features/manual/upload.html index 58e85cee4ed..499fe547eca 100644 --- a/tests/plugins/imagebase/features/manual/upload.html +++ b/tests/plugins/imagebase/features/manual/upload.html @@ -5,6 +5,10 @@ + + + diff --git a/tests/plugins/imagebase/features/manual/uploadsimple.md b/tests/plugins/imagebase/features/manual/uploadsimple.md new file mode 100644 index 00000000000..736c60aca1b --- /dev/null +++ b/tests/plugins/imagebase/features/manual/uploadsimple.md @@ -0,0 +1,13 @@ +@bender-tags: 4.9.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: wysiwygarea, toolbar, elementspath, imagebase, cloudservices + +## Upload Widget + +1. Drop a png/jpg files into the editor. + +## Expected + +A simple widget with the name of a file is created. + +**Note:** at the time of writing Cloud Service accepts only images, and return `400` code for any other resource type. \ No newline at end of file From f18a291f2d5b2f0648e57aca83dbca1c2228c9e9 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 24 Jan 2018 20:50:59 +0100 Subject: [PATCH 353/642] Added lang meta entry. --- dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt b/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt index bf239264cd5..cea6e9dc42b 100644 --- a/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt +++ b/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt @@ -4,3 +4,4 @@ altText = Label for button converting image to assign an alternative text. fullImage = Label for button converting image to a full width. sideImage = Label for button converting image to be a side image. +uploadFailed = Contents of alert displayed when Easy Image widget could not be uploaded due to network error. From 6c7706174c3487a3c3e52f867ede7e765d8664eb Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 24 Jan 2018 21:07:17 +0100 Subject: [PATCH 354/642] Docs: more API docs for the Widget Upload Feature. --- plugins/imagebase/plugin.js | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index b0ed1a61f2c..4c9f5cacb8b 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -187,6 +187,15 @@ } function getUploadFeature() { + /** + * Widget feature dedicated for handling seamless file uploads. + * + * This type serves solely as a mixing, and should be added using + * {@link CKEDITOR.plugins.imagebase#addFeature} method. + * + * @class CKEDITOR.plugins.imagebase.featuresDefinitions.upload + * @abstract + */ var ret = { progressReporterType: ProgressBar, @@ -256,7 +265,7 @@ } ); }, - /* + /** * Initiates an upload process on a given widget. It does that by firing a {@link CKEDITOR.fileTools#fileLoader} request. * * @private @@ -276,12 +285,28 @@ this._beginUpload( widget, loader ); }, + /** + * Tells whether the loader is complete. + * + * @private + * @param {CKEDITOR.fileTools.fileLoader} loader + * @returns {Boolean} + */ _isLoaderDone: function( loader ) { var xhr = loader.xhr; return xhr && loader.xhr.readyState === 4; }, + /** + * + * @private + * @param {CKEDITOR.editor} editor + * @param {Blob/String} fileOrData See {@link CKEDITOR.fileTools.fileLoader}. + * @param {String} [fileName] Preferred file name to be passed to the upload process. + * @param {CKEDITOR.plugins.widget.definition} widgetDef Widget definition that the loader is spawned for. + * @returns {CKEDITOR.fileTools.fileLoader} + */ _spawnLoader: function( editor, file, fileName, widgetDef ) { var loadMethod = widgetDef.loadMethod || 'loadAndUpload', loader = editor.uploadRepository.create( file, fileName, widgetDef.loaderType ); @@ -291,6 +316,13 @@ return loader; }, + /** + * Initializes the upload process for given `widget` using `loader`. + * + * @private + * @param {CKEDITOR.plugins.widget} widget + * @param {CKEDITOR.fileTools.fileLoader} loader + */ _beginUpload: function( widget, loader ) { function widgetCleanup() { // Remove upload id so that it's not being re-requested when e.g. some1 copies and pastes From f314f3dd8e84bbed28da86713522c1d06b8c23e4 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 24 Jan 2018 21:14:04 +0100 Subject: [PATCH 355/642] Docs: API docs polishing. --- plugins/imagebase/plugin.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 4c9f5cacb8b..59412c2c973 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -193,6 +193,9 @@ * This type serves solely as a mixing, and should be added using * {@link CKEDITOR.plugins.imagebase#addFeature} method. * + * This API is not yet in a final shape, thus marked as a private. It can be changed at any point. + * + * @private * @class CKEDITOR.plugins.imagebase.featuresDefinitions.upload * @abstract */ @@ -266,7 +269,7 @@ }, /** - * Initiates an upload process on a given widget. It does that by firing a {@link CKEDITOR.fileTools#fileLoader} request. + * Initiates an upload process on a given widget. It does that by firing a {@link CKEDITOR.fileTools.fileLoader} request. * * @private * @param {CKEDITOR.editor} editor Editor instance. From 2147b2d188f1c3543b99dfccff037913863344b3 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 25 Jan 2018 00:22:22 +0100 Subject: [PATCH 356/642] Changed the order of _spawnLoader method. --- plugins/easyimage/plugin.js | 2 +- plugins/imagebase/plugin.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 89cbd0f9a0d..e69362d3d7e 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -342,7 +342,7 @@ imgFormat = imgSrc.match( /image\/([a-z]+?);/i ); imgFormat = ( imgFormat && imgFormat[ 1 ] ) || 'jpg'; - var loader = easyImageDef._spawnLoader( editor, imgSrc, undefined, easyImageDef ); + var loader = easyImageDef._spawnLoader( editor, imgSrc, easyImageDef ); widgetElement = easyImageDef._insertWidget( editor, easyImageDef, imgSrc, false, { uploadId: loader.id diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 59412c2c973..be9741f37bc 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -234,7 +234,7 @@ evt.stop(); CKEDITOR.tools.array.forEach( matchedFiles, function( curFile, index ) { - var loader = ret._spawnLoader( editor, curFile, curFile.name, definition ); + var loader = ret._spawnLoader( editor, curFile, definition, curFile.name ); ret._insertWidget( editor, definition, URL.createObjectURL( curFile ), true, { uploadId: loader.id } ); @@ -306,11 +306,11 @@ * @private * @param {CKEDITOR.editor} editor * @param {Blob/String} fileOrData See {@link CKEDITOR.fileTools.fileLoader}. - * @param {String} [fileName] Preferred file name to be passed to the upload process. * @param {CKEDITOR.plugins.widget.definition} widgetDef Widget definition that the loader is spawned for. + * @param {String} [fileName] Preferred file name to be passed to the upload process. * @returns {CKEDITOR.fileTools.fileLoader} */ - _spawnLoader: function( editor, file, fileName, widgetDef ) { + _spawnLoader: function( editor, file, widgetDef, fileName ) { var loadMethod = widgetDef.loadMethod || 'loadAndUpload', loader = editor.uploadRepository.create( file, fileName, widgetDef.loaderType ); From 750feb177fa5b15ce9d45e8085470f2cfaa3fc3d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 25 Jan 2018 00:23:05 +0100 Subject: [PATCH 357/642] Refactoring: _loadWidget is no longer used - removing. --- plugins/imagebase/plugin.js | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index be9741f37bc..9d5e0a65666 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -268,26 +268,6 @@ } ); }, - /** - * Initiates an upload process on a given widget. It does that by firing a {@link CKEDITOR.fileTools.fileLoader} request. - * - * @private - * @param {CKEDITOR.editor} editor Editor instance. - * @param {CKEDITOR.plugins.widget} widget Widget to be loaded. - * @param {CKEDITOR.plugins.widget.definition} def Loaded widget definition. - * @param {File/String} file File or base64-encoded file string to be uploaded. - * @param {String} [fileName] If `file` is passed as a base64-encoded string, this field should contain a name. - */ - _loadWidget: function( editor, widget, def, file, fileName ) { - var uploads = editor.uploadRepository, - loadMethod = def.loadMethod || 'loadAndUpload', - loader = uploads.create( file, fileName, def.loaderType ); - - loader[ loadMethod ]( def.uploadUrl, def.additionalRequestParameters ); - - this._beginUpload( widget, loader ); - }, - /** * Tells whether the loader is complete. * From 4b078e24691c30e0f9f74d6bd78561d89b220e5f Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 25 Jan 2018 00:37:52 +0100 Subject: [PATCH 358/642] Refactoring: renamed uploadBegan to uploadStarted event. --- plugins/easyimage/plugin.js | 2 +- plugins/imagebase/plugin.js | 6 +++--- .../plugins/imagebase/features/manual/upload.html | 2 +- tests/plugins/imagebase/features/upload.js | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index e69362d3d7e..4ac5a5fd711 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -228,7 +228,7 @@ this.addClass( editor.config.easyimage_class ); } - this.on( 'uploadBegan', function() { + this.on( 'uploadStarted', function() { var widget = this; getNaturalWidth( widget.parts.image, function( width ) { diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 9d5e0a65666..68c14f8c3d7 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -351,7 +351,7 @@ } ); } ); - if ( widget.fire( 'uploadBegan', loader ) !== false && widget.progressReporterType ) { + if ( widget.fire( 'uploadStarted', loader ) !== false && widget.progressReporterType ) { widget.setData( 'uploadId', loader.id ); if ( !widget._isLoaderDone( loader ) ) { @@ -402,7 +402,7 @@ /* * Fired when upload was initiated and before response is fetched. * - * progress.once( 'uploadBegan', function( evt ) { + * progress.once( 'uploadStarted', function( evt ) { * evt.cancel(); * // Implement a custom progress bar. * } ); @@ -412,7 +412,7 @@ * Note that the event will be fired even if the widget was created for a loader that * is already resolved. * - * @evt uploadBegan + * @evt uploadStarted * @param {CKEDITOR.fileTools.fileLoader} data Lader that is used for this widget. */ diff --git a/tests/plugins/imagebase/features/manual/upload.html b/tests/plugins/imagebase/features/manual/upload.html index 7db412fad48..759f9d8495d 100644 --- a/tests/plugins/imagebase/features/manual/upload.html +++ b/tests/plugins/imagebase/features/manual/upload.html @@ -45,7 +45,7 @@ var widget = evt.data; if ( widget.name === 'placeholder' ) { - widget.once( 'uploadBegan', function( uploadEvent ) { + widget.once( 'uploadStarted', function( uploadEvent ) { widget.setData( 'name', 'Uploading...' ); } ); diff --git a/tests/plugins/imagebase/features/upload.js b/tests/plugins/imagebase/features/upload.js index e5d347f68e0..5550a3583ac 100644 --- a/tests/plugins/imagebase/features/upload.js +++ b/tests/plugins/imagebase/features/upload.js @@ -179,7 +179,7 @@ 'test events': function() { var editor = this.editor, stubs = { - uploadBegan: sinon.stub(), + uploadStarted: sinon.stub(), uploadDone: sinon.stub(), uploadFailed: sinon.stub() }, @@ -195,8 +195,8 @@ assertPasteFiles( editor, { files: [ bender.tools.getTestPngFile() ], callback: function() { - assert.areSame( 1, stubs.uploadBegan.callCount, 'uploadBegan event count' ); - sinon.assert.calledWithExactly( stubs.uploadBegan, sinon.match.has( 'data', editor.uploadRepository.loaders[ 0 ] ) ); + assert.areSame( 1, stubs.uploadStarted.callCount, 'uploadStarted event count' ); + sinon.assert.calledWithExactly( stubs.uploadStarted, sinon.match.has( 'data', editor.uploadRepository.loaders[ 0 ] ) ); assert.areSame( 1, stubs.uploadDone.callCount, 'uploadDone event count' ); @@ -208,7 +208,7 @@ 'test upload error': function() { var editor = this.editor, stubs = { - uploadBegan: sinon.stub(), + uploadStarted: sinon.stub(), uploadDone: sinon.stub(), uploadFailed: sinon.stub() }, @@ -233,8 +233,8 @@ var loaderInstance = editor.uploadRepository.loaders[ 0 ]; - assert.areSame( 1, stubs.uploadBegan.callCount, 'uploadBegan event count' ); - sinon.assert.calledWithExactly( stubs.uploadBegan, sinon.match.has( 'data', loaderInstance ) ); + assert.areSame( 1, stubs.uploadStarted.callCount, 'uploadStarted event count' ); + sinon.assert.calledWithExactly( stubs.uploadStarted, sinon.match.has( 'data', loaderInstance ) ); assert.areSame( 0, stubs.uploadDone.callCount, 'uploadDone event count' ); @@ -330,7 +330,7 @@ name: 'progressPrevent', supportedTypes: /text\/html/, init: function() { - disposableListeners.push( this.on( 'uploadBegan', function( evt ) { + disposableListeners.push( this.on( 'uploadStarted', function( evt ) { evt.cancel(); } ) ); } From 750c3eca68f96ee33c211944f7e7e739af821cfb Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 25 Jan 2018 00:41:13 +0100 Subject: [PATCH 359/642] Tests: lowered fake file loader response timings, so that the test suite passes faster. --- tests/plugins/easyimage/uploadintegrations.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/plugins/easyimage/uploadintegrations.js b/tests/plugins/easyimage/uploadintegrations.js index df53901743e..f7a8a1ec3f0 100644 --- a/tests/plugins/easyimage/uploadintegrations.js +++ b/tests/plugins/easyimage/uploadintegrations.js @@ -67,11 +67,11 @@ setTimeout( function() { that.update(); - }, 200 ); + }, 40 ); setTimeout( function() { that.update(); - }, 400 ); + }, 120 ); setTimeout( function() { var evtData = { @@ -83,7 +83,7 @@ }; that._lastTimeout( evtData ); - }, 1000 ); + }, 350 ); }, _lastTimeout: function( evtData ) { this.responseData = { From 6b0080e02a6d5e873d65c475190c2a9b6c379e5e Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 25 Jan 2018 10:14:07 +0100 Subject: [PATCH 360/642] Docs: improved API docs in widget upload feature. --- plugins/imagebase/plugin.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 68c14f8c3d7..566466e7710 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -200,6 +200,13 @@ * @abstract */ var ret = { + /** + * Type used for for progress reporting, it has to be a subclass of {@link CKEDITOR.plugins.imagebase.progressReporter}. + * + * Could be set to `false` so that there is no reporter created at all. + * + * @property {Function/Boolean} [progressReporterType=CKEDITOR.plugins.imagebase.progressBar] + */ progressReporterType: ProgressBar, setUp: function( editor, definition ) { @@ -276,6 +283,7 @@ * @returns {Boolean} */ _isLoaderDone: function( loader ) { + // This method should be removed once #1497 is done. var xhr = loader.xhr; return xhr && loader.xhr.readyState === 4; @@ -399,6 +407,12 @@ } } + /** + * Preferred file loader type used for requests. + * + * @property {Function} [loaderType=CKEDITOR.fileTools.fileLoader] + */ + /* * Fired when upload was initiated and before response is fetched. * From 62228c3de314c60e7c2ed48fbaba002fe9757c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Thu, 25 Jan 2018 16:36:17 +0100 Subject: [PATCH 361/642] Fixed typos. --- plugins/easyimage/plugin.js | 2 +- plugins/imagebase/plugin.js | 6 +++--- tests/plugins/easyimage/uploadintegrations.js | 2 +- tests/plugins/imagebase/features/_helpers/tools.js | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 4ac5a5fd711..7be991bff2b 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -326,7 +326,7 @@ isDataInSrc = imgSrc && imgSrc.substring( 0, 5 ) == 'data:', isRealObject = img.data( 'cke-realelement' ) === null; - // We are not uploading images in non-editable blocs and fake objects (https://dev.ckeditor.com/ticket/13003). + // We are not uploading images in non-editable blocks and fake objects (https://dev.ckeditor.com/ticket/13003). if ( isDataInSrc && isRealObject && !img.isReadOnly( 1 ) ) { widgetsFound++; diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 566466e7710..daf5d755d85 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -224,7 +224,7 @@ curFile; // Refetch the definition... original definition looks like an outdated copy and it doesn't - // include members inherited form imagebase. + // include members inherited from imagebase. definition = editor.widgets.registered[ definition.name ]; for ( var i = 0; i < filesCount; i++ ) { @@ -316,7 +316,7 @@ */ _beginUpload: function( widget, loader ) { function widgetCleanup() { - // Remove upload id so that it's not being re-requested when e.g. some1 copies and pastes + // Remove upload id so that it's not being re-requested when e.g. someone copies and pastes // the widget in other place. if ( widget.isInited() ) { widget.setData( 'uploadId', undefined ); @@ -380,7 +380,7 @@ * @param {CKEDITOR.editor} editor * @param {CKEDITOR.plugins.widget.definition} widgetDef * @param {String} blobUrl Blob URL of an image. - * @param {Boolean} [finalize=true] If `false` widget will not be automatically finalized (added to {@link CKEDITOR.plugins.widget.repository}) + * @param {Boolean} [finalize=true] If `false` widget will not be automatically finalized (added to {@link CKEDITOR.plugins.widget.repository}), * but returned as a {@link CKEDITOR.dom.element} instance. * @returns {CKEDITOR.plugins.widget/CKEDITOR.dom.element} The widget instance or {@link CKEDITOR.dom.element} of a widget wrapper if `finalize` was set to `false`. */ diff --git a/tests/plugins/easyimage/uploadintegrations.js b/tests/plugins/easyimage/uploadintegrations.js index f7a8a1ec3f0..98df914f278 100644 --- a/tests/plugins/easyimage/uploadintegrations.js +++ b/tests/plugins/easyimage/uploadintegrations.js @@ -269,7 +269,7 @@ 'test copy and paste in progress widget while original was loaded': function() { // Yet another tricky variation. // 1. In This case user starts to upload file that takes say 1 sec. - // 2. Copies the file curing the upload. + // 2. Copies the file during the upload. // 3. Wait for the file upload to complete. // 4. Then paste what he has in clipboard (incomplete) widget as a new widget. var editor = this.editor, diff --git a/tests/plugins/imagebase/features/_helpers/tools.js b/tests/plugins/imagebase/features/_helpers/tools.js index 69467866e1d..7e01a55597f 100644 --- a/tests/plugins/imagebase/features/_helpers/tools.js +++ b/tests/plugins/imagebase/features/_helpers/tools.js @@ -42,8 +42,8 @@ listeners = []; function wrappedCallback( uploadEvt ) { - // In case we listen for `upload*` events only first event should be handled (to not cause multiple) - // resume calls. + // In case we listen for `upload*` events only first event should be handled (to not cause multiple + // resume calls). if ( listeners.length ) { listeners = CKEDITOR.tools.array.filter( listeners, function( curListener ) { curListener.removeListener(); @@ -201,7 +201,7 @@ }, /* - * Cache for tye returned types. + * Cache for the returned types. */ _cache: {} } From f4d88054638653826559691d08e38891be9c87a8 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 26 Jan 2018 15:29:34 +0100 Subject: [PATCH 362/642] Tests: Corrected API docs for Upload Widget Feature test helpers. --- tests/plugins/imagebase/features/_helpers/tools.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/plugins/imagebase/features/_helpers/tools.js b/tests/plugins/imagebase/features/_helpers/tools.js index 7e01a55597f..dd27cc831b9 100644 --- a/tests/plugins/imagebase/features/_helpers/tools.js +++ b/tests/plugins/imagebase/features/_helpers/tools.js @@ -18,7 +18,6 @@ * * @param {CKEDITOR.editor} editor * @param {Object} options - * @param {File[]} [options.files=[]] Files to be dropped. * @param {Function} options.callback Function to be called after the paste event. * Params: * @@ -26,6 +25,7 @@ * * `CKEDITOR.eventInfo` evt - Paste event. * * `CKEDITOR.eventInfo/undefined` uploadEvt - Upload event, available ony if `options.fullLoad` was set * to `true` and at least one widget was found. + * @param {File[]} [options.files=[]] Files to be dropped. * @param {String} [options.dataValue=null] HTML data to be put into the clipboard if any. * @param {Boolean} [options.fullLoad=false] If `true` assertion will wait for `uploadDone` of `uploadFailed` * event of the first widget. @@ -79,8 +79,7 @@ * on a image, and removes it indicating the progress. * * @param {CKEDITOR.editor} editor - * @param {Function} ProgressReporter Base type for progress indicator - * {@link CKEDITOR.plugins.imageBase.progressReporter}. + * @param {Function} ProgressReporter Base type for progress indicator {@link CKEDITOR.plugins.imageBase.progressReporter}. * @returns {Function} */ getProgressOverlapType: function( editor, ProgressReporter ) { @@ -109,6 +108,8 @@ * Returns a type that implements a progress indicator that puts a * circle-shaped progress bar. * + * @param {CKEDITOR.editor} editor + * @param {Function} ProgressReporter Base type for progress indicator {@link CKEDITOR.plugins.imageBase.progressReporter}. * @returns {Function} */ getProgressCircleType: function( editor, ProgressReporter ) { From 4e827522f5f0e677b57a2b16f32b2cbd13de5915 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 26 Jan 2018 15:40:15 +0100 Subject: [PATCH 363/642] Fixed uploadId not being assigned if uploadStarted was cancelled and minor doc fixes. Docs: simplified reporter methods description and corrected uploadStarted event docs. --- plugins/imagebase/plugin.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index daf5d755d85..42b5b5166fc 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -359,9 +359,9 @@ } ); } ); - if ( widget.fire( 'uploadStarted', loader ) !== false && widget.progressReporterType ) { - widget.setData( 'uploadId', loader.id ); + widget.setData( 'uploadId', loader.id ); + if ( widget.fire( 'uploadStarted', loader ) !== false && widget.progressReporterType ) { if ( !widget._isLoaderDone( loader ) ) { // Progress reporter has only sense if widget is in progress. var progress = new widget.progressReporterType(); @@ -421,7 +421,7 @@ * // Implement a custom progress bar. * } ); * - * This event is cancelable, if canceled it will add a progress bar to the widget. + * This event is cancelable, if canceled, the default progress bar will not be created. * * Note that the event will be fired even if the widget was created for a loader that * is already resolved. @@ -584,21 +584,21 @@ updated: function() {}, /** - * To be called when the progress should be marked as complete. + * Marks the progress reporter as complete. */ done: function() { this.remove(); }, /** - * To be called when the progress should be marked as aborted. + * Marks the progress reporter as aborted. */ aborted: function() { this.remove(); }, /** - * To be called when the progress should be marked as failed. + * Marks the progress reporter as failed. */ failed: function() { this.remove(); From 6d74a9919d7ff1670e68d6b59dd001381c00d91e Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 26 Jan 2018 15:46:48 +0100 Subject: [PATCH 364/642] Fixed error message when uploading Easy Image widget fails. --- plugins/easyimage/lang/en.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/lang/en.js b/plugins/easyimage/lang/en.js index e7562db189c..97f7337e6c3 100644 --- a/plugins/easyimage/lang/en.js +++ b/plugins/easyimage/lang/en.js @@ -9,5 +9,5 @@ CKEDITOR.plugins.setLang( 'easyimage', 'en', { sideImage: 'Side Image', altText: 'Change image alternative text' }, - uploadFailed: 'Your image could not be downloaded due to network error.' + uploadFailed: 'Your image could not be uploaded due to a network error.' } ); From 0bbc741496955833fd2bc662c5f1748059b89b9b Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 26 Jan 2018 15:47:27 +0100 Subject: [PATCH 365/642] Docs: API docs for Image Base plugin corrected. --- plugins/imagebase/plugin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 42b5b5166fc..890b3e94c0e 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -190,7 +190,7 @@ /** * Widget feature dedicated for handling seamless file uploads. * - * This type serves solely as a mixing, and should be added using + * This type serves solely as a mixin, and should be added using * {@link CKEDITOR.plugins.imagebase#addFeature} method. * * This API is not yet in a final shape, thus marked as a private. It can be changed at any point. @@ -293,7 +293,7 @@ * * @private * @param {CKEDITOR.editor} editor - * @param {Blob/String} fileOrData See {@link CKEDITOR.fileTools.fileLoader}. + * @param {Blob/String} file See {@link CKEDITOR.fileTools.fileLoader}. * @param {CKEDITOR.plugins.widget.definition} widgetDef Widget definition that the loader is spawned for. * @param {String} [fileName] Preferred file name to be passed to the upload process. * @returns {CKEDITOR.fileTools.fileLoader} From a8270c02f8e14c5e75187c5e51ab425d99126d78 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Fri, 26 Jan 2018 16:09:12 +0100 Subject: [PATCH 366/642] Tests: added a manual test for Easy Image and Paste from Word integration. --- .../easyimage/manual/pastefromword.html | 32 +++++++++++++++++++ .../plugins/easyimage/manual/pastefromword.md | 19 +++++++++++ 2 files changed, 51 insertions(+) create mode 100644 tests/plugins/easyimage/manual/pastefromword.html create mode 100644 tests/plugins/easyimage/manual/pastefromword.md diff --git a/tests/plugins/easyimage/manual/pastefromword.html b/tests/plugins/easyimage/manual/pastefromword.html new file mode 100644 index 00000000000..5b44121b5e2 --- /dev/null +++ b/tests/plugins/easyimage/manual/pastefromword.html @@ -0,0 +1,32 @@ +

Note, this test uses a real Cloud Service connection, so you might want to be on-line 😉.

+ +

Classic editor

+ +
+

Sample editor

+

Go on, put some content here.

+
+ +

Inline editor

+ +
+

Sample editor

+

Go on, put some content here.

+
+ + + diff --git a/tests/plugins/easyimage/manual/pastefromword.md b/tests/plugins/easyimage/manual/pastefromword.md new file mode 100644 index 00000000000..a62b25ed65b --- /dev/null +++ b/tests/plugins/easyimage/manual/pastefromword.md @@ -0,0 +1,19 @@ +@bender-tags: 4.9.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, undo, pastefromword + +## Easy Image PFW Integration + +Upload some images: + +1. Open a document containing an image in MS Word (e.g. [`Image_alternative_text.docx`](https://github.com/ckeditor/ckeditor-dev/blob/7ecc15bc26aef53fadb7f3ec342510ca2d736236/tests/plugins/pastefromword/generated/_fixtures/PFW_image/Image_alternative_text/Image_alternative_text.docx)). +1. Copy whole file contents. +1. Focus the "Classic editor". +1. Paste into the editor. + +### Expected + +* Image is inserted as an Easy Image widget. +* Image gets uploaded (if you didn't see the progress bar you can examine it by checking image URL in devtools). + +Repeat the steps with Inline editor. \ No newline at end of file From 51d544b8b6f180fe420d031daf89754461e3e90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Mon, 29 Jan 2018 12:19:15 +0100 Subject: [PATCH 367/642] Tests: adjusted test assert to message change. --- tests/plugins/easyimage/uploadintegrations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/uploadintegrations.js b/tests/plugins/easyimage/uploadintegrations.js index 98df914f278..4fcdce36268 100644 --- a/tests/plugins/easyimage/uploadintegrations.js +++ b/tests/plugins/easyimage/uploadintegrations.js @@ -230,7 +230,7 @@ easyImageDef.loaderType = originalLoader; assert.areSame( 1, window.alert.callCount, 'Alert call count' ); - sinon.assert.alwaysCalledWith( window.alert, 'Your image could not be downloaded due to network error.' ); + sinon.assert.alwaysCalledWith( window.alert, 'Your image could not be uploaded due to a network error.' ); // Widget should be removed. assert.areSame( 0, widgets.length, 'Widgets count' ); From 4cc8f4740c320e0e3116e22ed2da126065632f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Mon, 29 Jan 2018 12:59:19 +0100 Subject: [PATCH 368/642] Docs scope adjustments. --- plugins/imagebase/plugin.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 890b3e94c0e..38a543d2150 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -375,7 +375,7 @@ } }, - /* + /** * @private * @param {CKEDITOR.editor} editor * @param {CKEDITOR.plugins.widget.definition} widgetDef @@ -413,7 +413,7 @@ * @property {Function} [loaderType=CKEDITOR.fileTools.fileLoader] */ - /* + /** * Fired when upload was initiated and before response is fetched. * * progress.once( 'uploadStarted', function( evt ) { @@ -430,7 +430,7 @@ * @param {CKEDITOR.fileTools.fileLoader} data Lader that is used for this widget. */ - /* + /** * Fired when upload process succeeded. This is the event where you want apply data * from your response into a widget. * @@ -444,7 +444,7 @@ * @param {CKEDITOR.fileTools.fileLoader} data.loader Loader that caused this event. */ - /* + /** * Fired when upload process {@link CKEDITOR.fileTools.fileLoader#event-error failed} or was * {@link CKEDITOR.fileTools.fileLoader#event-abort aborted}. * From 10dc6f5b16af58775588bb66d39b7fc3a5fda10a Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 15 Nov 2017 13:56:32 +0100 Subject: [PATCH 369/642] Add caption feature. --- plugins/imagebase/plugin.js | 19 ++++++ tests/plugins/imagebase/features/caption.html | 5 ++ tests/plugins/imagebase/features/caption.js | 59 +++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 tests/plugins/imagebase/features/caption.html create mode 100644 tests/plugins/imagebase/features/caption.js diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 38a543d2150..3e3e8b74b1a 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -463,7 +463,26 @@ return ret; } + function createCaption( widget ) { + var element = widget.element, + caption = element.getDocument().createElement( 'figcaption' ), + definition = widget.editor.widgets.registered[ widget.name ]; + + element.append( caption ); + widget.initEditable( 'caption', definition.editables.caption ); + + return caption; + } + var featuresDefinitions = { + caption: { + init: function() { + if ( !this.parts.caption ) { + this.parts.caption = createCaption( this ); + } + } + }, + upload: getUploadFeature(), link: getLinkFeature() }; diff --git a/tests/plugins/imagebase/features/caption.html b/tests/plugins/imagebase/features/caption.html new file mode 100644 index 00000000000..8620bb54ce8 --- /dev/null +++ b/tests/plugins/imagebase/features/caption.html @@ -0,0 +1,5 @@ +
+
+ +
+
diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js new file mode 100644 index 00000000000..187c243adc5 --- /dev/null +++ b/tests/plugins/imagebase/features/caption.js @@ -0,0 +1,59 @@ +/* bender-tags: editor,widget */ +/* bender-ckeditor-plugins: imagebase,toolbar */ +/* bender-include: ../../widget/_helpers/tools.js */ +/* global widgetTestsTools */ + +( function() { + 'use strict'; + + bender.editors = { + classic: {}, + + divarea: { + config: { + extraPlugins: 'divarea' + } + }, + + inline: { + creator: 'inline' + } + }; + + function addTestWidget( editor ) { + if ( editor.widgets.registered.testWidget ) { + return; + } + + var plugin = CKEDITOR.plugins.imagebase; + + plugin.addImageWidget( editor, 'testWidget', plugin.addFeature( editor, 'caption', {} ) ); + } + + var tests = { + 'test upcasting widget without figcaption element': function( editor, bot ) { + addTestWidget( editor ); + + widgetTestsTools.assertWidget( { + count: 1, + widgetOffset: 0, + nameCreated: 'testWidget', + html: CKEDITOR.document.getById( 'upcastWithoutCaptionTest' ).getHtml(), + bot: bot, + + assertCreated: function( widget ) { + var figcaptions = widget.element.find( 'figcaption' ); + + assert.areSame( 1, figcaptions.count(), 'captions count' ); + assert.isTrue( figcaptions.getItem( 0 ).equals( widget.parts.caption ), + 'Widget caption part element' ); + assert.isTrue( CKEDITOR.plugins.widget.isDomNestedEditable( widget.parts.caption ), + 'Caption is nested editable' ); + } + } ); + } + }; + + tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); + bender.test( tests ); +} )(); From 5b154797ac721a34bf3d741b1fbc6bc4c5ac6218 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 14:52:37 +0100 Subject: [PATCH 370/642] Add toggling caption. --- plugins/imagebase/plugin.js | 60 +++++++++++++++++++++++++- plugins/imagebase/styles/imagebase.css | 3 ++ 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 plugins/imagebase/styles/imagebase.css diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 3e3e8b74b1a..055f15b78ea 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -6,8 +6,30 @@ ( function() { 'use strict'; + var stylesLoaded = false; + + function loadStyles( editor, plugin ) { + if ( !stylesLoaded ) { + CKEDITOR.document.appendStyleSheet( plugin.path + 'styles/imagebase.css' ); + stylesLoaded = true; + } + + if ( editor.addContentsCss ) { + editor.addContentsCss( plugin.path + 'styles/imagebase.css' ); + } + } + function getFocusedWidget( editor ) { - return editor.widgets.focused; + var widgets = editor.widgets, + currentActive = editor.focusManager.currentActive; + + if ( widgets.focused ) { + return widgets.focused; + } + + if ( currentActive instanceof CKEDITOR.plugins.widget.nestedEditable ) { + return widgets.getByElement( currentActive ); + } } function getLinkFeature() { @@ -476,10 +498,40 @@ var featuresDefinitions = { caption: { + setUp: function( editor ) { + var lastWidget; + + editor.on( 'selectionChange', function() { + var widget = getFocusedWidget( editor ); + + if ( lastWidget ) { + lastWidget._toggleCaption(); + } + + if ( widget && CKEDITOR.tools.indexOf( widget.features, 'caption' ) !== -1 ) { + widget._toggleCaption(); + + lastWidget = widget; + } + } ); + }, + init: function() { if ( !this.parts.caption ) { this.parts.caption = createCaption( this ); } + + this._toggleCaption(); + }, + + _toggleCaption: function() { + var isFocused = getFocusedWidget( this.editor ) === this; + + if ( isFocused ) { + this.parts.caption.removeAttribute( 'data-cke-hidden' ); + } else if ( !this.editables.caption.getData() ) { + this.parts.caption.setAttribute( 'data-cke-hidden', true ); + } } }, @@ -709,7 +761,11 @@ CKEDITOR.plugins.add( 'imagebase', { requires: 'widget,filetools', - lang: 'en' + lang: 'en', + + init: function( editor ) { + loadStyles( editor, this ); + } } ); /** diff --git a/plugins/imagebase/styles/imagebase.css b/plugins/imagebase/styles/imagebase.css new file mode 100644 index 00000000000..3845865c5a3 --- /dev/null +++ b/plugins/imagebase/styles/imagebase.css @@ -0,0 +1,3 @@ +[data-cke-hidden] { + display: none; +} From a43c8ba90aff4154f6fb0ee92c588a5f862aa8d2 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 16:57:29 +0100 Subject: [PATCH 371/642] Add unit tests. --- tests/plugins/imagebase/features/caption.html | 43 ++++++ tests/plugins/imagebase/features/caption.js | 125 +++++++++++++++++- 2 files changed, 166 insertions(+), 2 deletions(-) diff --git a/tests/plugins/imagebase/features/caption.html b/tests/plugins/imagebase/features/caption.html index 8620bb54ce8..fc685467dc8 100644 --- a/tests/plugins/imagebase/features/caption.html +++ b/tests/plugins/imagebase/features/caption.html @@ -3,3 +3,46 @@
+ +
+

Focus trap!

+ +
+ +
+
+
+ +
+

Focus trap!

+ +
+ +
Test caption
+
+
+ + +
+
+ +
+
+ +
+ +
+
+
+ +
+
+ +
Test caption
+
+ +
+ +
Test caption
+
+
diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 187c243adc5..f5d84888d13 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -30,6 +30,77 @@ plugin.addImageWidget( editor, 'testWidget', plugin.addFeature( editor, 'caption', {} ) ); } + function getFixture( name ) { + return CKEDITOR.document.getById( name ).getHtml(); + } + + function assertVisibility( caption, isVisible, msg ) { + assert[ 'is' + ( isVisible ? 'False' : 'True' ) ]( caption.hasAttribute( 'data-cke-hidden' ), msg ); + } + + function createToggleTest( options ) { + return function( editor, bot ) { + addTestWidget( editor ); + + bot.setData( getFixture( options.fixture ), function() { + var widget = widgetTestsTools.getWidgetByDOMOffset( editor, 0 ), + caption = widget.parts.caption, + focusTrap = editor.editable().findOne( 'p' ).getChild( 0 ), + range = editor.createRange(); + + assertVisibility( caption, options.initial, 'caption visibility (initial)' ); + + widget.focus(); + + assertVisibility( caption, options.focus, 'caption visibility (focus)' ); + + if ( options.onFocus ) { + options.onFocus( widget ); + } + + range.setStart( focusTrap, 1 ); + range.collapse(); + range.select(); + + assertVisibility( caption, options.blur, 'caption visibility (blur)' ); + } ); + }; + } + + function createDoubleToggleTest( options ) { + return function( editor, bot ) { + addTestWidget( editor ); + + bot.setData( getFixture( options.fixture ), function() { + var widget1 = widgetTestsTools.getWidgetByDOMOffset( editor, 0 ), + widget2 = widgetTestsTools.getWidgetByDOMOffset( editor, 1 ), + caption1 = widget1.parts.caption, + caption2 = widget2.parts.caption; + + assertVisibility( caption1, options.initial[ 0 ], 'caption#1 visibility (initial)' ); + assertVisibility( caption2, options.initial[ 1 ], 'caption#2 visibility (initial)' ); + + widget1.focus(); + + assertVisibility( caption1, options.focus1[ 0 ], 'caption#1 visibility (focus widget#1)' ); + assertVisibility( caption2, options.focus1[ 1 ], 'caption#2 visibility (focus widget#1)' ); + + if ( options.onFocus1 ) { + options.onFocus1( widget1 ); + } + + widget2.focus(); + + assertVisibility( caption1, options.focus2[ 0 ], 'caption#1 visibility (focus widget#2)' ); + assertVisibility( caption2, options.focus2[ 1 ], 'caption#2 visibility (focus widget#2)' ); + + if ( options.onFocus2 ) { + options.onFocus2( widget2 ); + } + } ); + }; + } + var tests = { 'test upcasting widget without figcaption element': function( editor, bot ) { addTestWidget( editor ); @@ -38,7 +109,7 @@ count: 1, widgetOffset: 0, nameCreated: 'testWidget', - html: CKEDITOR.document.getById( 'upcastWithoutCaptionTest' ).getHtml(), + html: getFixture( 'upcastWithoutCaptionTest' ), bot: bot, assertCreated: function( widget ) { @@ -51,7 +122,57 @@ 'Caption is nested editable' ); } } ); - } + }, + + 'test toggling caption (one widget with empty caption)': createToggleTest( { + fixture: 'toggleOneEmpty', + initial: false, + focus: true, + blur: false + } ), + + 'test toggling caption (one widget with non-empty caption)': createToggleTest( { + fixture: 'toggleOne', + initial: true, + focus: true, + blur: true + } ), + + 'test toggling caption (one widget with empty caption that gets filled)': createToggleTest( { + fixture: 'toggleOneEmpty', + initial: false, + focus: true, + blur: true, + + onFocus: function( widget ) { + widget.editables.caption.setData( 'Test' ); + } + } ), + + 'test toggling caption (one widget with non-empty caption that gets emptied)': createToggleTest( { + fixture: 'toggleOne', + initial: true, + focus: true, + blur: false, + + onFocus: function( widget ) { + widget.editables.caption.setData( '' ); + } + } ), + + 'test toggling captions (two widgets with empty captions)': createDoubleToggleTest( { + fixture: 'toggleTwoEmpty', + initial: [ false, false ], + focus1: [ true, false ], + focus2: [ false, true ] + } ), + + 'test toggling captions (two widgets with non-empty captions)': createDoubleToggleTest( { + fixture: 'toggleTwo', + initial: [ true, true ], + focus1: [ true, true ], + focus2: [ true, true ] + } ) }; tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); From 52cd326f31c2fa94025805e44d4514ca2076b8d1 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 17:07:01 +0100 Subject: [PATCH 372/642] Make testing tools more generic. --- tests/plugins/imagebase/features/caption.js | 66 +++++++++++++-------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index f5d84888d13..4d40774395d 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -67,36 +67,44 @@ }; } - function createDoubleToggleTest( options ) { + function createMultipleToggleTest( options ) { return function( editor, bot ) { + var forEach = CKEDITOR.tools.array.forEach; + addTestWidget( editor ); - bot.setData( getFixture( options.fixture ), function() { - var widget1 = widgetTestsTools.getWidgetByDOMOffset( editor, 0 ), - widget2 = widgetTestsTools.getWidgetByDOMOffset( editor, 1 ), - caption1 = widget1.parts.caption, - caption2 = widget2.parts.caption; + function getWidgets( editor, amount ) { + var i, + widgets = []; - assertVisibility( caption1, options.initial[ 0 ], 'caption#1 visibility (initial)' ); - assertVisibility( caption2, options.initial[ 1 ], 'caption#2 visibility (initial)' ); + for ( i = 0; i < amount; i++ ) { + widgets.push( widgetTestsTools.getWidgetByDOMOffset( editor, i ) ); + } + + return widgets; + } - widget1.focus(); + function assertMultipleVisibility( widgets, expected, msg ) { + forEach( widgets, function( widget, i ) { + assertVisibility( widget.parts.caption, expected[ i ], + 'caption#' + i + ' visibility (' + msg + ')' ); + } ); + } - assertVisibility( caption1, options.focus1[ 0 ], 'caption#1 visibility (focus widget#1)' ); - assertVisibility( caption2, options.focus1[ 1 ], 'caption#2 visibility (focus widget#1)' ); + function assertOnFocus( widgets, expected ) { + forEach( widgets, function( widget, i ) { + widget.focus(); - if ( options.onFocus1 ) { - options.onFocus1( widget1 ); - } + assertMultipleVisibility( widgets, expected[ i ], 'focus widget#' + i ); + } ); + } - widget2.focus(); + bot.setData( getFixture( options.fixture ), function() { + var widgets = getWidgets( editor, options.widgetsCount ); - assertVisibility( caption1, options.focus2[ 0 ], 'caption#1 visibility (focus widget#2)' ); - assertVisibility( caption2, options.focus2[ 1 ], 'caption#2 visibility (focus widget#2)' ); + assertMultipleVisibility( widgets, options.initial, 'initial' ); - if ( options.onFocus2 ) { - options.onFocus2( widget2 ); - } + assertOnFocus( widgets, options.focus ); } ); }; } @@ -160,18 +168,24 @@ } } ), - 'test toggling captions (two widgets with empty captions)': createDoubleToggleTest( { + 'test toggling captions (two widgets with empty captions)': createMultipleToggleTest( { fixture: 'toggleTwoEmpty', + widgetsCount: 2, initial: [ false, false ], - focus1: [ true, false ], - focus2: [ false, true ] + focus: [ + [ true, false ], + [ false, true ] + ] } ), - 'test toggling captions (two widgets with non-empty captions)': createDoubleToggleTest( { + 'test toggling captions (two widgets with non-empty captions)': createMultipleToggleTest( { fixture: 'toggleTwo', + widgetsCount: 2, initial: [ true, true ], - focus1: [ true, true ], - focus2: [ true, true ] + focus: [ + [ true, true ], + [ true, true ] + ] } ) }; From bc71e25ff4507042cc05e1df7d51d5237c2ee3d9 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 17:22:06 +0100 Subject: [PATCH 373/642] Update tests. --- tests/plugins/imagebase/features/caption.js | 44 +++++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 4d40774395d..bad858a58d7 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -48,21 +48,25 @@ focusTrap = editor.editable().findOne( 'p' ).getChild( 0 ), range = editor.createRange(); - assertVisibility( caption, options.initial, 'caption visibility (initial)' ); + try { + assertVisibility( caption, options.initial, 'caption visibility (initial)' ); - widget.focus(); + widget.focus(); - assertVisibility( caption, options.focus, 'caption visibility (focus)' ); + assertVisibility( caption, options.focus, 'caption visibility (focus)' ); - if ( options.onFocus ) { - options.onFocus( widget ); - } + if ( options.onFocus ) { + options.onFocus( widget ); + } - range.setStart( focusTrap, 1 ); - range.collapse(); - range.select(); + range.setStart( focusTrap, 1 ); + range.collapse(); + range.select(); - assertVisibility( caption, options.blur, 'caption visibility (blur)' ); + assertVisibility( caption, options.blur, 'caption visibility (blur)' ); + } catch ( error ) { + assert.fail( 'Error occured: ' + error ); + } } ); }; } @@ -102,9 +106,12 @@ bot.setData( getFixture( options.fixture ), function() { var widgets = getWidgets( editor, options.widgetsCount ); - assertMultipleVisibility( widgets, options.initial, 'initial' ); - - assertOnFocus( widgets, options.focus ); + try { + assertMultipleVisibility( widgets, options.initial, 'initial' ); + assertOnFocus( widgets, options.focus ); + } catch ( error ) { + assert.fail( 'Error occured: ' + error ); + } } ); }; } @@ -186,6 +193,17 @@ [ true, true ], [ true, true ] ] + } ), + + 'remove widget before changing selection': createToggleTest( { + fixture: 'toggleOne', + initial: true, + focus: true, + blur: true, + + onFocus: function( widget ) { + widget.wrapper.remove(); + } } ) }; From aa9628102834079f1a93aee2ac7ab8a90a1c3c60 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 17:22:39 +0100 Subject: [PATCH 374/642] Change mechanism for invoking toggling captions. --- plugins/imagebase/plugin.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 055f15b78ea..e29b03b9275 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -499,19 +499,15 @@ var featuresDefinitions = { caption: { setUp: function( editor ) { - var lastWidget; - editor.on( 'selectionChange', function() { - var widget = getFocusedWidget( editor ); - - if ( lastWidget ) { - lastWidget._toggleCaption(); - } + var widgets = editor.widgets.instances, + i; - if ( widget && CKEDITOR.tools.indexOf( widget.features, 'caption' ) !== -1 ) { - widget._toggleCaption(); - - lastWidget = widget; + for ( i in widgets ) { + if ( widgets[ i ].features && + CKEDITOR.tools.array.indexOf( widgets[ i ].features, 'caption' ) !== -1 ) { + widgets[ i ]._toggleCaption(); + } } } ); }, From 9a68a5a850f13228dab7dd41d67761c141ac4e10 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 18:20:07 +0100 Subject: [PATCH 375/642] Add placeholder. --- plugins/imagebase/plugin.js | 30 ++++++++++++++++++++------ plugins/imagebase/styles/imagebase.css | 4 ++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index e29b03b9275..eb6e933fd03 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -496,17 +496,21 @@ return caption; } + function isEmptyOrHasPlaceholder( widget ) { + return !widget.editables.caption.getData() || widget.parts.caption.hasAttribute( 'data-cke-placeholder' ); + } + var featuresDefinitions = { caption: { setUp: function( editor ) { - editor.on( 'selectionChange', function() { + editor.on( 'selectionChange', function( evt ) { var widgets = editor.widgets.instances, i; for ( i in widgets ) { if ( widgets[ i ].features && CKEDITOR.tools.array.indexOf( widgets[ i ].features, 'caption' ) !== -1 ) { - widgets[ i ]._toggleCaption(); + widgets[ i ]._toggleCaption( evt.data.path.lastElement ); } } } ); @@ -520,13 +524,25 @@ this._toggleCaption(); }, - _toggleCaption: function() { - var isFocused = getFocusedWidget( this.editor ) === this; + _toggleCaption: function( sender ) { + var isFocused = getFocusedWidget( this.editor ) === this, + caption = this.parts.caption, + editable = this.editables.caption; if ( isFocused ) { - this.parts.caption.removeAttribute( 'data-cke-hidden' ); - } else if ( !this.editables.caption.getData() ) { - this.parts.caption.setAttribute( 'data-cke-hidden', true ); + caption.removeAttribute( 'data-cke-hidden' ); + + if ( !editable.getData() ) { + caption.setAttribute( 'data-cke-placeholder', true ); + editable.setData( 'Fill me' ); + } else if ( sender.equals( caption ) && sender.hasAttribute( 'data-cke-placeholder' ) ) { + editable.setData( '' ); + caption.removeAttribute( 'data-cke-placeholder' ); + } + } else if ( isEmptyOrHasPlaceholder( this ) ) { + caption.setAttribute( 'data-cke-hidden', true ); + caption.removeAttribute( 'data-cke-placeholder' ); + editable.setData( '' ); } } }, diff --git a/plugins/imagebase/styles/imagebase.css b/plugins/imagebase/styles/imagebase.css index 3845865c5a3..91589d678f5 100644 --- a/plugins/imagebase/styles/imagebase.css +++ b/plugins/imagebase/styles/imagebase.css @@ -1,3 +1,7 @@ [data-cke-hidden] { display: none; } + +[data-cke-placeholder] { + color: rgba( 0, 0, 0, .4 ); +} From 18fade8a3eeeea5888646a58a5a9e234cfe6efd1 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 18:20:44 +0100 Subject: [PATCH 376/642] Add unit tests. --- tests/plugins/imagebase/features/caption.js | 69 ++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index bad858a58d7..e7867f649ae 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -51,6 +51,10 @@ try { assertVisibility( caption, options.initial, 'caption visibility (initial)' ); + if ( options.onInit ) { + options.onInit( widget ); + } + widget.focus(); assertVisibility( caption, options.focus, 'caption visibility (focus)' ); @@ -64,6 +68,10 @@ range.select(); assertVisibility( caption, options.blur, 'caption visibility (blur)' ); + + if ( options.onBlur ) { + options.onBlur( widget ); + } } catch ( error ) { assert.fail( 'Error occured: ' + error ); } @@ -116,6 +124,23 @@ }; } + function fillInCaption( widget, content ) { + widget.parts.caption.focus(); + widget.editables.caption.setData( content ); + } + + function assertPlaceholder( widget, isVisible ) { + var caption = widget.parts.caption, + editable = widget.editables.caption; + + assert[ 'is' + ( isVisible ? 'True' : 'False' ) ]( caption.hasAttribute( 'data-cke-placeholder' ), + 'Placeholder visibility' ); + + if ( isVisible ) { + assert.areSame( 'Fill me', editable.getData(), 'Placeholder value' ); + } + } + var tests = { 'test upcasting widget without figcaption element': function( editor, bot ) { addTestWidget( editor ); @@ -160,7 +185,8 @@ blur: true, onFocus: function( widget ) { - widget.editables.caption.setData( 'Test' ); + assertPlaceholder( widget, true ); + fillInCaption( widget, 'Test' ); } } ), @@ -171,7 +197,8 @@ blur: false, onFocus: function( widget ) { - widget.editables.caption.setData( '' ); + assertPlaceholder( widget, false ); + fillInCaption( widget, '' ); } } ), @@ -204,6 +231,44 @@ onFocus: function( widget ) { widget.wrapper.remove(); } + } ), + + 'test placeholder visibility (widget with empty caption)': createToggleTest( { + fixture: 'toggleOneEmpty', + initial: false, + focus: true, + blur: false, + + onInit: function( widget ) { + assertPlaceholder( widget, false ); + }, + + onFocus: function( widget ) { + assertPlaceholder( widget, true ); + }, + + onBlur: function( widget ) { + assertPlaceholder( widget, false ); + } + } ), + + 'test placeholder visibility (widget with non-empty caption)': createToggleTest( { + fixture: 'toggleOne', + initial: true, + focus: true, + blur: true, + + onInit: function( widget ) { + assertPlaceholder( widget, false ); + }, + + onFocus: function( widget ) { + assertPlaceholder( widget, false ); + }, + + onBlur: function( widget ) { + assertPlaceholder( widget, false ); + } } ) }; From dce593ede351900564f3da662588d11a9ce3bd8c Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 18:23:55 +0100 Subject: [PATCH 377/642] Add lang entry for placeholder. --- plugins/imagebase/lang/en.js | 2 +- plugins/imagebase/plugin.js | 2 +- tests/plugins/imagebase/features/caption.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/imagebase/lang/en.js b/plugins/imagebase/lang/en.js index 18ccf9a3e50..78e72aa73bd 100644 --- a/plugins/imagebase/lang/en.js +++ b/plugins/imagebase/lang/en.js @@ -4,5 +4,5 @@ */ CKEDITOR.plugins.setLang( 'imagebase', 'en', { - captionPlaceholder: 'Caption' + captionPlaceholder: 'Enter image caption' } ); diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index eb6e933fd03..0e2c5e462e5 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -534,7 +534,7 @@ if ( !editable.getData() ) { caption.setAttribute( 'data-cke-placeholder', true ); - editable.setData( 'Fill me' ); + editable.setData( this.editor.lang.imagebase.captionPlaceholder ); } else if ( sender.equals( caption ) && sender.hasAttribute( 'data-cke-placeholder' ) ) { editable.setData( '' ); caption.removeAttribute( 'data-cke-placeholder' ); diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index e7867f649ae..7a00d2b9250 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -137,7 +137,7 @@ 'Placeholder visibility' ); if ( isVisible ) { - assert.areSame( 'Fill me', editable.getData(), 'Placeholder value' ); + assert.areSame( widget.editor.lang.imagebase.captionPlaceholder, editable.getData(), 'Placeholder value' ); } } From a1e10d09183b33e953313b4b3726e18a3d7f49e6 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 18:24:08 +0100 Subject: [PATCH 378/642] Add manual test. --- .../imagebase/features/manual/caption.html | 34 +++++++++++++++++++ .../imagebase/features/manual/caption.md | 11 ++++++ 2 files changed, 45 insertions(+) create mode 100644 tests/plugins/imagebase/features/manual/caption.html create mode 100644 tests/plugins/imagebase/features/manual/caption.md diff --git a/tests/plugins/imagebase/features/manual/caption.html b/tests/plugins/imagebase/features/manual/caption.html new file mode 100644 index 00000000000..132af60085e --- /dev/null +++ b/tests/plugins/imagebase/features/manual/caption.html @@ -0,0 +1,34 @@ +
+

Widget with caption:

+
+ foo +
+

Widget with empty caption:

+
+ + foo + +
+
+

Widget with caption:

+
+ + foo + +
Test caption
+
+
+ + diff --git a/tests/plugins/imagebase/features/manual/caption.md b/tests/plugins/imagebase/features/manual/caption.md new file mode 100644 index 00000000000..c9641039799 --- /dev/null +++ b/tests/plugins/imagebase/features/manual/caption.md @@ -0,0 +1,11 @@ +@bender-tags: 4.8.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, imagebase, link, htmlwriter, elementspath + +Check if caption is working correctly: + +* In source mode every widget contains `figcaption` element. +* In source mode there are no attributes for any `figcaption` element. +* If caption is empty, it's hidden when widget is blurred. +* If caption is empty, it's shown when widget is focused. +* If caption is empty, it contains placeholder text. From 7394de003ccbef8162141ebb18a5589c63e78e60 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 18:27:49 +0100 Subject: [PATCH 379/642] Small refactoring of toggling placeholder. --- plugins/imagebase/plugin.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 0e2c5e462e5..bcbdf9f0e86 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -500,6 +500,16 @@ return !widget.editables.caption.getData() || widget.parts.caption.hasAttribute( 'data-cke-placeholder' ); } + function addPlaceholder( widget ) { + widget.parts.caption.setAttribute( 'data-cke-placeholder', true ); + widget.editables.caption.setData( widget.editor.lang.imagebase.captionPlaceholder ); + } + + function removePlaceholder( widget ) { + widget.parts.caption.removeAttribute( 'data-cke-placeholder' ); + widget.editables.caption.setData( '' ); + } + var featuresDefinitions = { caption: { setUp: function( editor ) { @@ -533,16 +543,13 @@ caption.removeAttribute( 'data-cke-hidden' ); if ( !editable.getData() ) { - caption.setAttribute( 'data-cke-placeholder', true ); - editable.setData( this.editor.lang.imagebase.captionPlaceholder ); + addPlaceholder( this ); } else if ( sender.equals( caption ) && sender.hasAttribute( 'data-cke-placeholder' ) ) { - editable.setData( '' ); - caption.removeAttribute( 'data-cke-placeholder' ); + removePlaceholder( this ); } } else if ( isEmptyOrHasPlaceholder( this ) ) { caption.setAttribute( 'data-cke-hidden', true ); - caption.removeAttribute( 'data-cke-placeholder' ); - editable.setData( '' ); + removePlaceholder( this ); } } }, From 257764951b770c564adc0aabc3e930a41e7d45fe Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 18:36:28 +0100 Subject: [PATCH 380/642] Add some API docs. --- plugins/imagebase/plugin.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index bcbdf9f0e86..2f007feb739 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -534,6 +534,14 @@ this._toggleCaption(); }, + /** + * Method used inside {@link CKEDITOR.editor#event-selectionChange} event to decide if caption for given widget + * should be displayed and should contain placeholder text. + * + * @private + * @member CKEDITOR.plugins.imagebase.featuresDefinitions.caption + * @param {CKEDITOR.dom.element} sender Element, which triggered `selectionChange` event + */ _toggleCaption: function( sender ) { var isFocused = getFocusedWidget( this.editor ) === this, caption = this.parts.caption, From 9e858d9ac7e9ae898c0166e94414c94af9fd2f85 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 18:38:00 +0100 Subject: [PATCH 381/642] Add caption feature to easyimage. --- plugins/easyimage/plugin.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 7be991bff2b..34d6007299e 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -279,6 +279,7 @@ } widgetDefinition = CKEDITOR.plugins.imagebase.addFeature( editor, 'upload', widgetDefinition ); + widgetDefinition = CKEDITOR.plugins.imagebase.addFeature( editor, 'caption', widgetDefinition ); CKEDITOR.plugins.imagebase.addImageWidget( editor, WIDGET_NAME, widgetDefinition ); } From f451b357bdfed348f70abcbeed97a45319d45ab7 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 16 Nov 2017 18:42:10 +0100 Subject: [PATCH 382/642] Fix failing test in Safari. --- tests/plugins/imagebase/features/caption.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 7a00d2b9250..17b9a678f87 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -125,7 +125,13 @@ } function fillInCaption( widget, content ) { + var range = widget.editor.createRange(); + + range.setStart( widget.parts.caption.getChild( 0 ), 1 ); + range.collapse(); + range.select(); widget.parts.caption.focus(); + widget.editables.caption.setData( content ); } From 277f5f32a1439ffb86bf437cdef61087c4126133 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 28 Dec 2017 18:31:48 +0100 Subject: [PATCH 383/642] Added assert.isNotMatching assertion. --- tests/_benderjs/ckeditor/static/extensions.js | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/_benderjs/ckeditor/static/extensions.js b/tests/_benderjs/ckeditor/static/extensions.js index 68ec37e9e29..2bdbcd5b63a 100644 --- a/tests/_benderjs/ckeditor/static/extensions.js +++ b/tests/_benderjs/ckeditor/static/extensions.js @@ -43,10 +43,17 @@ ); } - bender.assert.isMatching = function( expected, actual, message ) { + /* + * @param {RegExp} expected RegExp that must be matched. + * @param {String} actual String value to be tested. + * @param {String} [message] + * @param {Boolean} [reversed=false] If `true` will reverse assertion, and ensure that pattern is not included. + */ + bender.assert.isMatching = function( expected, actual, message, reversed ) { YTest.Assert._increment(); + var desiredMatchResult = reversed ? false : true; // Using regexp.test may lead to unpredictable bugs when using global flag for regexp. - if ( typeof actual != 'string' || !actual.match( expected ) ) { + if ( typeof actual != 'string' || !!actual.match( expected ) !== desiredMatchResult ) { throw new YTest.ComparisonFailure( YTest.Assert._formatMessage( message, 'Value should match expected pattern.' ), expected.toString(), actual @@ -54,6 +61,15 @@ } }; + /* + * @param {RegExp} expected RegExp that **must not** be matched. + * @param {String} actual String value to be tested. + * @param {String} [message] + */ + bender.assert.isNotMatching = function( expected, actual, message ) { + this.isMatching( expected, actual, message || 'Value can not match the pattern.', true ); + }; + /** * Asserts that `innerHTML`-like HTML strings are equal. See the {@link bender.tools.html#compareInnerHtml} * method for more information. From a71aecd9abcca71f564fa80b977c79c1b8e1c0a6 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 28 Dec 2017 18:33:11 +0100 Subject: [PATCH 384/642] Tests: added unit test case ensuring that caption placeholder is not leaked into output markup. --- tests/plugins/imagebase/features/caption.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 17b9a678f87..f92dec11237 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -275,6 +275,15 @@ onBlur: function( widget ) { assertPlaceholder( widget, false ); } + } ), + + 'test caption placeholder is not outputted': createToggleTest( { + fixture: 'toggleOneEmpty', + focus: true, + + onFocus: function( widget ) { + assert.isNotMatching( /Enter image caption/, widget.editor.getData() ); + } } ) }; From 7e116d8118db56b8dd3c8bb5f50d479290903392 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 30 Dec 2017 16:09:36 +0100 Subject: [PATCH 385/642] Introduce hasWidgeetFeature private function. --- plugins/imagebase/plugin.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 2f007feb739..9d30746cc09 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -32,9 +32,13 @@ } } + function hasWidgetFeature( widget, feature ) { + return widget.features && CKEDITOR.tools.array.indexOf( widget.features, feature ) !== -1; + } + function getLinkFeature() { function isLinkable( widget ) { - return widget && widget.features && CKEDITOR.tools.array.indexOf( widget.features, 'link' ) !== -1; + return widget && hasWidgetFeature( widget, 'link' ); } function addLinkAttributes( editor, linkElement, linkData ) { @@ -518,8 +522,7 @@ i; for ( i in widgets ) { - if ( widgets[ i ].features && - CKEDITOR.tools.array.indexOf( widgets[ i ].features, 'caption' ) !== -1 ) { + if ( hasWidgetFeature( widgets[ i ], 'caption' ) ) { widgets[ i ]._toggleCaption( evt.data.path.lastElement ); } } From f00f76b71bf944e3ec558f5044843472e53c9a34 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 30 Dec 2017 16:52:29 +0100 Subject: [PATCH 386/642] Close caption feature in separate scope. --- plugins/imagebase/plugin.js | 47 ++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 9d30746cc09..9bc0480dfd6 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -489,33 +489,33 @@ return ret; } - function createCaption( widget ) { - var element = widget.element, - caption = element.getDocument().createElement( 'figcaption' ), - definition = widget.editor.widgets.registered[ widget.name ]; + function getCaptionFeature() { + function createCaption( widget ) { + var element = widget.element, + caption = element.getDocument().createElement( 'figcaption' ), + definition = widget.editor.widgets.registered[ widget.name ]; - element.append( caption ); - widget.initEditable( 'caption', definition.editables.caption ); + element.append( caption ); + widget.initEditable( 'caption', definition.editables.caption ); - return caption; - } + return caption; + } - function isEmptyOrHasPlaceholder( widget ) { - return !widget.editables.caption.getData() || widget.parts.caption.hasAttribute( 'data-cke-placeholder' ); - } + function isEmptyOrHasPlaceholder( widget ) { + return !widget.editables.caption.getData() || widget.parts.caption.hasAttribute( 'data-cke-placeholder' ); + } - function addPlaceholder( widget ) { - widget.parts.caption.setAttribute( 'data-cke-placeholder', true ); - widget.editables.caption.setData( widget.editor.lang.imagebase.captionPlaceholder ); - } + function addPlaceholder( widget ) { + widget.parts.caption.setAttribute( 'data-cke-placeholder', true ); + widget.editables.caption.setData( widget.editor.lang.imagebase.captionPlaceholder ); + } - function removePlaceholder( widget ) { - widget.parts.caption.removeAttribute( 'data-cke-placeholder' ); - widget.editables.caption.setData( '' ); - } + function removePlaceholder( widget ) { + widget.parts.caption.removeAttribute( 'data-cke-placeholder' ); + widget.editables.caption.setData( '' ); + } - var featuresDefinitions = { - caption: { + return { setUp: function( editor ) { editor.on( 'selectionChange', function( evt ) { var widgets = editor.widgets.instances, @@ -563,8 +563,11 @@ removePlaceholder( this ); } } - }, + }; + } + var featuresDefinitions = { + caption: getCaptionFeature(), upload: getUploadFeature(), link: getLinkFeature() }; From 31020d69ba71213f17aa1da2a31bd1ce58c74139 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 30 Dec 2017 17:08:48 +0100 Subject: [PATCH 387/642] Refactor access to data attributes. --- plugins/imagebase/plugin.js | 12 ++++++------ tests/plugins/imagebase/features/caption.js | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 9bc0480dfd6..a2bb138abd7 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -502,16 +502,16 @@ } function isEmptyOrHasPlaceholder( widget ) { - return !widget.editables.caption.getData() || widget.parts.caption.hasAttribute( 'data-cke-placeholder' ); + return !widget.editables.caption.getData() || widget.parts.caption.data( 'cke-placeholder' ); } function addPlaceholder( widget ) { - widget.parts.caption.setAttribute( 'data-cke-placeholder', true ); + widget.parts.caption.data( 'cke-placeholder', true ); widget.editables.caption.setData( widget.editor.lang.imagebase.captionPlaceholder ); } function removePlaceholder( widget ) { - widget.parts.caption.removeAttribute( 'data-cke-placeholder' ); + widget.parts.caption.data( 'cke-placeholder', false ); widget.editables.caption.setData( '' ); } @@ -551,15 +551,15 @@ editable = this.editables.caption; if ( isFocused ) { - caption.removeAttribute( 'data-cke-hidden' ); + caption.data( 'cke-hidden', false ); if ( !editable.getData() ) { addPlaceholder( this ); - } else if ( sender.equals( caption ) && sender.hasAttribute( 'data-cke-placeholder' ) ) { + } else if ( sender.equals( caption ) && sender.data( 'cke-placeholder' ) ) { removePlaceholder( this ); } } else if ( isEmptyOrHasPlaceholder( this ) ) { - caption.setAttribute( 'data-cke-hidden', true ); + caption.data( 'cke-hidden', true ); removePlaceholder( this ); } } diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index f92dec11237..07370966cd6 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -35,7 +35,7 @@ } function assertVisibility( caption, isVisible, msg ) { - assert[ 'is' + ( isVisible ? 'False' : 'True' ) ]( caption.hasAttribute( 'data-cke-hidden' ), msg ); + assert[ 'is' + ( isVisible ? 'False' : 'True' ) ]( !!caption.data( 'cke-hidden' ), msg ); } function createToggleTest( options ) { @@ -139,7 +139,7 @@ var caption = widget.parts.caption, editable = widget.editables.caption; - assert[ 'is' + ( isVisible ? 'True' : 'False' ) ]( caption.hasAttribute( 'data-cke-placeholder' ), + assert[ 'is' + ( isVisible ? 'True' : 'False' ) ]( !!caption.data( 'cke-placeholder' ), 'Placeholder visibility' ); if ( isVisible ) { From 220802c6660b61a8fac3e6b35e11ae8bdd399557 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 30 Dec 2017 17:15:53 +0100 Subject: [PATCH 388/642] Simplify access to widget's definition. --- plugins/imagebase/plugin.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index a2bb138abd7..511644ed9ee 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -492,11 +492,10 @@ function getCaptionFeature() { function createCaption( widget ) { var element = widget.element, - caption = element.getDocument().createElement( 'figcaption' ), - definition = widget.editor.widgets.registered[ widget.name ]; + caption = element.getDocument().createElement( 'figcaption' ); element.append( caption ); - widget.initEditable( 'caption', definition.editables.caption ); + widget.initEditable( 'caption', widget.definition.editables.caption ); return caption; } From 037b149791f59c044a517d7b71ebf4ca8840d169 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 30 Dec 2017 18:09:36 +0100 Subject: [PATCH 389/642] Add integration with ACF. --- plugins/imagebase/plugin.js | 12 +++++++++++- tests/plugins/imagebase/features/caption.js | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 511644ed9ee..b12e5a18169 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -516,10 +516,16 @@ return { setUp: function( editor ) { - editor.on( 'selectionChange', function( evt ) { + var listener; + + listener = editor.on( 'selectionChange', function( evt ) { var widgets = editor.widgets.instances, i; + if ( !editor.filter.check( 'figcaption' ) ) { + return listener.removeListener(); + } + for ( i in widgets ) { if ( hasWidgetFeature( widgets[ i ], 'caption' ) ) { widgets[ i ]._toggleCaption( evt.data.path.lastElement ); @@ -529,6 +535,10 @@ }, init: function() { + if ( !this.editor.filter.check( 'figcaption' ) ) { + return; + } + if ( !this.parts.caption ) { this.parts.caption = createCaption( this ); } diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 07370966cd6..c0633eedcb0 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -288,5 +288,23 @@ }; tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); + + tests[ 'test integration with ACF' ] = function() { + bender.editorBot.create( { + name: 'acf_integration', + config: { + disallowedContent: 'figcaption' + } + }, function( bot ) { + var editor = bot.editor; + + addTestWidget( editor ); + + bot.setData( getFixture( 'toggleOneEmpty' ), function() { + assert.isFalse( !!widgetTestsTools.getWidgetByDOMOffset( editor, 0 ).parts.caption, 'Caption presence' ); + } ); + } ); + }; + bender.test( tests ); } )(); From aef8d4e42437edf4f99a30f3b8d015592a848dab Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 30 Dec 2017 18:12:53 +0100 Subject: [PATCH 390/642] Rename _toggleCaption to _refreshCaption. --- plugins/imagebase/plugin.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index b12e5a18169..723984b068b 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -528,7 +528,7 @@ for ( i in widgets ) { if ( hasWidgetFeature( widgets[ i ], 'caption' ) ) { - widgets[ i ]._toggleCaption( evt.data.path.lastElement ); + widgets[ i ]._refreshCaption( evt.data.path.lastElement ); } } } ); @@ -543,7 +543,7 @@ this.parts.caption = createCaption( this ); } - this._toggleCaption(); + this._refreshCaption(); }, /** @@ -554,7 +554,7 @@ * @member CKEDITOR.plugins.imagebase.featuresDefinitions.caption * @param {CKEDITOR.dom.element} sender Element, which triggered `selectionChange` event */ - _toggleCaption: function( sender ) { + _refreshCaption: function( sender ) { var isFocused = getFocusedWidget( this.editor ) === this, caption = this.parts.caption, editable = this.editables.caption; From daf2cc3fe11c672f0961a6d414642253ce774062 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 30 Dec 2017 19:11:05 +0100 Subject: [PATCH 391/642] Optimize selectionChange listener. --- plugins/imagebase/plugin.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 723984b068b..6be8720ed17 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -514,22 +514,30 @@ widget.editables.caption.setData( '' ); } + function toggleVisibility( caption, isVisible ) { + caption.data( 'cke-active', isVisible ); + caption.data( 'cke-hidden', !isVisible ); + } + return { setUp: function( editor ) { var listener; listener = editor.on( 'selectionChange', function( evt ) { - var widgets = editor.widgets.instances, - i; + var widgets = editor.widgets, + focused = widgets.focused, + previous = widgets.getByElement( editor.editable().findOne( 'figcaption[data-cke-active]' ) ); if ( !editor.filter.check( 'figcaption' ) ) { return listener.removeListener(); } - for ( i in widgets ) { - if ( hasWidgetFeature( widgets[ i ], 'caption' ) ) { - widgets[ i ]._refreshCaption( evt.data.path.lastElement ); - } + if ( focused && hasWidgetFeature( focused, 'caption' ) ) { + focused._refreshCaption( evt.data.path.lastElement ); + } + + if ( previous && hasWidgetFeature( previous, 'caption' ) ) { + previous._refreshCaption( evt.data.path.lastElement ); } } ); }, @@ -560,7 +568,7 @@ editable = this.editables.caption; if ( isFocused ) { - caption.data( 'cke-hidden', false ); + toggleVisibility( caption, true ); if ( !editable.getData() ) { addPlaceholder( this ); @@ -568,7 +576,7 @@ removePlaceholder( this ); } } else if ( isEmptyOrHasPlaceholder( this ) ) { - caption.data( 'cke-hidden', true ); + toggleVisibility( caption, false ); removePlaceholder( this ); } } From 70ad19a0e9d5544ee842ab050f27d1a678e61c94 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 30 Dec 2017 19:13:05 +0100 Subject: [PATCH 392/642] Reduce reflows while switching visibility of the caption. --- plugins/imagebase/plugin.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 6be8720ed17..bb6e26f8709 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -568,16 +568,16 @@ editable = this.editables.caption; if ( isFocused ) { - toggleVisibility( caption, true ); - if ( !editable.getData() ) { addPlaceholder( this ); } else if ( sender.equals( caption ) && sender.data( 'cke-placeholder' ) ) { removePlaceholder( this ); } + + toggleVisibility( caption, true ); } else if ( isEmptyOrHasPlaceholder( this ) ) { - toggleVisibility( caption, false ); removePlaceholder( this ); + toggleVisibility( caption, false ); } } }; From f84c7f01a6f3aa55a945b83105b88748c1200cd2 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Fri, 5 Jan 2018 12:17:35 +0100 Subject: [PATCH 393/642] Improve test stability in IE11 and Edge. --- tests/plugins/imagebase/features/caption.js | 62 +++++++++++---------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index c0633eedcb0..5358aff5ae5 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -48,32 +48,28 @@ focusTrap = editor.editable().findOne( 'p' ).getChild( 0 ), range = editor.createRange(); - try { - assertVisibility( caption, options.initial, 'caption visibility (initial)' ); + assertVisibility( caption, options.initial, 'caption visibility (initial)' ); - if ( options.onInit ) { - options.onInit( widget ); - } + if ( options.onInit ) { + options.onInit( widget ); + } - widget.focus(); + widget.focus(); - assertVisibility( caption, options.focus, 'caption visibility (focus)' ); + assertVisibility( caption, options.focus, 'caption visibility (focus)' ); - if ( options.onFocus ) { - options.onFocus( widget ); - } + if ( options.onFocus ) { + options.onFocus( widget ); + } - range.setStart( focusTrap, 1 ); - range.collapse(); - range.select(); + range.setStart( focusTrap, 1 ); + range.collapse(); + range.select(); - assertVisibility( caption, options.blur, 'caption visibility (blur)' ); + assertVisibility( caption, options.blur, 'caption visibility (blur)' ); - if ( options.onBlur ) { - options.onBlur( widget ); - } - } catch ( error ) { - assert.fail( 'Error occured: ' + error ); + if ( options.onBlur ) { + options.onBlur( widget ); } } ); }; @@ -105,21 +101,22 @@ function assertOnFocus( widgets, expected ) { forEach( widgets, function( widget, i ) { - widget.focus(); + setTimeout( function() { + resume( function() { + assertMultipleVisibility( widgets, expected[ i ], 'focus widget#' + i ); + } ); + }, 50 ); - assertMultipleVisibility( widgets, expected[ i ], 'focus widget#' + i ); + widget.focus(); + wait(); } ); } bot.setData( getFixture( options.fixture ), function() { var widgets = getWidgets( editor, options.widgetsCount ); - try { - assertMultipleVisibility( widgets, options.initial, 'initial' ); - assertOnFocus( widgets, options.focus ); - } catch ( error ) { - assert.fail( 'Error occured: ' + error ); - } + assertMultipleVisibility( widgets, options.initial, 'initial' ); + assertOnFocus( widgets, options.focus ); } ); }; } @@ -127,12 +124,19 @@ function fillInCaption( widget, content ) { var range = widget.editor.createRange(); + setTimeout( function() { + resume( function() { + widget.editables.caption.setData( content ); + } ); + }, 50 ); + + // Simulate user clicking inside the caption. range.setStart( widget.parts.caption.getChild( 0 ), 1 ); range.collapse(); range.select(); - widget.parts.caption.focus(); - widget.editables.caption.setData( content ); + widget.parts.caption.focus(); + wait(); } function assertPlaceholder( widget, isVisible ) { From 98c07f7948cabdce0615142339a144a8355e0d04 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 11 Jan 2018 14:06:35 +0100 Subject: [PATCH 394/642] Fix getting focused widget. --- plugins/imagebase/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index bb6e26f8709..51e34d96b1c 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -525,7 +525,7 @@ listener = editor.on( 'selectionChange', function( evt ) { var widgets = editor.widgets, - focused = widgets.focused, + focused = getFocusedWidget( editor ), previous = widgets.getByElement( editor.editable().findOne( 'figcaption[data-cke-active]' ) ); if ( !editor.filter.check( 'figcaption' ) ) { From 29115b1da45d058559c02ba91ff1f60629c50a72 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 11 Jan 2018 14:07:09 +0100 Subject: [PATCH 395/642] Add unit test. --- tests/plugins/imagebase/features/caption.js | 22 ++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 5358aff5ae5..0bb0f145a1d 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -54,7 +54,11 @@ options.onInit( widget ); } - widget.focus(); + if ( options.customFocus ) { + options.customFocus( widget ); + } else { + widget.focus(); + } assertVisibility( caption, options.focus, 'caption visibility (focus)' ); @@ -212,6 +216,22 @@ } } ), + 'test toggling caption (one widget with non-empty caption that gets emptied; focus in caption)': createToggleTest( { + fixture: 'toggleOne', + initial: true, + focus: true, + blur: false, + + customFocus: function( widget ) { + widget.editables.caption.focus(); + }, + + onFocus: function( widget ) { + assertPlaceholder( widget, false ); + fillInCaption( widget, '' ); + } + } ), + 'test toggling captions (two widgets with empty captions)': createMultipleToggleTest( { fixture: 'toggleTwoEmpty', widgetsCount: 2, From 6b6cb5e797f8374d081f84efef716c046c73a1f4 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 2 Jan 2018 00:16:47 +0100 Subject: [PATCH 396/642] Move placeholder to CSS generated content. --- plugins/imagebase/plugin.js | 7 +++---- plugins/imagebase/styles/imagebase.css | 5 +++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 51e34d96b1c..dea1382ec00 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -501,12 +501,11 @@ } function isEmptyOrHasPlaceholder( widget ) { - return !widget.editables.caption.getData() || widget.parts.caption.data( 'cke-placeholder' ); + return !widget.editables.caption.getData() || !!widget.parts.caption.data( 'cke-placeholder' ); } function addPlaceholder( widget ) { - widget.parts.caption.data( 'cke-placeholder', true ); - widget.editables.caption.setData( widget.editor.lang.imagebase.captionPlaceholder ); + widget.parts.caption.data( 'cke-placeholder', widget.editor.lang.imagebase.captionPlaceholder ); } function removePlaceholder( widget ) { @@ -568,7 +567,7 @@ editable = this.editables.caption; if ( isFocused ) { - if ( !editable.getData() ) { + if ( !editable.getData() && !sender.equals( caption ) ) { addPlaceholder( this ); } else if ( sender.equals( caption ) && sender.data( 'cke-placeholder' ) ) { removePlaceholder( this ); diff --git a/plugins/imagebase/styles/imagebase.css b/plugins/imagebase/styles/imagebase.css index 91589d678f5..f0b76bd7c6d 100644 --- a/plugins/imagebase/styles/imagebase.css +++ b/plugins/imagebase/styles/imagebase.css @@ -5,3 +5,8 @@ [data-cke-placeholder] { color: rgba( 0, 0, 0, .4 ); } + +[data-cke-placeholder]::before { + display: inline; + content: attr( data-cke-placeholder ); +} From 978254cd0b4736a2bb3df4748e320d06d4c1dd29 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 2 Jan 2018 00:17:06 +0100 Subject: [PATCH 397/642] Simplify placeholder asserting. --- tests/plugins/imagebase/features/caption.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 0bb0f145a1d..c9837d11bf6 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -144,14 +144,12 @@ } function assertPlaceholder( widget, isVisible ) { - var caption = widget.parts.caption, - editable = widget.editables.caption; + var placeholder = widget.parts.caption.data( 'cke-placeholder' ); - assert[ 'is' + ( isVisible ? 'True' : 'False' ) ]( !!caption.data( 'cke-placeholder' ), - 'Placeholder visibility' ); + assert[ 'is' + ( isVisible ? 'True' : 'False' ) ]( !!placeholder, 'Placeholder visibility' ); if ( isVisible ) { - assert.areSame( widget.editor.lang.imagebase.captionPlaceholder, editable.getData(), 'Placeholder value' ); + assert.areSame( widget.editor.lang.imagebase.captionPlaceholder, placeholder, 'Placeholder value' ); } } From f68d7211d1e835bce4e2cbeeb434afcb27f31b52 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 2 Jan 2018 00:17:33 +0100 Subject: [PATCH 398/642] Add example of image without caption. --- plugins/easyimage/samples/easyimage.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/easyimage/samples/easyimage.html b/plugins/easyimage/samples/easyimage.html index 6a6afb0cc23..4e8b498d8b7 100644 --- a/plugins/easyimage/samples/easyimage.html +++ b/plugins/easyimage/samples/easyimage.html @@ -48,6 +48,9 @@

Easy Image Demo

Apollo 11

+
+ Saturn V carrying Apollo 11 +

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

Saturn V carrying Apollo 11 From 031024a7ebcc8ee80bd7c08d350ddaba6e743f5f Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 11 Jan 2018 17:25:16 +0100 Subject: [PATCH 399/642] Use a smaller image in Easy Image sample. --- plugins/easyimage/samples/easyimage.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/samples/easyimage.html b/plugins/easyimage/samples/easyimage.html index 4e8b498d8b7..9265654e0a0 100644 --- a/plugins/easyimage/samples/easyimage.html +++ b/plugins/easyimage/samples/easyimage.html @@ -49,7 +49,7 @@

Easy Image Demo

Apollo 11

- Saturn V carrying Apollo 11 + Saturn V carrying Apollo 11

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

From 39ddcdfd51d4ff77d951b031bd94223e9d5d715f Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 13 Jan 2018 21:35:36 +0100 Subject: [PATCH 400/642] Tests: added unit tests for case where caption remains visible after blurring the editor. --- tests/plugins/imagebase/features/caption.js | 93 ++++++++++++++++++++- 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index c9837d11bf6..d89387c028f 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -66,9 +66,13 @@ options.onFocus( widget ); } - range.setStart( focusTrap, 1 ); - range.collapse(); - range.select(); + if ( options.customBlur ) { + options.customBlur.call( this, widget ); + } else { + range.setStart( focusTrap, 1 ); + range.collapse(); + range.select(); + } assertVisibility( caption, options.blur, 'caption visibility (blur)' ); @@ -299,6 +303,89 @@ } } ), + 'test blurring editor hides visible, empty caption (widget focused)': createToggleTest( { + fixture: 'toggleOneEmpty', + initial: false, + focus: true, + blur: false, + + customBlur: function( widget ) { + var focusHost = CKEDITOR.document.getById( 'focusHost' ), + editor = widget.editor; + + widget.focus(); + + // Normally we'd listen to focusHost#focus event, but it happens **before** blur, which might handle + // this case. + widget.once( 'blur', function() { + resume( function() { + assertVisibility( widget.parts.caption, false, 'Caption visibility' ); + } ); + }, null, null, 9999 ); + + // Enforce focus event to be called asynchronously on all browsers. + setTimeout( function() { + focusHost.focus(); + }, 0 ); + + wait(); + } + } ), + + 'test blurring editor hides visible, empty caption (caption focused)': createToggleTest( { + fixture: 'toggleOneEmpty', + initial: false, + focus: true, + blur: false, + + customBlur: function( widget ) { + var focusHost = CKEDITOR.document.getById( 'focusHost' ), + editor = widget.editor; + + widget.parts.caption.focus(); + + // Normally we'd listen to focusHost#focus event, but it happens **before** blur, which might handle + // this case. + widget.parts.caption.once( 'blur', function() { + resume( function() { + assertVisibility( widget.parts.caption, false, 'Caption visibility' ); + } ); + }, null, null, 9999 ); + + // Enforce focus event to be called asynchronously on all browsers. + setTimeout( function() { + focusHost.focus(); + }, 0 ); + + wait(); + } + } ), + + 'test blurring editor does not hide the caption': createToggleTest( { + fixture: 'toggleOne', + initial: true, + focus: true, + blur: true, + + customBlur: function( widget ) { + var focusHost = CKEDITOR.document.getById( 'focusHost' ), + editor = widget.editor; + + focusHost.once( 'focus', function() { + resume( function() { + assertVisibility( widget.parts.caption, true, 'Caption visibility' ); + } ); + } ); + + // Enforce focus event to be called asynchronously on all browsers. + setTimeout( function() { + focusHost.focus(); + }, 0 ); + + wait(); + } + } ), + 'test caption placeholder is not outputted': createToggleTest( { fixture: 'toggleOneEmpty', focus: true, From 3b012684cd8bb38963997b5cf2ae63d22c2ce2e0 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 13 Jan 2018 22:15:28 +0100 Subject: [PATCH 401/642] Tests: added missing fixture. --- tests/plugins/imagebase/features/caption.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/plugins/imagebase/features/caption.html b/tests/plugins/imagebase/features/caption.html index fc685467dc8..e6db30c6c95 100644 --- a/tests/plugins/imagebase/features/caption.html +++ b/tests/plugins/imagebase/features/caption.html @@ -1,3 +1,5 @@ + +
@@ -45,4 +47,4 @@
Test caption
-
+
\ No newline at end of file From 0c89872218ed37916b41f5af5e1db8d90a0e9fcf Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 13 Jan 2018 21:47:34 +0100 Subject: [PATCH 402/642] Tests: extracted common code in Easy Image caption test. --- tests/plugins/imagebase/features/caption.js | 84 ++++++++++----------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index d89387c028f..99dd3cba5fb 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -68,7 +68,7 @@ if ( options.customBlur ) { options.customBlur.call( this, widget ); - } else { + } else { range.setStart( focusTrap, 1 ); range.collapse(); range.select(); @@ -157,6 +157,29 @@ } } + // Blurs the editor, by putting focus in an element outside of the editor. + // Resumes asserting, when the options.blurHost is blurred. + // Note that it calls wait(), so no code after this function is executed. + function blurEditor( options ) { + var focusHost = CKEDITOR.document.getById( 'focusHost' ), + blurHost = options.blurHost; + + // Normally we'd listen to focusHost#focus event, but it happens **before** blur, which might handle + // this case. + blurHost.once( 'blur', function() { + resume( function() { + options.assert(); + } ); + }, null, null, 9999 ); + + // Enforce focus event to be called asynchronously on all browsers. + setTimeout( function() { + focusHost.focus(); + }, 0 ); + + wait(); + } + var tests = { 'test upcasting widget without figcaption element': function( editor, bot ) { addTestWidget( editor ); @@ -310,25 +333,14 @@ blur: false, customBlur: function( widget ) { - var focusHost = CKEDITOR.document.getById( 'focusHost' ), - editor = widget.editor; - widget.focus(); - // Normally we'd listen to focusHost#focus event, but it happens **before** blur, which might handle - // this case. - widget.once( 'blur', function() { - resume( function() { + blurEditor( { + assert: function() { assertVisibility( widget.parts.caption, false, 'Caption visibility' ); - } ); - }, null, null, 9999 ); - - // Enforce focus event to be called asynchronously on all browsers. - setTimeout( function() { - focusHost.focus(); - }, 0 ); - - wait(); + }, + blurHost: widget + } ); } } ), @@ -339,25 +351,14 @@ blur: false, customBlur: function( widget ) { - var focusHost = CKEDITOR.document.getById( 'focusHost' ), - editor = widget.editor; - widget.parts.caption.focus(); - // Normally we'd listen to focusHost#focus event, but it happens **before** blur, which might handle - // this case. - widget.parts.caption.once( 'blur', function() { - resume( function() { + blurEditor( { + assert: function() { assertVisibility( widget.parts.caption, false, 'Caption visibility' ); - } ); - }, null, null, 9999 ); - - // Enforce focus event to be called asynchronously on all browsers. - setTimeout( function() { - focusHost.focus(); - }, 0 ); - - wait(); + }, + blurHost: widget.parts.caption + } ); } } ), @@ -368,21 +369,14 @@ blur: true, customBlur: function( widget ) { - var focusHost = CKEDITOR.document.getById( 'focusHost' ), - editor = widget.editor; + widget.focus(); - focusHost.once( 'focus', function() { - resume( function() { + blurEditor( { + assert: function() { assertVisibility( widget.parts.caption, true, 'Caption visibility' ); - } ); + }, + blurHost: widget } ); - - // Enforce focus event to be called asynchronously on all browsers. - setTimeout( function() { - focusHost.focus(); - }, 0 ); - - wait(); } } ), From 8d998301456ff4764d58f33b64abcb9ea104e3b1 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 13 Jan 2018 22:12:15 +0100 Subject: [PATCH 403/642] Tests: added manual tests for caption blur issue. --- .../features/manual/captionblur.html | 45 +++++++++++++++++++ .../imagebase/features/manual/captionblur.md | 34 ++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 tests/plugins/imagebase/features/manual/captionblur.html create mode 100644 tests/plugins/imagebase/features/manual/captionblur.md diff --git a/tests/plugins/imagebase/features/manual/captionblur.html b/tests/plugins/imagebase/features/manual/captionblur.html new file mode 100644 index 00000000000..4b4ce3bf88d --- /dev/null +++ b/tests/plugins/imagebase/features/manual/captionblur.html @@ -0,0 +1,45 @@ + + + + + +

Classic

+ +
+

Widget with empty caption:

+
+ foo +
+
+
+ +

Divarea

+ +
+

Widget with empty caption:

+
+ foo +
+
+
+ + + diff --git a/tests/plugins/imagebase/features/manual/captionblur.md b/tests/plugins/imagebase/features/manual/captionblur.md new file mode 100644 index 00000000000..7f083646b16 --- /dev/null +++ b/tests/plugins/imagebase/features/manual/captionblur.md @@ -0,0 +1,34 @@ +@bender-tags: 4.9.0, bug, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, imagebase, link, htmlwriter, elementspath + +## Caption - blurring widget + +1. Focus the **widget**, so that caption placeholder text appears. +1. Click outside of the editor, so that it losses the focus. + +### Expected + +Caption placeholder is removed. + +### Unexpected + +Caption placeholder is still visible. + +## Caption - blurring editable + +1. Focus the widget, so that caption placeholder text appears. +1. Focus caption editable, so that the text is hidden and edit caret appears. +1. Click outside of the editor, so that it losses the focus. + +### Expected + +Caption placeholder is removed. + +### Unexpected + +Caption is visible. Text might be removed, but there's still one line of extra height below the image. + +--- + +Repeat above tests with the "Divarea" editor. \ No newline at end of file From d9abc0d867044c5d82b0dbe8b0c4ad24d572d956 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 14 Jan 2018 15:24:59 +0100 Subject: [PATCH 404/642] Tests: fixed Permission Error for IE/Edge. --- tests/plugins/imagebase/features/caption.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 99dd3cba5fb..afa5e5f6156 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -42,6 +42,9 @@ return function( editor, bot ) { addTestWidget( editor ); + // Make sure the editor is focused, othrwise Edge/IE11 will throw Permission Denied error. + editor.focus(); + bot.setData( getFixture( options.fixture ), function() { var widget = widgetTestsTools.getWidgetByDOMOffset( editor, 0 ), caption = widget.parts.caption, From 5cee25843d6bc8e2337697b9f88a98ce640cff36 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sat, 13 Jan 2018 20:04:44 +0100 Subject: [PATCH 405/642] Tests, added a manual test for caption ACF customization. --- .../manual/captionacfcustomization.html | 47 +++++++++++++++++++ .../manual/captionacfcustomization.md | 19 ++++++++ 2 files changed, 66 insertions(+) create mode 100644 tests/plugins/imagebase/features/manual/captionacfcustomization.html create mode 100644 tests/plugins/imagebase/features/manual/captionacfcustomization.md diff --git a/tests/plugins/imagebase/features/manual/captionacfcustomization.html b/tests/plugins/imagebase/features/manual/captionacfcustomization.html new file mode 100644 index 00000000000..afee1d251af --- /dev/null +++ b/tests/plugins/imagebase/features/manual/captionacfcustomization.html @@ -0,0 +1,47 @@ +

Classic editor

+ +
+

Widget with caption:

+
+ foo +
Test + caption +
+
+
+ +

Divarea

+ +
+

Widget with caption:

+
+ foo +
Test + caption +
+
+
+ + diff --git a/tests/plugins/imagebase/features/manual/captionacfcustomization.md b/tests/plugins/imagebase/features/manual/captionacfcustomization.md new file mode 100644 index 00000000000..54ff055a7fa --- /dev/null +++ b/tests/plugins/imagebase/features/manual/captionacfcustomization.md @@ -0,0 +1,19 @@ +@bender-tags: 4.9.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, toolbar, imagebase, link, htmlwriter, elementspath, basicstyles + +# Customizing caption ACF + +1. Look at the widget caption. + + ## Expected + + "caption" text is not emphasized. + +1. Select any text in the caption. + + ## Expected + + Only Bold and Underline styles can be applied. Other styles are disabled. + +Repeat steps with Divarea editor. \ No newline at end of file From 741ffbfc348010fdae6dbe19d2b9184c0db2d663 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 14 Jan 2018 00:38:11 +0100 Subject: [PATCH 406/642] Tests: added a directory for Easy Image - Balloon Toolbar manual tests. Added test for issue with toolbar positioning. --- .../{ => balloontoolbar}/balloontoolbar.html | 0 .../{ => balloontoolbar}/balloontoolbar.md | 0 .../manual/balloontoolbar/caption.html | 42 +++++++++++++++++++ .../manual/balloontoolbar/caption.md | 26 ++++++++++++ 4 files changed, 68 insertions(+) rename tests/plugins/easyimage/manual/{ => balloontoolbar}/balloontoolbar.html (100%) rename tests/plugins/easyimage/manual/{ => balloontoolbar}/balloontoolbar.md (100%) create mode 100644 tests/plugins/easyimage/manual/balloontoolbar/caption.html create mode 100644 tests/plugins/easyimage/manual/balloontoolbar/caption.md diff --git a/tests/plugins/easyimage/manual/balloontoolbar.html b/tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.html similarity index 100% rename from tests/plugins/easyimage/manual/balloontoolbar.html rename to tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.html diff --git a/tests/plugins/easyimage/manual/balloontoolbar.md b/tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.md similarity index 100% rename from tests/plugins/easyimage/manual/balloontoolbar.md rename to tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.md diff --git a/tests/plugins/easyimage/manual/balloontoolbar/caption.html b/tests/plugins/easyimage/manual/balloontoolbar/caption.html new file mode 100644 index 00000000000..95d2e87d934 --- /dev/null +++ b/tests/plugins/easyimage/manual/balloontoolbar/caption.html @@ -0,0 +1,42 @@ + + +

Classic editor

+
+

Sample image:

+
+ foo +
+
+
+ +

Divarea editor

+
+

Sample image:

+
+ foo +
+
+
+ +

Inline editor

+
+

Sample image:

+
+ foo +
+
+
+ + diff --git a/tests/plugins/easyimage/manual/balloontoolbar/caption.md b/tests/plugins/easyimage/manual/balloontoolbar/caption.md new file mode 100644 index 00000000000..435f15a4c62 --- /dev/null +++ b/tests/plugins/easyimage/manual/balloontoolbar/caption.md @@ -0,0 +1,26 @@ +@bender-tags: 4.9.0, bug, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, undo, easyimage + +## Balloon positioning + +1. Focus Easy Image widget in the first editor. + ### Expected + + A balloon panel shows, pointing at middle bottom edge of the widget. +1. Put a collapsed selection inside of the caption. + ### Expected + + Balloon is hidden. +1. Move focus back to widget (by clicking anywhere on the image). + ### Expected + + Balloon panel shows, again in the same position. + + ### Unexpected + + Balloon panel points to the bottom edge **of an image**, overlapping the caption. + +--- + +Repeat above steps for all other editors. \ No newline at end of file From 4153b6f3bad2592cd36c8734f14357798b626869 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 14 Jan 2018 12:49:04 +0100 Subject: [PATCH 407/642] Tests: WIP extracted balloontoolbar related tests into a separate suite. Added integration test for balloon position after clicking the caption and focusing back the widget. --- tests/plugins/easyimage/balloontoolbar.js | 35 +++++------------------ tests/plugins/easyimage/commands.js | 30 ------------------- 2 files changed, 7 insertions(+), 58 deletions(-) diff --git a/tests/plugins/easyimage/balloontoolbar.js b/tests/plugins/easyimage/balloontoolbar.js index 2d51d61b6b1..e639d0140f1 100644 --- a/tests/plugins/easyimage/balloontoolbar.js +++ b/tests/plugins/easyimage/balloontoolbar.js @@ -1,5 +1,5 @@ /* bender-tags: editor,widget */ -/* bender-ckeditor-plugins: easyimage,toolbar,undo */ +/* bender-ckeditor-plugins: easyimage,toolbar,contextmenu,undo */ /* bender-include: _helpers/tools.js */ /* global easyImageTools */ @@ -24,19 +24,6 @@ return editor.balloonToolbars._contexts[ 0 ]; } - // Forces the Balloon Toolbar to be always drawn below the target. - function patchBalloonPositioning( toolbar ) { - var original = toolbar._view._getAlignments; - - toolbar._view._getAlignments = function() { - var ret = original.apply( this, arguments ); - - return { - 'bottom hcenter': ret[ 'bottom hcenter' ] - }; - }; - } - /* * Returns an expected balloon Y position for a given widget. * @@ -45,29 +32,23 @@ */ function getExpectedYOffset( widget ) { var editor = widget.editor, + wrapperPosition = widget.element.getDocumentPosition( CKEDITOR.document ), wrapperRect = widget.element.getClientRect(), toolbar = getEasyImageBalloonContext( editor ).toolbar, - ret = wrapperRect.bottom + toolbar._view.triangleHeight; - - if ( !editor.editable().isInline() ) { - // In case of classic editor we also need to include position of the editor iframe too. - ret += editor.window.getFrame().getClientRect().top; - } + ret = wrapperPosition.y + wrapperRect.height + toolbar._view.triangleHeight; return ret; } var testSuiteIframe = CKEDITOR.document.getWindow().getFrame(), - initialFrameHeight = testSuiteIframe && testSuiteIframe.getStyle( 'height' ), + initialFrameHeight = null, tests = { setUp: function() { - if ( CKEDITOR.env.ie && CKEDITOR.env.version < 11 ) { - assert.ignore(); - } - // This test checks real balloon panel positioning. To avoid affecting position with scroll offset, set the parent iframe height - // enough to contain entire content. Note that iframe is not present if the test suite is open in a separate window, or ran on IEs. + // enough to contain entire content. Note that some browsers like IE/Edge do not use the iframe but display results in a new + // window, so this is not needed there. if ( testSuiteIframe ) { + initialFrameHeight = testSuiteIframe.getStyle( 'height' ); testSuiteIframe.setStyle( 'height', '3000px' ); } }, @@ -117,8 +98,6 @@ var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ), toolbar = getEasyImageBalloonContext( editor ).toolbar; - patchBalloonPositioning( toolbar ); - widget.once( 'focus', function() { setTimeout( function() { var expectedY = getExpectedYOffset( widget ), diff --git a/tests/plugins/easyimage/commands.js b/tests/plugins/easyimage/commands.js index 77df51c0b6c..941a45c2fbe 100644 --- a/tests/plugins/easyimage/commands.js +++ b/tests/plugins/easyimage/commands.js @@ -179,36 +179,6 @@ assert.areSame( 'side', widget.data.type, 'Widget has correct type data' ); } ); - }, - - 'test balloontoolbar integration': function( editor, bot ) { - bot.setData( widgetHtml, function() { - var widget = editor.widgets.getByElement( editor.editable().findOne( 'figure' ) ), - toolbar = editor.balloonToolbars._contexts[ 0 ].toolbar; - - toolbar._view.once( 'show', function() { - easyImageTools.assertCommandsState( editor, { - easyimageFull: CKEDITOR.TRISTATE_ON, - easyimageSide: CKEDITOR.TRISTATE_OFF, - easyimageAlt: CKEDITOR.TRISTATE_OFF - } ); - - editor.once( 'afterCommandExec', function() { - resume( function() { - easyImageTools.assertCommandsState( editor, { - easyimageFull: CKEDITOR.TRISTATE_OFF, - easyimageSide: CKEDITOR.TRISTATE_ON, - easyimageAlt: CKEDITOR.TRISTATE_OFF - } ); - } ); - } ); - - editor.execCommand( 'easyimageSide' ); - } ); - - widget.focus(); - wait(); - } ); } }; From edaa28938bc70da0ad817d1e571f58ab6f9615bb Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 14 Jan 2018 13:30:54 +0100 Subject: [PATCH 408/642] Tests: extracted common Easy Image assertion. --- tests/plugins/easyimage/balloontoolbar.js | 6 ++---- tests/plugins/easyimage/commands.js | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/plugins/easyimage/balloontoolbar.js b/tests/plugins/easyimage/balloontoolbar.js index e639d0140f1..c8191e5dd78 100644 --- a/tests/plugins/easyimage/balloontoolbar.js +++ b/tests/plugins/easyimage/balloontoolbar.js @@ -41,14 +41,12 @@ } var testSuiteIframe = CKEDITOR.document.getWindow().getFrame(), - initialFrameHeight = null, + initialFrameHeight = testSuiteIframe && testSuiteIframe.getStyle( 'height' ), tests = { setUp: function() { // This test checks real balloon panel positioning. To avoid affecting position with scroll offset, set the parent iframe height - // enough to contain entire content. Note that some browsers like IE/Edge do not use the iframe but display results in a new - // window, so this is not needed there. + // enough to contain entire content. Note that iframe is not present if the test suite is open in a separate window, or ran on IEs. if ( testSuiteIframe ) { - initialFrameHeight = testSuiteIframe.getStyle( 'height' ); testSuiteIframe.setStyle( 'height', '3000px' ); } }, diff --git a/tests/plugins/easyimage/commands.js b/tests/plugins/easyimage/commands.js index 941a45c2fbe..cbdec1a63b7 100644 --- a/tests/plugins/easyimage/commands.js +++ b/tests/plugins/easyimage/commands.js @@ -1,7 +1,7 @@ /* bender-tags: editor,widget */ /* bender-ckeditor-plugins: easyimage,toolbar,contextmenu,undo */ /* bender-include: _helpers/tools.js */ -/* globals easyImageTools */ +/* global easyImageTools */ ( function() { 'use strict'; From 3465a32701712473e408e9698b10f02127a3af69 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Sun, 14 Jan 2018 13:48:31 +0100 Subject: [PATCH 409/642] Fixed an issue when Easy Image toolbar would have a wrong position. The issue happens if you have image widget with an empty caption, you have to click the widget to show the caption with a placeholder, then click on caption and back on the image. As a result balloon toolbar would overlap over the caption. --- plugins/imagebase/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index dea1382ec00..689c639235a 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -538,7 +538,7 @@ if ( previous && hasWidgetFeature( previous, 'caption' ) ) { previous._refreshCaption( evt.data.path.lastElement ); } - } ); + }, null, null, 9 ); }, init: function() { From 44f2f9f3c41d8cf4a5227ab1a0dea5a2da1df742 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sun, 14 Jan 2018 23:07:30 +0100 Subject: [PATCH 410/642] Fix missing images in manual test. --- .../easyimage/manual/balloontoolbar/balloontoolbar.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.html b/tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.html index d880e0da1eb..97d1169d037 100644 --- a/tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.html +++ b/tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.html @@ -2,7 +2,7 @@

Classic editor

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

- foo + foo
Test image

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

@@ -12,7 +12,7 @@

Divarea editor

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

- foo + foo
Test image

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

@@ -22,7 +22,7 @@

Inline editor

Apollo 11 was the spaceflight that landed the first humans, Americans Neil Armstrong and Buzz Aldrin, on the Moon on July 20, 1969, at 20:18 UTC. Armstrong became the first to step onto the lunar surface 6 hours later on July 21 at 02:56 UTC.

- foo + foo
Test image

Armstrong spent about three and a half two and a half hours outside the spacecraft, Aldrin slightly less; and together they collected 47.5 pounds (21.5 kg) of lunar material for return to Earth. A third member of the mission, Michael Collins, piloted the command spacecraft alone in lunar orbit until Armstrong and Aldrin returned to it for the trip back to Earth.

From 3438b0460c8159f1cb2267d808d4e0c7c476cf33 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 00:20:18 +0100 Subject: [PATCH 411/642] Fix failing unit test for smaller screens. --- tests/plugins/easyimage/balloontoolbar.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/plugins/easyimage/balloontoolbar.js b/tests/plugins/easyimage/balloontoolbar.js index c8191e5dd78..c235d3c40b3 100644 --- a/tests/plugins/easyimage/balloontoolbar.js +++ b/tests/plugins/easyimage/balloontoolbar.js @@ -48,6 +48,8 @@ // enough to contain entire content. Note that iframe is not present if the test suite is open in a separate window, or ran on IEs. if ( testSuiteIframe ) { testSuiteIframe.setStyle( 'height', '3000px' ); + } else { + CKEDITOR.document.getDocumentElement().setStyle( 'height', '3000px' ); } }, @@ -90,6 +92,9 @@ }, 'test balloontoolbar positioning': function( editor, bot ) { + // Force toolbar to always appear under the widget. + editor.container.getWindow().$.scroll( 0, editor.container.getDocumentPosition().y ); + var source = '
foo
'; bot.setData( source, function() { From d1f54932984d7ce789bd21dfb8e8d69380199e49 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 00:59:14 +0100 Subject: [PATCH 412/642] Fix incorrect placeholder behavior on editor's blur. --- plugins/imagebase/plugin.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 689c639235a..ac4d85c5095 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -23,6 +23,10 @@ var widgets = editor.widgets, currentActive = editor.focusManager.currentActive; + if ( !editor.focusManager.hasFocus ) { + return; + } + if ( widgets.focused ) { return widgets.focused; } @@ -520,25 +524,31 @@ return { setUp: function( editor ) { - var listener; + var listeners = []; - listener = editor.on( 'selectionChange', function( evt ) { - var widgets = editor.widgets, + function listener( evt ) { + var sender = evt.name === 'blur' ? editor.elementPath().lastElement : evt.data.path.lastElement, + widgets = editor.widgets, focused = getFocusedWidget( editor ), previous = widgets.getByElement( editor.editable().findOne( 'figcaption[data-cke-active]' ) ); if ( !editor.filter.check( 'figcaption' ) ) { - return listener.removeListener(); + return CKEDITOR.tools.array.forEach( listeners, function( listener ) { + listener.removeListener(); + } ); } if ( focused && hasWidgetFeature( focused, 'caption' ) ) { - focused._refreshCaption( evt.data.path.lastElement ); + focused._refreshCaption( sender ); } if ( previous && hasWidgetFeature( previous, 'caption' ) ) { - previous._refreshCaption( evt.data.path.lastElement ); + previous._refreshCaption( sender ); } - }, null, null, 9 ); + } + + listeners.push( editor.on( 'selectionChange', listener , null, null, 9 ) ); + listeners.push( editor.on( 'blur', listener ) ); }, init: function() { From 2db7a128174dc224e474fe58d994b9c4414e407e Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 01:05:33 +0100 Subject: [PATCH 413/642] Update manual test. --- .../imagebase/features/manual/caption.html | 80 ++++++++++++++++--- .../imagebase/features/manual/caption.md | 6 +- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/tests/plugins/imagebase/features/manual/caption.html b/tests/plugins/imagebase/features/manual/caption.html index 132af60085e..ad842bb2f5b 100644 --- a/tests/plugins/imagebase/features/manual/caption.html +++ b/tests/plugins/imagebase/features/manual/caption.html @@ -1,5 +1,53 @@ +

Classic editor

+
+

Widget without caption:

+
+ foo +
+

Widget with empty caption:

+
+ + foo + +
+

Widget with caption:

+
+ + foo + +
Test caption
+
+
+ +

Divarea editor

+ +
+

Widget without caption:

+
+ foo +
+

Widget with empty caption:

+
+ + foo + +
+
+

Widget with caption:

+
+ + foo + +
Test caption
+
+
+ +

Inline editor

+ +
+

Widget without caption:

foo
@@ -20,15 +68,25 @@
diff --git a/tests/plugins/imagebase/features/manual/caption.md b/tests/plugins/imagebase/features/manual/caption.md index c9641039799..201828ddad7 100644 --- a/tests/plugins/imagebase/features/manual/caption.md +++ b/tests/plugins/imagebase/features/manual/caption.md @@ -1,6 +1,6 @@ -@bender-tags: 4.8.0, feature, 932 +@bender-tags: 4.9.0, feature, 932 @bender-ui: collapsed -@bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, imagebase, link, htmlwriter, elementspath +@bender-ckeditor-plugins: sourcearea, sourcedialog, wysiwygarea, floatingspace, toolbar, imagebase, link, htmlwriter, elementspath Check if caption is working correctly: @@ -9,3 +9,5 @@ Check if caption is working correctly: * If caption is empty, it's hidden when widget is blurred. * If caption is empty, it's shown when widget is focused. * If caption is empty, it contains placeholder text. + +Repeat these checks for all editors. From b1c83494c353302487ae7b67dddd0843ba3b7c20 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 01:21:49 +0100 Subject: [PATCH 414/642] Remove redundant getWidgets function. --- tests/plugins/imagebase/features/caption.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index afa5e5f6156..38880fa3f3e 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -92,17 +92,6 @@ addTestWidget( editor ); - function getWidgets( editor, amount ) { - var i, - widgets = []; - - for ( i = 0; i < amount; i++ ) { - widgets.push( widgetTestsTools.getWidgetByDOMOffset( editor, i ) ); - } - - return widgets; - } - function assertMultipleVisibility( widgets, expected, msg ) { forEach( widgets, function( widget, i ) { assertVisibility( widget.parts.caption, expected[ i ], @@ -124,7 +113,7 @@ } bot.setData( getFixture( options.fixture ), function() { - var widgets = getWidgets( editor, options.widgetsCount ); + var widgets = widgetTestsTools.obj2Array( editor.widgets.instances ).slice( 0, options.widgetsCount ); assertMultipleVisibility( widgets, options.initial, 'initial' ); assertOnFocus( widgets, options.focus ); From 560b95a1a5cd72362e32a4327143acc78ca3cd35 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 01:44:15 +0100 Subject: [PATCH 415/642] Add check for path existence. --- plugins/imagebase/plugin.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index ac4d85c5095..6d387cacefa 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -527,7 +527,8 @@ var listeners = []; function listener( evt ) { - var sender = evt.name === 'blur' ? editor.elementPath().lastElement : evt.data.path.lastElement, + var path = evt.name === 'blur' ? editor.elementPath() : evt.data.path, + sender = path ? path.lastElement : null, widgets = editor.widgets, focused = getFocusedWidget( editor ), previous = widgets.getByElement( editor.editable().findOne( 'figcaption[data-cke-active]' ) ); @@ -579,7 +580,7 @@ if ( isFocused ) { if ( !editable.getData() && !sender.equals( caption ) ) { addPlaceholder( this ); - } else if ( sender.equals( caption ) && sender.data( 'cke-placeholder' ) ) { + } else if ( !sender || ( sender.equals( caption ) && sender.data( 'cke-placeholder' ) ) ) { removePlaceholder( this ); } From 063d36607257fc7669f34495c687a4c05553eb1d Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 01:44:57 +0100 Subject: [PATCH 416/642] Update assertion for blurring editor when focus is in caption unit test. --- tests/plugins/imagebase/features/caption.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 38880fa3f3e..6145b6b3e0c 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -349,7 +349,9 @@ assert: function() { assertVisibility( widget.parts.caption, false, 'Caption visibility' ); }, - blurHost: widget.parts.caption + // In case of blurring from caption, the host must be editor as blur for caption + // itself is fired before blurring listener. + blurHost: widget.editor } ); } } ), From 36c478706df7b534d420663388ea2e4a307a8e64 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 11:14:27 +0100 Subject: [PATCH 417/642] Add API docs for tests. --- tests/plugins/imagebase/features/caption.js | 24 +++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 6145b6b3e0c..70d92a305aa 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -38,6 +38,20 @@ assert[ 'is' + ( isVisible ? 'False' : 'True' ) ]( !!caption.data( 'cke-hidden' ), msg ); } + /* Simulate focusing and blurring image widget with caption, asserting caption visibility + * during each step. + * + * @param {Object} options + * @param {String} options.fixture Fixture's name. + * @param {Boolean} options.initial Caption visibility at the start of the test. + * @param {Boolean} options.focus Caption visibility after calling focus function. + * @param {Boolean} options.blur Caption visibility after calling blur function. + * @param {Boolean} options.onInit Callback to run at the beginning of the test. + * @param {Function} options.onFocus Callback to run after focus function. + * @param {Function} options.onBlur Callback to run after blur function. + * @param {Function} options.customFocus Function to be called instead of default focus function. + * @param {Function} options.customBlur Function to be called instead of default blur function. + */ function createToggleTest( options ) { return function( editor, bot ) { addTestWidget( editor ); @@ -86,6 +100,16 @@ }; } + /* Simulate focusing and blurring group of image widgets with captions, asserting caption visibility + * during each step. Assertions are made for every widget in the group. + * + * @param {Object} options + * @param {String} options.fixture Fixture's name. + * @param {Number} options.widgetsCount Number of widgets to test. + * @param {Boolean} options.initial Caption visibility at the start of the test. + * @param {Boolean} options.focus Caption visibility after calling focus function. + * @param {Boolean} options.blur Caption visibility after calling blur function. + */ function createMultipleToggleTest( options ) { return function( editor, bot ) { var forEach = CKEDITOR.tools.array.forEach; From 036e2cc8e6dad09ef171c528a102621fb04a3bca Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 12:57:47 +0100 Subject: [PATCH 418/642] Fix tests for multiple widgets. --- tests/plugins/imagebase/features/caption.js | 58 +++++++++++++++------ 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 70d92a305aa..5b3b7187ff9 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -34,8 +34,12 @@ return CKEDITOR.document.getById( name ).getHtml(); } - function assertVisibility( caption, isVisible, msg ) { + function assertVisibility( caption, isVisible, msg, callback ) { assert[ 'is' + ( isVisible ? 'False' : 'True' ) ]( !!caption.data( 'cke-hidden' ), msg ); + + if ( callback ) { + callback(); + } } /* Simulate focusing and blurring image widget with caption, asserting caption visibility @@ -112,28 +116,48 @@ */ function createMultipleToggleTest( options ) { return function( editor, bot ) { - var forEach = CKEDITOR.tools.array.forEach; - addTestWidget( editor ); - function assertMultipleVisibility( widgets, expected, msg ) { - forEach( widgets, function( widget, i ) { - assertVisibility( widget.parts.caption, expected[ i ], - 'caption#' + i + ' visibility (' + msg + ')' ); - } ); + function assertMultipleVisibility( widgets, expected, msg, callback, i ) { + var widget; + + i = i || 0; + + widget = widgets[ i ]; + assertVisibility( widget.parts.caption, expected[ i ], 'caption#' + i + ' visibility (' + msg + ')', + function() { + if ( i === widgets.length - 1 ) { + if ( callback ) { + callback(); + } + + return; + } + + assertMultipleVisibility( widgets, expected, msg, callback, ++i ); + } ); } - function assertOnFocus( widgets, expected ) { - forEach( widgets, function( widget, i ) { - setTimeout( function() { - resume( function() { - assertMultipleVisibility( widgets, expected[ i ], 'focus widget#' + i ); + function assertOnFocus( widgets, expected, i ) { + var widget; + + i = i || 0; + + widget = widgets[ i ]; + + setTimeout( function() { + resume( function() { + assertMultipleVisibility( widgets, expected[ i ], 'focus widget#' + i, function() { + if ( i === widgets.length - 1 ) { + return; + } + assertOnFocus( widgets, expected, ++i ); } ); - }, 50 ); + } ); + }, 50 ); - widget.focus(); - wait(); - } ); + widget.focus(); + wait(); } bot.setData( getFixture( options.fixture ), function() { From d0629d22d0e4bb30552e3ca209d2c3dede3c3e43 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 13:10:52 +0100 Subject: [PATCH 419/642] Rename toggleVisibility to setVisibility. --- plugins/imagebase/plugin.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 6d387cacefa..46bed59d1ff 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -517,7 +517,7 @@ widget.editables.caption.setData( '' ); } - function toggleVisibility( caption, isVisible ) { + function setVisibility( caption, isVisible ) { caption.data( 'cke-active', isVisible ); caption.data( 'cke-hidden', !isVisible ); } @@ -584,10 +584,10 @@ removePlaceholder( this ); } - toggleVisibility( caption, true ); + setVisibility( caption, true ); } else if ( isEmptyOrHasPlaceholder( this ) ) { removePlaceholder( this ); - toggleVisibility( caption, false ); + setVisibility( caption, false ); } } }; From 9c760274b463de1894fca3af695435949f064c5d Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 13:17:06 +0100 Subject: [PATCH 420/642] Rename data attributes. --- plugins/imagebase/plugin.js | 15 +++++++-------- plugins/imagebase/styles/imagebase.css | 8 ++++---- tests/plugins/imagebase/features/caption.js | 4 ++-- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 46bed59d1ff..4b805a9a81a 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -505,21 +505,20 @@ } function isEmptyOrHasPlaceholder( widget ) { - return !widget.editables.caption.getData() || !!widget.parts.caption.data( 'cke-placeholder' ); + return !widget.editables.caption.getData() || !!widget.parts.caption.data( 'cke-caption-placeholder' ); } function addPlaceholder( widget ) { - widget.parts.caption.data( 'cke-placeholder', widget.editor.lang.imagebase.captionPlaceholder ); + widget.parts.caption.data( 'cke-caption-placeholder', widget.editor.lang.imagebase.captionPlaceholder ); } function removePlaceholder( widget ) { - widget.parts.caption.data( 'cke-placeholder', false ); - widget.editables.caption.setData( '' ); + widget.parts.caption.data( 'cke-caption-placeholder', false ); } function setVisibility( caption, isVisible ) { - caption.data( 'cke-active', isVisible ); - caption.data( 'cke-hidden', !isVisible ); + caption.data( 'cke-caption-active', isVisible ); + caption.data( 'cke-caption-hidden', !isVisible ); } return { @@ -531,7 +530,7 @@ sender = path ? path.lastElement : null, widgets = editor.widgets, focused = getFocusedWidget( editor ), - previous = widgets.getByElement( editor.editable().findOne( 'figcaption[data-cke-active]' ) ); + previous = widgets.getByElement( editor.editable().findOne( 'figcaption[data-cke-caption-active]' ) ); if ( !editor.filter.check( 'figcaption' ) ) { return CKEDITOR.tools.array.forEach( listeners, function( listener ) { @@ -580,7 +579,7 @@ if ( isFocused ) { if ( !editable.getData() && !sender.equals( caption ) ) { addPlaceholder( this ); - } else if ( !sender || ( sender.equals( caption ) && sender.data( 'cke-placeholder' ) ) ) { + } else if ( !sender || ( sender.equals( caption ) && sender.data( 'cke-caption-placeholder' ) ) ) { removePlaceholder( this ); } diff --git a/plugins/imagebase/styles/imagebase.css b/plugins/imagebase/styles/imagebase.css index f0b76bd7c6d..353d3fa06fd 100644 --- a/plugins/imagebase/styles/imagebase.css +++ b/plugins/imagebase/styles/imagebase.css @@ -1,12 +1,12 @@ -[data-cke-hidden] { +[data-cke-caption-hidden] { display: none; } -[data-cke-placeholder] { +[data-cke-caption-placeholder] { color: rgba( 0, 0, 0, .4 ); } -[data-cke-placeholder]::before { +[data-cke-caption-placeholder]::before { display: inline; - content: attr( data-cke-placeholder ); + content: attr( data-cke-caption-placeholder ); } diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 5b3b7187ff9..8fdbbd30288 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -35,7 +35,7 @@ } function assertVisibility( caption, isVisible, msg, callback ) { - assert[ 'is' + ( isVisible ? 'False' : 'True' ) ]( !!caption.data( 'cke-hidden' ), msg ); + assert[ 'is' + ( isVisible ? 'False' : 'True' ) ]( !!caption.data( 'cke-caption-hidden' ), msg ); if ( callback ) { callback(); @@ -188,7 +188,7 @@ } function assertPlaceholder( widget, isVisible ) { - var placeholder = widget.parts.caption.data( 'cke-placeholder' ); + var placeholder = widget.parts.caption.data( 'cke-caption-placeholder' ); assert[ 'is' + ( isVisible ? 'True' : 'False' ) ]( !!placeholder, 'Placeholder visibility' ); From 4831b98327483ed37b5d4296481e215f2772f7d0 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 15 Jan 2018 15:37:27 +0100 Subject: [PATCH 421/642] Move placeholder color definition to pseudoelement block. --- plugins/imagebase/styles/imagebase.css | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/imagebase/styles/imagebase.css b/plugins/imagebase/styles/imagebase.css index 353d3fa06fd..91923af678b 100644 --- a/plugins/imagebase/styles/imagebase.css +++ b/plugins/imagebase/styles/imagebase.css @@ -2,11 +2,8 @@ display: none; } -[data-cke-caption-placeholder] { - color: rgba( 0, 0, 0, .4 ); -} - [data-cke-caption-placeholder]::before { display: inline; + color: rgba( 0, 0, 0, .4 ); content: attr( data-cke-caption-placeholder ); } From 25807574569a570001930b0008499b497ff7c11a Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 29 Jan 2018 17:02:10 +0100 Subject: [PATCH 422/642] Add language meta entry for caption placeholder. --- dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt b/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt index cea6e9dc42b..53ff3a429e0 100644 --- a/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt +++ b/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt @@ -5,3 +5,4 @@ altText = Label for button converting image to assign an alternative text. fullImage = Label for button converting image to a full width. sideImage = Label for button converting image to be a side image. uploadFailed = Contents of alert displayed when Easy Image widget could not be uploaded due to network error. +captionPlaceholder = Contents of placeholder shown inside empty caption of Easy Image widget. From 3bab9493289c1235e1994b58c4d5fdac983b6bd5 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 29 Jan 2018 17:25:45 +0100 Subject: [PATCH 423/642] Update API docs. --- plugins/imagebase/plugin.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 4b805a9a81a..81255052652 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -521,6 +521,18 @@ caption.data( 'cke-caption-hidden', !isVisible ); } + /** + * Widget feature dedicated for displaying caption under the widget. + * + * This type serves solely as a mixin, and should be added using + * {@link CKEDITOR.plugins.imagebase#addFeature} method. + * + * This API is not yet in a final shape, thus marked as a private. It can be changed at any point. + * + * @private + * @class CKEDITOR.plugins.imagebase.featuresDefinitions.caption + * @abstract + */ return { setUp: function( editor ) { var listeners = []; @@ -564,12 +576,12 @@ }, /** - * Method used inside {@link CKEDITOR.editor#event-selectionChange} event to decide if caption for given widget - * should be displayed and should contain placeholder text. + * Method used to decide if caption for focused widget should be displayed and should contain + * placeholder text. * * @private * @member CKEDITOR.plugins.imagebase.featuresDefinitions.caption - * @param {CKEDITOR.dom.element} sender Element, which triggered `selectionChange` event + * @param {CKEDITOR.dom.element} sender Element, on which this function should be called. */ _refreshCaption: function( sender ) { var isFocused = getFocusedWidget( this.editor ) === this, From f5b41cf41cef6b855da55f40adb8f70191c8ee3b Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 29 Jan 2018 17:26:44 +0100 Subject: [PATCH 424/642] Inline widgets variable. --- plugins/imagebase/plugin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 81255052652..40cbad13e06 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -540,9 +540,9 @@ function listener( evt ) { var path = evt.name === 'blur' ? editor.elementPath() : evt.data.path, sender = path ? path.lastElement : null, - widgets = editor.widgets, focused = getFocusedWidget( editor ), - previous = widgets.getByElement( editor.editable().findOne( 'figcaption[data-cke-caption-active]' ) ); + previous = editor.widgets.getByElement( + editor.editable().findOne( 'figcaption[data-cke-caption-active]' ) ); if ( !editor.filter.check( 'figcaption' ) ) { return CKEDITOR.tools.array.forEach( listeners, function( listener ) { From 157bd1bb132711040d072dbbc09308a1de5b88b8 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 29 Jan 2018 17:30:24 +0100 Subject: [PATCH 425/642] Update unit test API docs. --- tests/plugins/imagebase/features/caption.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 8fdbbd30288..f41d5007766 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -46,15 +46,15 @@ * during each step. * * @param {Object} options - * @param {String} options.fixture Fixture's name. + * @param {String} options.fixture Fixture's id. * @param {Boolean} options.initial Caption visibility at the start of the test. * @param {Boolean} options.focus Caption visibility after calling focus function. * @param {Boolean} options.blur Caption visibility after calling blur function. - * @param {Boolean} options.onInit Callback to run at the beginning of the test. - * @param {Function} options.onFocus Callback to run after focus function. - * @param {Function} options.onBlur Callback to run after blur function. - * @param {Function} options.customFocus Function to be called instead of default focus function. - * @param {Function} options.customBlur Function to be called instead of default blur function. + * @param {Function} [options.onInit] Callback to run at the beginning of the test. + * @param {Function} [options.onFocus] Callback to run after focus function. + * @param {Function} [options.onBlur] Callback to run after blur function. + * @param {Function} [options.customFocus] Function to be called instead of default focus function. + * @param {Function} [options.customBlur] Function to be called instead of default blur function. */ function createToggleTest( options ) { return function( editor, bot ) { @@ -108,11 +108,10 @@ * during each step. Assertions are made for every widget in the group. * * @param {Object} options - * @param {String} options.fixture Fixture's name. + * @param {String} options.fixture Fixture's id. * @param {Number} options.widgetsCount Number of widgets to test. * @param {Boolean} options.initial Caption visibility at the start of the test. * @param {Boolean} options.focus Caption visibility after calling focus function. - * @param {Boolean} options.blur Caption visibility after calling blur function. */ function createMultipleToggleTest( options ) { return function( editor, bot ) { From 136d4c2b3019185e008e304b96f8f1787d5ed1aa Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 29 Jan 2018 17:35:11 +0100 Subject: [PATCH 426/642] Ingore unit tests in old IEs. --- tests/plugins/imagebase/features/caption.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index f41d5007766..286e5a6fdae 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -220,6 +220,12 @@ } var tests = { + setUp: function() { + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 11 ) { + assert.ignore(); + } + }, + 'test upcasting widget without figcaption element': function( editor, bot ) { addTestWidget( editor ); From 468058e41fac480187ef52d020b8b860c5fbae8b Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 29 Jan 2018 17:39:05 +0100 Subject: [PATCH 427/642] Add note for Edge users. --- tests/plugins/easyimage/manual/balloontoolbar/caption.md | 6 +++++- tests/plugins/imagebase/features/manual/caption.md | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/plugins/easyimage/manual/balloontoolbar/caption.md b/tests/plugins/easyimage/manual/balloontoolbar/caption.md index 435f15a4c62..5930c69622d 100644 --- a/tests/plugins/easyimage/manual/balloontoolbar/caption.md +++ b/tests/plugins/easyimage/manual/balloontoolbar/caption.md @@ -23,4 +23,8 @@ --- -Repeat above steps for all other editors. \ No newline at end of file +Repeat above steps for all other editors. + +## Note + +On Edge you could be affected by [#1458](https://github.com/ckeditor/ckeditor-dev/issues/1458) and have to double click widget to focus it. diff --git a/tests/plugins/imagebase/features/manual/caption.md b/tests/plugins/imagebase/features/manual/caption.md index 201828ddad7..4a40812e27b 100644 --- a/tests/plugins/imagebase/features/manual/caption.md +++ b/tests/plugins/imagebase/features/manual/caption.md @@ -11,3 +11,7 @@ Check if caption is working correctly: * If caption is empty, it contains placeholder text. Repeat these checks for all editors. + +## Note + +On Edge you could be affected by [#1458](https://github.com/ckeditor/ckeditor-dev/issues/1458) and have to double click widget to focus it. From 21af6a8396c4935a68e49e027756d979867e14b1 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Mon, 29 Jan 2018 17:52:30 +0100 Subject: [PATCH 428/642] Add manual test for disabled caption. --- .../features/manual/captiondisabled.html | 35 +++++++++++++++++++ .../features/manual/captiondisabled.md | 19 ++++++++++ 2 files changed, 54 insertions(+) create mode 100644 tests/plugins/imagebase/features/manual/captiondisabled.html create mode 100644 tests/plugins/imagebase/features/manual/captiondisabled.md diff --git a/tests/plugins/imagebase/features/manual/captiondisabled.html b/tests/plugins/imagebase/features/manual/captiondisabled.html new file mode 100644 index 00000000000..b1cd1d7f725 --- /dev/null +++ b/tests/plugins/imagebase/features/manual/captiondisabled.html @@ -0,0 +1,35 @@ +

Classic editor

+ +
+

Widget:

+
+ foo +
+
+ +

Divarea

+ +
+

Widget:

+
+ foo +
+
+ + diff --git a/tests/plugins/imagebase/features/manual/captiondisabled.md b/tests/plugins/imagebase/features/manual/captiondisabled.md new file mode 100644 index 00000000000..840b22ba81b --- /dev/null +++ b/tests/plugins/imagebase/features/manual/captiondisabled.md @@ -0,0 +1,19 @@ +@bender-tags: 4.9.0, feature, 932 +@bender-ui: collapsed +@bender-ckeditor-plugins: sourcearea, wysiwygarea, toolbar, imagebase, link, htmlwriter, elementspath, basicstyles + +# Customizing caption existence with ACF + +1. Focus widget. + +## Expected + +There is no caption. + +## Unexpected + +Caption shows after focus. + +--- + +Repeat for all editors. From d8bf5fee686c2baa2a78d4e3756b2a56a699eca7 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 25 Jan 2018 13:18:50 +0100 Subject: [PATCH 429/642] Corrected doc typo. --- tests/plugins/imagebase/features/caption.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/imagebase/features/caption.js b/tests/plugins/imagebase/features/caption.js index 286e5a6fdae..7a1ed81a091 100644 --- a/tests/plugins/imagebase/features/caption.js +++ b/tests/plugins/imagebase/features/caption.js @@ -60,7 +60,7 @@ return function( editor, bot ) { addTestWidget( editor ); - // Make sure the editor is focused, othrwise Edge/IE11 will throw Permission Denied error. + // Make sure the editor is focused, otherwise Edge/IE11 will throw Permission Denied error. editor.focus(); bot.setData( getFixture( options.fixture ), function() { From 21919c74bcf0eb610059f288c8f980ca40895719 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 30 Jan 2018 11:58:44 +0100 Subject: [PATCH 430/642] Added consistent content CSS to the caption test. --- .../imagebase/features/manual/caption.html | 165 +++++++++--------- 1 file changed, 85 insertions(+), 80 deletions(-) diff --git a/tests/plugins/imagebase/features/manual/caption.html b/tests/plugins/imagebase/features/manual/caption.html index ad842bb2f5b..bfa3c934a6e 100644 --- a/tests/plugins/imagebase/features/manual/caption.html +++ b/tests/plugins/imagebase/features/manual/caption.html @@ -1,92 +1,97 @@ -

Classic editor

+ + + + +

Classic editor

-
-

Widget without caption:

-
- foo -
-

Widget with empty caption:

-
- +
+

Widget without caption:

+
foo - -
-
-

Widget with caption:

-
- - foo - -
Test caption
-
-
+
+

Widget with empty caption:

+
+ + foo + +
+
+

Widget with caption:

+
+ + foo + +
Test caption
+
+
-

Divarea editor

+

Divarea editor

-
-

Widget without caption:

-
- foo -
-

Widget with empty caption:

-
- - foo - -
-
-

Widget with caption:

-
- + +
+

Widget with empty caption:

+
+ + foo + +
+
+

Widget with caption:

+
+ + foo + +
Test caption
+
+
-

Inline editor

+

Inline editor

-
-

Widget without caption:

-
- foo -
-

Widget with empty caption:

-
- - foo - -
-
-

Widget with caption:

-
- + +
+

Widget with empty caption:

+
+ + foo + +
+
+

Widget with caption:

+
+ + foo + +
Test caption
+
+
- + CKEDITOR.replace( 'classic', commonConfig ); + CKEDITOR.replace( 'divarea', CKEDITOR.tools.object.merge( commonConfig, { + extraPlugins: 'divarea' + } ) ); + CKEDITOR.inline( 'inline', commonConfig ); + }() ); + + \ No newline at end of file From 7d96a72f8f73e95c72bc0e00c18c195237ab3427 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 30 Jan 2018 12:01:25 +0100 Subject: [PATCH 431/642] Corrected code style. --- tests/plugins/imagebase/features/manual/caption.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugins/imagebase/features/manual/caption.html b/tests/plugins/imagebase/features/manual/caption.html index bfa3c934a6e..2853ffa54bf 100644 --- a/tests/plugins/imagebase/features/manual/caption.html +++ b/tests/plugins/imagebase/features/manual/caption.html @@ -94,4 +94,4 @@

Inline editor

CKEDITOR.inline( 'inline', commonConfig ); }() ); - \ No newline at end of file + From 1b3941688734dcba41e42925b1d2569d505106ba Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 30 Jan 2018 12:57:28 +0100 Subject: [PATCH 432/642] Tests: Simplified manual test checks, and removed one of 2 source verification plugins. --- tests/plugins/imagebase/features/manual/caption.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/plugins/imagebase/features/manual/caption.md b/tests/plugins/imagebase/features/manual/caption.md index 4a40812e27b..a8392d055e5 100644 --- a/tests/plugins/imagebase/features/manual/caption.md +++ b/tests/plugins/imagebase/features/manual/caption.md @@ -1,14 +1,13 @@ @bender-tags: 4.9.0, feature, 932 @bender-ui: collapsed -@bender-ckeditor-plugins: sourcearea, sourcedialog, wysiwygarea, floatingspace, toolbar, imagebase, link, htmlwriter, elementspath +@bender-ckeditor-plugins: sourcedialog, wysiwygarea, floatingspace, toolbar, imagebase, link, htmlwriter, elementspath Check if caption is working correctly: +* If caption is empty, it's hidden when widget is blurred. +* If caption is empty and is focused, it's shown and it contains a placeholder text. * In source mode every widget contains `figcaption` element. * In source mode there are no attributes for any `figcaption` element. -* If caption is empty, it's hidden when widget is blurred. -* If caption is empty, it's shown when widget is focused. -* If caption is empty, it contains placeholder text. Repeat these checks for all editors. From 66b6cbbc6eeb75a461d9fa3d1bfd8ec8b5d7858c Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 30 Jan 2018 13:01:23 +0100 Subject: [PATCH 433/642] Docs: corrected event API tags in Upload Widget Feature. --- plugins/imagebase/plugin.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 40cbad13e06..e7af75945cc 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -456,7 +456,7 @@ * Note that the event will be fired even if the widget was created for a loader that * is already resolved. * - * @evt uploadStarted + * @event uploadStarted * @param {CKEDITOR.fileTools.fileLoader} data Lader that is used for this widget. */ @@ -469,7 +469,7 @@ * this.setData( 'backendUrl', response.url ); * } ); * - * @evt uploadDone + * @event uploadDone * @param data * @param {CKEDITOR.fileTools.fileLoader} data.loader Loader that caused this event. */ @@ -484,7 +484,7 @@ * * This event is cancelable, if not canceled it will remove the widget. * - * @evt uploadFailed + * @event uploadFailed * @param data * @param {CKEDITOR.fileTools.fileLoader} data.loader Loader that caused this event. */ From 734a5f44601edac923f508617076d27874330b6d Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 30 Jan 2018 14:25:36 +0100 Subject: [PATCH 434/642] Added autogrow plugin to Easy Image sample. --- plugins/easyimage/samples/easyimage.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/easyimage/samples/easyimage.html b/plugins/easyimage/samples/easyimage.html index 9265654e0a0..d6cb4228664 100644 --- a/plugins/easyimage/samples/easyimage.html +++ b/plugins/easyimage/samples/easyimage.html @@ -111,7 +111,7 @@

Apollo 11

getToken( function( token ) { CKEDITOR.replace( 'editor', { - plugins: 'sourcearea,toolbar,undo,wysiwygarea,list,liststyle,format,link,basicstyles', + plugins: 'easyimage,autogrow,sourcearea,toolbar,undo,wysiwygarea,list,liststyle,format,link,basicstyles', toolbar: [ { name: 'document', items: [ 'Source', 'Undo', 'Redo' ] }, { name: 'basicstyles', items: [ 'Bold', 'Italic', 'Strike', '-', 'RemoveFormat' ] }, @@ -119,7 +119,6 @@

Apollo 11

{ name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] }, { name: 'styles', items: [ 'Format' ] } ], - extraPlugins: 'easyimage', cloudServices_url: 'https://files.cke-cs.com/upload/', cloudServices_token: token, height: 500 From eb5e393b35ee29f6b9ee8ea0e287acd5da0b510c Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Mon, 29 Jan 2018 15:27:41 +0100 Subject: [PATCH 435/642] Update meta files for easyimage and imagebase. --- dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt | 6 +++--- dev/langtool/meta/ckeditor.plugin-imagebase/meta.txt | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 dev/langtool/meta/ckeditor.plugin-imagebase/meta.txt diff --git a/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt b/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt index 53ff3a429e0..06088a3c91a 100644 --- a/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt +++ b/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt @@ -1,8 +1,8 @@ # Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. # For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license -altText = Label for button converting image to assign an alternative text. -fullImage = Label for button converting image to a full width. -sideImage = Label for button converting image to be a side image. +commands.fullImage = Label for button converting image to a full width. +commands.sideImage = Label for button converting image to be a side image. +commands.altText = Label for button converting image to assign an alternative text. uploadFailed = Contents of alert displayed when Easy Image widget could not be uploaded due to network error. captionPlaceholder = Contents of placeholder shown inside empty caption of Easy Image widget. diff --git a/dev/langtool/meta/ckeditor.plugin-imagebase/meta.txt b/dev/langtool/meta/ckeditor.plugin-imagebase/meta.txt new file mode 100644 index 00000000000..41a9986abc7 --- /dev/null +++ b/dev/langtool/meta/ckeditor.plugin-imagebase/meta.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. +# For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + +captionPlaceholder = Caption displayed below images, which describes it. From f1ad7d126186a7070c213d34aa52cfb35f4dcd5f Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Mon, 29 Jan 2018 17:25:24 +0100 Subject: [PATCH 436/642] Update langtool config with new plugins. --- dev/langtool/_common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/langtool/_common.sh b/dev/langtool/_common.sh index 9dc8fd2bcfc..8c485c6f024 100755 --- a/dev/langtool/_common.sh +++ b/dev/langtool/_common.sh @@ -46,5 +46,5 @@ fi cd ../.. -plugins=( about autoembed basicstyles bidi blockquote button clipboard codesnippet colorbutton colordialog contextmenu copyformatting devtools div docprops elementspath embedbase fakeobjects filetools find flash font format forms horizontalrule iframe image image2 indent justify language link list liststyle magicline maximize mathjax newpage notification pagebreak pastefromword pastetext placeholder preview print removeformat save selectall showblocks smiley sourcearea sourcedialog specialchar stylescombo table templates toolbar uicolor undo uploadwidget widget ) +plugins=( about autoembed basicstyles bidi blockquote button clipboard codesnippet colorbutton colordialog contextmenu copyformatting devtools div docprops easyimage elementspath embedbase fakeobjects filetools find flash font format forms horizontalrule iframe image image2 imagebase indent justify language link list liststyle magicline maximize mathjax newpage notification pagebreak pastefromword pastetext placeholder preview print removeformat save selectall showblocks smiley sourcearea sourcedialog specialchar stylescombo table templates toolbar uicolor undo uploadwidget widget ) plugins_dialogs=( a11yhelp specialchar ) From 00accfe52f751f7ff043f9b360d46505ba86bb8c Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 31 Jan 2018 11:26:57 +0100 Subject: [PATCH 437/642] Added PFW plugin to EI demo. --- plugins/easyimage/samples/easyimage.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/samples/easyimage.html b/plugins/easyimage/samples/easyimage.html index d6cb4228664..c86361fe7bc 100644 --- a/plugins/easyimage/samples/easyimage.html +++ b/plugins/easyimage/samples/easyimage.html @@ -111,7 +111,7 @@

Apollo 11

getToken( function( token ) { CKEDITOR.replace( 'editor', { - plugins: 'easyimage,autogrow,sourcearea,toolbar,undo,wysiwygarea,list,liststyle,format,link,basicstyles', + plugins: 'easyimage,autogrow,sourcearea,toolbar,undo,wysiwygarea,list,liststyle,format,link,basicstyles,pastefromword', toolbar: [ { name: 'document', items: [ 'Source', 'Undo', 'Redo' ] }, { name: 'basicstyles', items: [ 'Bold', 'Italic', 'Strike', '-', 'RemoveFormat' ] }, From 74af724f3b775787bceb366c44118274078ef15a Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Wed, 31 Jan 2018 11:42:54 +0100 Subject: [PATCH 438/642] Fix langtool property description for imagebase. --- dev/langtool/meta/ckeditor.plugin-imagebase/meta.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/langtool/meta/ckeditor.plugin-imagebase/meta.txt b/dev/langtool/meta/ckeditor.plugin-imagebase/meta.txt index 41a9986abc7..89b05d8fe60 100644 --- a/dev/langtool/meta/ckeditor.plugin-imagebase/meta.txt +++ b/dev/langtool/meta/ckeditor.plugin-imagebase/meta.txt @@ -1,4 +1,4 @@ # Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. # For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license -captionPlaceholder = Caption displayed below images, which describes it. +captionPlaceholder = Contents of placeholder shown inside empty caption of an image. From a08c77a4ff2b1e859ea22a1f63a68a752cbbf1ca Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Wed, 31 Jan 2018 14:15:05 +0100 Subject: [PATCH 439/642] Remove unnecessary description for translation for easy image. --- dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt b/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt index 06088a3c91a..500ab3c19a5 100644 --- a/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt +++ b/dev/langtool/meta/ckeditor.plugin-easyimage/meta.txt @@ -5,4 +5,3 @@ commands.fullImage = Label for button converting image to a full width. commands.sideImage = Label for button converting image to be a side image. commands.altText = Label for button converting image to assign an alternative text. uploadFailed = Contents of alert displayed when Easy Image widget could not be uploaded due to network error. -captionPlaceholder = Contents of placeholder shown inside empty caption of Easy Image widget. From 5ceb07b1b386e4ca2320e83b150d96cdedf49e97 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 31 Jan 2018 18:06:15 +0100 Subject: [PATCH 440/642] Adjusted Easy Image demo text. --- plugins/easyimage/samples/easyimage.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/easyimage/samples/easyimage.html b/plugins/easyimage/samples/easyimage.html index c86361fe7bc..0d20893950f 100644 --- a/plugins/easyimage/samples/easyimage.html +++ b/plugins/easyimage/samples/easyimage.html @@ -39,7 +39,7 @@

Easy Image Demo

-

It shows our progress of work on Easy Image plugin.

+

It shows our progress of work on Easy Image. Drop an image file in the editor to see how easily images can be handled.

From 5b11a18873695014212443ff55fcf4912d499bc6 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 31 Jan 2018 18:10:40 +0100 Subject: [PATCH 441/642] Make background in Easy Image sample static. Otherwise blue background would be moving as the editor height increases, which caused a funny experience. --- plugins/easyimage/samples/easyimage.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/easyimage/samples/easyimage.html b/plugins/easyimage/samples/easyimage.html index 0d20893950f..2d95dced94c 100644 --- a/plugins/easyimage/samples/easyimage.html +++ b/plugins/easyimage/samples/easyimage.html @@ -13,6 +13,12 @@ + +

A paragraph with some text.

-

Another paragraph with more text.

-

Next paragraph with even more text.

-
- CKEditor logo -
- Test caption. -
-
diff --git a/tests/plugins/easyimage/manual/browsersupport.md b/tests/plugins/easyimage/manual/browsersupport.md index 8907ecace31..f7552127c41 100644 --- a/tests/plugins/easyimage/manual/browsersupport.md +++ b/tests/plugins/easyimage/manual/browsersupport.md @@ -1,11 +1,13 @@ @bender-tags: 4.9.0, bug, 1596 @bender-ui: collapsed -@bender-ckeditor-plugins: wysiwygarea, floatingspace, toolbar, easyimage +@bender-ckeditor-plugins: wysiwygarea, toolbar, easyimage -## EasyImage support for different browsers +## Easy Image browser support -Do this test on Internet Explorer 10 and lower. +1. Check the editor contents. ## Expected -There shouldn't be no EasyImage instances visible in editor. +**IE8-10**: There is no Easy Image instance visible in editor. + +**Other browsers**: Easy Image widget is visible. From fcf2ed877c11e04f2cdbf4b589409626180f7571 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 7 Feb 2018 14:55:24 +0100 Subject: [PATCH 546/642] Corrected Easy Image supported browsers condition. --- plugins/easyimage/plugin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 35eb4ee181c..4eb1fc810fe 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -515,7 +515,7 @@ }, init: function( editor ) { - if ( isSupportedBrowser() ) { + if ( !isSupportedBrowser() ) { return; } loadStyles( editor, this ); @@ -524,7 +524,7 @@ // Widget must be registered after init in case that link plugin is dynamically loaded e.g. via // `config.extraPlugins`. afterInit: function( editor ) { - if ( isSupportedBrowser() ) { + if ( !isSupportedBrowser() ) { return; } var styles = getStylesForEditor( editor ); From b4b0167eefb4c1b9bc8cf185798dfd8aa1b23658 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 1 Feb 2018 16:22:31 +0100 Subject: [PATCH 547/642] Tests: adjusted Easy Image progress bar test expectation. --- tests/plugins/easyimage/manual/progressbar.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/plugins/easyimage/manual/progressbar.md b/tests/plugins/easyimage/manual/progressbar.md index 8270ab61a8d..3278c3fca49 100644 --- a/tests/plugins/easyimage/manual/progressbar.md +++ b/tests/plugins/easyimage/manual/progressbar.md @@ -1,4 +1,4 @@ -@bender-tags: 4.9.0, feature, 932 +@bender-tags: 4.9.0, feature, 932, 1533 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage @bender-include: ../../uploadwidget/manual/_helpers/xhr.js @@ -14,6 +14,14 @@ Remarks: 1. Drop an image into the editor. -### Expected + ### Expected -* Upload progress is shown. + * Upload progress is shown. + * The image is a little opaque. + +1. Wait till the image load completes. + + ### Expected + + * Progress indicator disappear. + * Image is no longer opaque. \ No newline at end of file From 3cd09fb90e0ce19d3f3f7fd23334e35e5226f121 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 1 Feb 2018 16:46:13 +0100 Subject: [PATCH 548/642] Added cke_widget_wrapper_uploading class to upload widgets that are being uploaded. --- plugins/easyimage/styles/easyimage.css | 11 +++++++++++ plugins/imagebase/plugin.js | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/plugins/easyimage/styles/easyimage.css b/plugins/easyimage/styles/easyimage.css index 1fde4bbe177..fb65d36c5d8 100644 --- a/plugins/easyimage/styles/easyimage.css +++ b/plugins/easyimage/styles/easyimage.css @@ -110,3 +110,14 @@ body.cke_editable > .cke_widget_wrapper_easyimage-side { left: 40px; right: 40px; } + +/* Fancy opacity effect discussed in #1533. Transition assigned in this awkward way so that it **does not** happen for +the initial render, otherwise it would start transitioning from opacity 1 to 0.x upon first render. */ + +.cke_widget_wrapper_easyimage:not(.cke_widget_wrapper_uploading) figure img { + transition: opacity 0.3s ease-in-out; +} + +.cke_widget_wrapper_easyimage.cke_widget_wrapper_uploading figure img { + opacity: 0.75; +} \ No newline at end of file diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index e7af75945cc..f811ae0a748 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -351,6 +351,7 @@ if ( widget.isInited() ) { widget.setData( 'uploadId', undefined ); } + widget.removeClass( 'uploading' ); } function failHandling() { @@ -397,6 +398,7 @@ var progress = new widget.progressReporterType(); widget.wrapper.append( progress.wrapper ); progress.bindLoader( loader ); + widget.addClass( 'uploading' ); } else { if ( loaderEventMapping[ loader.status ] ) { loaderEventMapping[ loader.status ](); @@ -451,7 +453,8 @@ * // Implement a custom progress bar. * } ); * - * This event is cancelable, if canceled, the default progress bar will not be created. + * This event is cancelable, if canceled, the default progress bar will not be created + * and widget element and wrapper won't be marked with `cke_widget_(wrapper_)uploading` class. * * Note that the event will be fired even if the widget was created for a loader that * is already resolved. From 3de0c14b90ad9dc645a80be3dfaefe27f81c75ad Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 1 Feb 2018 17:43:14 +0100 Subject: [PATCH 549/642] Adjusted Easy Image uploading class so that it is added only to the wrapper. Otherwise it would result with a junk/stray classes in the output. --- plugins/imagebase/plugin.js | 8 ++-- tests/plugins/imagebase/features/upload.js | 48 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index f811ae0a748..a40d748c67e 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -351,7 +351,7 @@ if ( widget.isInited() ) { widget.setData( 'uploadId', undefined ); } - widget.removeClass( 'uploading' ); + // widget.wrapper.removeClass( 'cke_widget_wrapper_uploading' ); } function failHandling() { @@ -366,6 +366,7 @@ function uploadComplete() { widgetCleanup(); + widget.wrapper.removeClass( 'cke_widget_wrapper_uploading' ); widget.fire( 'uploadDone', { loader: loader @@ -394,11 +395,12 @@ if ( widget.fire( 'uploadStarted', loader ) !== false && widget.progressReporterType ) { if ( !widget._isLoaderDone( loader ) ) { + // Deliberately add class to wrapper, it does not make sense for widget element. + widget.wrapper.addClass( 'cke_widget_wrapper_uploading' ); // Progress reporter has only sense if widget is in progress. var progress = new widget.progressReporterType(); widget.wrapper.append( progress.wrapper ); progress.bindLoader( loader ); - widget.addClass( 'uploading' ); } else { if ( loaderEventMapping[ loader.status ] ) { loaderEventMapping[ loader.status ](); @@ -454,7 +456,7 @@ * } ); * * This event is cancelable, if canceled, the default progress bar will not be created - * and widget element and wrapper won't be marked with `cke_widget_(wrapper_)uploading` class. + * and the widget wrapper won't be marked with `cke_widget_wrapper_uploading` class. * * Note that the event will be fired even if the widget was created for a loader that * is already resolved. diff --git a/tests/plugins/imagebase/features/upload.js b/tests/plugins/imagebase/features/upload.js index 5550a3583ac..87e81b8237b 100644 --- a/tests/plugins/imagebase/features/upload.js +++ b/tests/plugins/imagebase/features/upload.js @@ -385,6 +385,54 @@ } ); }, + // (#1533) + 'test widget gets class during the upload': function() { + var editor = this.editor; + + assertPasteFiles( editor, { + files: [ getTestRtfFile() ], + callback: function( widgets ) { + var widget = widgets[ 0 ]; + assert.isTrue( widget.hasClass( 'uploading' ), 'Class is present during the upload' ); + + widget.once( 'uploadDone', function() { + resume( function() { + assert.isFalse( widget.hasClass( 'uploading' ), 'Class is removed after upload' ); + } ); + } ); + + wait(); + } + } ); + }, + + 'test widget upload class is removed after fail': function() { + var editor = this.editor, + listeners = this.listeners, + originalLoader = editor.widgets.registered.testImageWidget.loaderType; + + // Force a loader that will fail. + editor.widgets.registered.testImageWidget.loaderType = FailFileLoader; + + // Make sure to prevent default handling, otherwise widget is removed. + this.listeners.push( editor.widgets.on( 'instanceCreated', function( evt ) { + listeners.push( evt.data.on( 'uploadFailed', function( evt ) { + evt.cancel(); + } ) ); + } ) ); + + assertPasteFiles( editor, { + files: [ bender.tools.getTestPngFile() ], + callback: function( widgets ) { + // Note FailFileLoader is synchronous, so there's no need to wait for uploadFailed. + editor.widgets.registered.testImageWidget.loaderType = originalLoader; + + var widget = widgets[ 0 ]; + assert.isTrue( widget.hasClass( 'uploading' ), 'Class is present during the upload' ); + } + } ); + }, + 'test data.uploadId behavior': function() { var editor = this.editor; From ae06d05981b93da9fcbc36b365cc81a89f1a6134 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 1 Feb 2018 17:47:14 +0100 Subject: [PATCH 550/642] Tests: aligned unit tests with the recent change. --- tests/plugins/imagebase/features/upload.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/plugins/imagebase/features/upload.js b/tests/plugins/imagebase/features/upload.js index 87e81b8237b..3b52e25f9c6 100644 --- a/tests/plugins/imagebase/features/upload.js +++ b/tests/plugins/imagebase/features/upload.js @@ -393,11 +393,11 @@ files: [ getTestRtfFile() ], callback: function( widgets ) { var widget = widgets[ 0 ]; - assert.isTrue( widget.hasClass( 'uploading' ), 'Class is present during the upload' ); + assert.isTrue( widget.wrapper.hasClass( 'cke_widget_wrapper_uploading' ), 'Class is present during the upload' ); widget.once( 'uploadDone', function() { resume( function() { - assert.isFalse( widget.hasClass( 'uploading' ), 'Class is removed after upload' ); + assert.isFalse( widget.wrapper.hasClass( 'cke_widget_wrapper_uploading' ), 'Class is removed after upload' ); } ); } ); @@ -428,7 +428,7 @@ editor.widgets.registered.testImageWidget.loaderType = originalLoader; var widget = widgets[ 0 ]; - assert.isTrue( widget.hasClass( 'uploading' ), 'Class is present during the upload' ); + assert.isTrue( widget.wrapper.hasClass( 'cke_widget_wrapper_uploading' ), 'Class is present during the upload' ); } } ); }, From eed58b7cab963fcf9975646603c4c21226e11ee6 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 5 Feb 2018 16:46:29 +0100 Subject: [PATCH 551/642] Fixed upload class being removed only in case of success, used async fail loader stub for uploading class unit tests. --- plugins/imagebase/plugin.js | 3 +-- tests/plugins/imagebase/features/upload.js | 31 +++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index a40d748c67e..8829f5db340 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -351,7 +351,7 @@ if ( widget.isInited() ) { widget.setData( 'uploadId', undefined ); } - // widget.wrapper.removeClass( 'cke_widget_wrapper_uploading' ); + widget.wrapper.removeClass( 'cke_widget_wrapper_uploading' ); } function failHandling() { @@ -366,7 +366,6 @@ function uploadComplete() { widgetCleanup(); - widget.wrapper.removeClass( 'cke_widget_wrapper_uploading' ); widget.fire( 'uploadDone', { loader: loader diff --git a/tests/plugins/imagebase/features/upload.js b/tests/plugins/imagebase/features/upload.js index 3b52e25f9c6..962c73258c7 100644 --- a/tests/plugins/imagebase/features/upload.js +++ b/tests/plugins/imagebase/features/upload.js @@ -25,7 +25,7 @@ CKEDITOR.fileTools.fileLoader.call( this, editor, fileOrData, fileName ); } - // A mocked Loader type that synchronously notifies that the file has been failed. + // A mocked Loader type that synchronously notifies that the file failed to upload. function FailFileLoader( editor, fileOrData, fileName ) { CKEDITOR.fileTools.fileLoader.call( this, editor, fileOrData, fileName ); } @@ -35,6 +35,11 @@ CKEDITOR.fileTools.fileLoader.call( this, editor, fileOrData, fileName ); } + // A mocked Loader type that asynchronously notifies that the file failed to upload. + function AsyncFailFileLoader( editor, fileOrData, fileName ) { + CKEDITOR.fileTools.fileLoader.call( this, editor, fileOrData, fileName ); + } + var assertPasteFiles = imageBaseFeaturesTools.assertPasteFiles, tests = { init: function() { @@ -92,6 +97,18 @@ }, 100 ); } }, CKEDITOR.fileTools.fileLoader.prototype ); + + AsyncFailFileLoader.prototype = CKEDITOR.tools.extend( { + upload: function() { + var that = this; + setTimeout( function() { + that.xhr = { + readyState: 4 + }; + that.changeStatus( 'error' ); + }, 100 ); + } + }, CKEDITOR.fileTools.fileLoader.prototype ); }, tearDown: function() { @@ -412,23 +429,31 @@ originalLoader = editor.widgets.registered.testImageWidget.loaderType; // Force a loader that will fail. - editor.widgets.registered.testImageWidget.loaderType = FailFileLoader; + editor.widgets.registered.testImageWidget.loaderType = AsyncFailFileLoader; // Make sure to prevent default handling, otherwise widget is removed. this.listeners.push( editor.widgets.on( 'instanceCreated', function( evt ) { listeners.push( evt.data.on( 'uploadFailed', function( evt ) { + var widget = this; + + // Prevent image from being removed. evt.cancel(); + + resume( function() { + assert.isFalse( widget.wrapper.hasClass( 'cke_widget_wrapper_uploading' ), + 'Class is removed after fail' ); + } ); } ) ); } ) ); assertPasteFiles( editor, { files: [ bender.tools.getTestPngFile() ], callback: function( widgets ) { - // Note FailFileLoader is synchronous, so there's no need to wait for uploadFailed. editor.widgets.registered.testImageWidget.loaderType = originalLoader; var widget = widgets[ 0 ]; assert.isTrue( widget.wrapper.hasClass( 'cke_widget_wrapper_uploading' ), 'Class is present during the upload' ); + wait(); } } ); }, From 86fd4f96dfdf6a1b877e4b8fa6e73d9940c4cccf Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Mon, 5 Feb 2018 16:46:55 +0100 Subject: [PATCH 552/642] Tests: correceted manual test description. --- tests/plugins/easyimage/manual/progressbar.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plugins/easyimage/manual/progressbar.md b/tests/plugins/easyimage/manual/progressbar.md index 3278c3fca49..0f6a593ca9e 100644 --- a/tests/plugins/easyimage/manual/progressbar.md +++ b/tests/plugins/easyimage/manual/progressbar.md @@ -17,11 +17,11 @@ Remarks: ### Expected * Upload progress is shown. - * The image is a little opaque. + * The image is a little transparent. 1. Wait till the image load completes. ### Expected * Progress indicator disappear. - * Image is no longer opaque. \ No newline at end of file + * Image has its regular color. \ No newline at end of file From c5c23880408ff15f7d354f5ef0a0341afa667ba3 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 21 Nov 2017 13:22:21 +0100 Subject: [PATCH 553/642] Revert "Removed paste dialog." This reverts commit 4f79efc0967a72211c6d82521fe45b5f086ce583. --- plugins/clipboard/dialogs/paste.js | 254 +++++++++++++++++++++++++++++ plugins/clipboard/plugin.js | 83 +++++++++- 2 files changed, 333 insertions(+), 4 deletions(-) create mode 100644 plugins/clipboard/dialogs/paste.js diff --git a/plugins/clipboard/dialogs/paste.js b/plugins/clipboard/dialogs/paste.js new file mode 100644 index 00000000000..48e4072770e --- /dev/null +++ b/plugins/clipboard/dialogs/paste.js @@ -0,0 +1,254 @@ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +CKEDITOR.dialog.add( 'paste', function( editor ) { + var lang = editor.lang.clipboard, + clipboard = CKEDITOR.plugins.clipboard, + lastDataTransfer; + + function onPasteFrameLoad( win ) { + var doc = new CKEDITOR.dom.document( win.document ), + body = doc.getBody(), + script = doc.getById( 'cke_actscrpt' ); + + script && script.remove(); + + body.setAttribute( 'contenteditable', true ); + + // Forward dataTransfer (#13883). + body.on( clipboard.mainPasteEvent, function( evt ) { + var dataTransfer = clipboard.initPasteDataTransfer( evt ); + + if ( !lastDataTransfer ) { + lastDataTransfer = dataTransfer; + } else + // For two paste with the same dataTransfer we can use that dataTransfer (two internal pastes are + // considered as an internal paste). + if ( dataTransfer != lastDataTransfer ) { + // If there were two paste with different DataTransfer objects create a new, empty, data transfer + // and use it (one internal and one external paste are considered as external paste). + lastDataTransfer = clipboard.initPasteDataTransfer(); + } + } ); + + // IE before version 8 will leave cursor blinking inside the document after + // editor blurred unless we clean up the selection. (#4716) + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 8 ) { + doc.getWindow().on( 'blur', function() { + doc.$.selection.empty(); + } ); + } + + doc.on( 'keydown', function( e ) { + var domEvent = e.data, + key = domEvent.getKeystroke(), + processed; + + switch ( key ) { + case 27: + this.hide(); + processed = 1; + break; + + case 9: + case CKEDITOR.SHIFT + 9: + this.changeFocus( 1 ); + processed = 1; + } + + processed && domEvent.preventDefault(); + }, this ); + + editor.fire( 'ariaWidget', new CKEDITOR.dom.element( win.frameElement ) ); + + // Handle pending focus. + if ( doc.getWindow().getFrame().removeCustomData( 'pendingFocus' ) ) + body.focus(); + } + + // If pasteDialogCommit wasn't canceled by e.g. editor.getClipboardData + // then fire paste event. + // Do not use editor#paste, because it would start from beforePaste event. + editor.on( 'pasteDialogCommit', function( evt ) { + if ( evt.data ) + editor.fire( 'paste', { + type: 'auto', + dataValue: evt.data.dataValue, + method: 'paste', + dataTransfer: evt.data.dataTransfer || clipboard.initPasteDataTransfer() + } ); + }, null, null, 1000 ); + + return { + title: lang.title, + + minWidth: CKEDITOR.env.ie && CKEDITOR.env.quirks ? 370 : 350, + minHeight: CKEDITOR.env.quirks ? 250 : 245, + onShow: function() { + // FIREFOX BUG: Force the browser to render the dialog to make the to-be- + // inserted iframe editable. (#3366) + this.parts.dialog.$.offsetHeight; + + this.setupContent(); + + // Set dialog title to the custom value (set e.g. in editor.openDialog callback) and reset this value. + // If custom title not set, use default one. + this.parts.title.setHtml( this.customTitle || lang.title ); + this.customTitle = null; + }, + + onLoad: function() { + if ( ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) && editor.lang.dir == 'rtl' ) + this.parts.contents.setStyle( 'overflow', 'hidden' ); + }, + + onOk: function() { + this.commitContent(); + }, + + contents: [ { + id: 'general', + label: editor.lang.common.generalTab, + elements: [ + { + type: 'html', + id: 'securityMsg', + html: '
' + lang.securityMsg + '
' + }, + { + type: 'html', + id: 'pasteMsg', + html: '
' + lang.pasteMsg + '
' + }, + { + type: 'html', + id: 'editing_area', + style: 'width:100%;height:100%', + html: '', + focus: function() { + var iframe = this.getInputElement(), + doc = iframe.getFrameDocument(), + body = doc.getBody(); + + // Frame content may not loaded at the moment. + if ( !body || body.isReadOnly() ) + iframe.setCustomData( 'pendingFocus', 1 ); + else + body.focus(); + }, + setup: function() { + var dialog = this.getDialog(); + var htmlToLoad = '' + + '' + + '' + + ''; + + var src = + CKEDITOR.env.air ? + 'javascript:void(0)' : // jshint ignore:line + ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) ? + 'javascript:void((function(){' + encodeURIComponent( // jshint ignore:line + 'document.open();' + + '(' + CKEDITOR.tools.fixDomain + ')();' + + 'document.close();' + ) + '})())"' + : ''; + + var iframe = CKEDITOR.dom.element.createFromHtml( '' ); + + // Reset last data transfer. + lastDataTransfer = null; + + iframe.on( 'load', function( e ) { + e.removeListener(); + + var doc = iframe.getFrameDocument(); + doc.write( htmlToLoad ); + + editor.focusManager.add( doc.getBody() ); + + if ( CKEDITOR.env.air ) + onPasteFrameLoad.call( this, doc.getWindow().$ ); + }, dialog ); + + iframe.setCustomData( 'dialog', dialog ); + + var container = this.getElement(); + container.setHtml( '' ); + container.append( iframe ); + + // IE need a redirect on focus to make + // the cursor blinking inside iframe. (#5461) + if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) { + var focusGrabber = CKEDITOR.dom.element.createFromHtml( '' ); + focusGrabber.on( 'focus', function() { + // Since fixDomain is called in src attribute, + // IE needs some slight delay to correctly move focus. + setTimeout( function() { + iframe.$.contentWindow.focus(); + } ); + } ); + container.append( focusGrabber ); + + // Override focus handler on field. + this.focus = function() { + focusGrabber.focus(); + this.fire( 'focus' ); + }; + } + + this.getInputElement = function() { + return iframe; + }; + + // Force container to scale in IE. + if ( CKEDITOR.env.ie ) { + container.setStyle( 'display', 'block' ); + container.setStyle( 'height', ( iframe.$.offsetHeight + 2 ) + 'px' ); + } + }, + commit: function() { + var editor = this.getDialog().getParentEditor(), + body = this.getInputElement().getFrameDocument().getBody(), + bogus = body.getBogus(), + html; + bogus && bogus.remove(); + + // Saving the contents so changes until paste is complete will not take place (#7500) + html = body.getHtml(); + + // Opera needs some time to think about what has happened and what it should do now. + setTimeout( function() { + editor.fire( 'pasteDialogCommit', { + dataValue: html, + // Avoid error if there was no paste so lastDataTransfer is null. + dataTransfer: lastDataTransfer || clipboard.initPasteDataTransfer() + } ); + }, 0 ); + } + } + ] + } ] + }; +} ); + +/** + * Internal event to pass paste dialog's data to the listeners. + * + * @private + * @event pasteDialogCommit + * @member CKEDITOR.editor + * @param {CKEDITOR.editor} editor This editor instance. + */ diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index de88142ee38..cf1cb602db6 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -118,7 +118,7 @@ // Register the plugin. CKEDITOR.plugins.add( 'clipboard', { - requires: 'notification,toolbar', + requires: 'dialog,notification,toolbar', // jscs:disable maximumLineLength lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,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,oc,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% // jscs:enable maximumLineLength @@ -144,6 +144,8 @@ initPasteClipboard( editor ); initDragDrop( editor ); + CKEDITOR.dialog.add( 'paste', CKEDITOR.getUrl( this.path + 'dialogs/paste.js' ) ); + // Convert image file (if present) to base64 string for Firefox. Do it as the first // step as the conversion is asynchronous and should hold all further paste processing. if ( CKEDITOR.env.gecko ) { @@ -320,7 +322,7 @@ } // Strip presentational markup & unify text markup. - // Forced plain text. + // Forced plain text (dialog or forcePAPT). // Note: we do not check dontFilter option in this case, because forcePAPT was implemented // before pasteFilter and pasteFilter is automatically used on Webkit&Blink since 4.5, so // forcePAPT should have priority as it had before 4.5. @@ -364,6 +366,17 @@ }, 0 ); } }, null, null, 1000 ); + + editor.on( 'pasteDialog', function( evt ) { + // TODO it's possible that this setTimeout is not needed any more, + // because of changes introduced in the same commit as this comment. + // Editor.getClipboardData adds listener to the dialog's events which are + // fired after a while (not like 'showDialog'). + setTimeout( function() { + // Open default paste dialog. + editor.openDialog( 'paste', evt.data ); + }, 0 ); + } ); } } ); @@ -412,7 +425,7 @@ addButtonsCommands(); /** - * Gets clipboard data by directly accessing the clipboard (IE only). + * Gets clipboard data by directly accessing the clipboard (IE only) or opening the paste dialog window. * * editor.getClipboardData( function( data ) { * if ( data ) @@ -427,12 +440,21 @@ * an upcoming major release. */ editor.getClipboardData = function( callbackOrOptions, callback ) { + var isDialogNeeded = false, + beforePasteNotCanceled = false, + dialogCommited = false, + dataType = 'auto'; + // Options are optional - args shift. if ( !callback ) { callback = callbackOrOptions; callbackOrOptions = null; } + // Listen at the end of listeners chain to see if event wasn't canceled + // and to retrieve modified data.type. + editor.on( 'beforePaste', onBeforePaste, null, null, 1000 ); + // Listen with maximum priority to handle content before everyone else. // This callback will handle paste event that will be fired if direct // access to the clipboard succeed in IE. @@ -444,7 +466,26 @@ // Direct access to the clipboard wasn't successful so remove listener. editor.removeListener( 'paste', onPaste ); - callback( null ); + // If beforePaste was canceled do not open dialog. + // Add listeners only if dialog really opened. 'pasteDialog' can be canceled. + if ( isDialogNeeded && beforePasteNotCanceled && editor.fire( 'pasteDialog', onDialogOpen ) ) { + editor.on( 'pasteDialogCommit', onDialogCommit ); + + // 'dialogHide' will be fired after 'pasteDialogCommit'. + editor.on( 'dialogHide', function( evt ) { + evt.removeListener(); + evt.data.removeListener( 'pasteDialogCommit', onDialogCommit ); + + // Because Opera has to wait a while in pasteDialog we have to wait here. + setTimeout( function() { + // Notify even if user canceled dialog (clicked 'cancel', ESC, etc). + if ( !dialogCommited ) + callback( null ); + }, 10 ); + } ); + } else { + callback( null ); + } } function onPaste( evt ) { @@ -452,6 +493,30 @@ evt.cancel(); callback( evt.data ); } + + function onBeforePaste( evt ) { + evt.removeListener(); + beforePasteNotCanceled = true; + dataType = evt.data.type; + } + + function onDialogCommit( evt ) { + evt.removeListener(); + // Cancel pasteDialogCommit so paste dialog won't automatically fire + // 'paste' evt by itself. + evt.cancel(); + dialogCommited = true; + callback( { + type: dataType, + dataValue: evt.data.dataValue, + dataTransfer: evt.data.dataTransfer, + method: 'paste' + } ); + } + + function onDialogOpen() { + this.customTitle = ( typeof callbackOrOptions === 'object' && callbackOrOptions.title ); + } }; function addButtonsCommands() { @@ -3002,6 +3067,16 @@ * @member CKEDITOR.editor */ +/** + * Internal event to open the Paste dialog window. + * + * @private + * @event pasteDialog + * @member CKEDITOR.editor + * @param {CKEDITOR.editor} editor This editor instance. + * @param {Function} [data] Callback that will be passed to {@link CKEDITOR.editor#openDialog}. + */ + /** * Facade for the native `drop` event. Fired when the native `drop` event occurs. * From 6326e94173ccc64304ab8328d9ab5638430f44ee Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Tue, 21 Nov 2017 17:02:56 +0100 Subject: [PATCH 554/642] Update language meta data and default language. --- dev/langtool/meta/ckeditor.plugin-clipboard/meta.txt | 3 +++ dev/langtool/meta/ckeditor.plugin-pastetext/meta.txt | 1 + plugins/clipboard/lang/en.js | 5 ++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/dev/langtool/meta/ckeditor.plugin-clipboard/meta.txt b/dev/langtool/meta/ckeditor.plugin-clipboard/meta.txt index 2a9d95e9c9d..2230043b3a3 100644 --- a/dev/langtool/meta/ckeditor.plugin-clipboard/meta.txt +++ b/dev/langtool/meta/ckeditor.plugin-clipboard/meta.txt @@ -7,3 +7,6 @@ cut = Toolbar button tooltip for the Cut feature. cutError = A notification message shown when the browser is blocking cutting, and the user should use the keyboard instead. The %1 sequence is replaced with a keystroke that - when pressed - will perform the action. paste = Toolbar button tooltip for the Paste feature. pasteNotification = A notification message shown when the browser is blocking pasting, and the user should use the keyboard instead. The %1 sequence is replaced with a keystroke that - when pressed - will perform the action. +pasteArea = WAI-ARIA label for the paste area. +pasteMsg = A help message urging the user to paste the text into the dialog window by using the keyboard. +title = Label for the Paste dialog window. diff --git a/dev/langtool/meta/ckeditor.plugin-pastetext/meta.txt b/dev/langtool/meta/ckeditor.plugin-pastetext/meta.txt index 3b44d59915d..528f6597ebc 100644 --- a/dev/langtool/meta/ckeditor.plugin-pastetext/meta.txt +++ b/dev/langtool/meta/ckeditor.plugin-pastetext/meta.txt @@ -3,3 +3,4 @@ button = Toolbar button tooltip for the Paste as Plain Text feature. pasteNotification = A notification message shown when the browser is blocking pasting, and the user should use the keyboard instead. The %1 sequence is replaced with a keystroke that - when pressed - will perform the action. +title = Label for the Paste as Plain Text dialog window. diff --git a/plugins/clipboard/lang/en.js b/plugins/clipboard/lang/en.js index 77fb0111e51..5c6d7ab38cf 100644 --- a/plugins/clipboard/lang/en.js +++ b/plugins/clipboard/lang/en.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en', { cut: 'Cut', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', paste: 'Paste', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', + pasteArea: 'Paste Area', + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', + title: 'Paste' } ); From 1eee96af9546f82ceed5343aa6075c84378ac608 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 22 Nov 2017 17:57:21 +0100 Subject: [PATCH 555/642] Add touch detection on paste button and forcing dialog. --- plugins/clipboard/plugin.js | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index cf1cb602db6..ac0f1e76791 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -440,8 +440,7 @@ * an upcoming major release. */ editor.getClipboardData = function( callbackOrOptions, callback ) { - var isDialogNeeded = false, - beforePasteNotCanceled = false, + var beforePasteNotCanceled = false, dialogCommited = false, dataType = 'auto'; @@ -468,11 +467,14 @@ // If beforePaste was canceled do not open dialog. // Add listeners only if dialog really opened. 'pasteDialog' can be canceled. - if ( isDialogNeeded && beforePasteNotCanceled && editor.fire( 'pasteDialog', onDialogOpen ) ) { + if ( editor._.forcePasteDialog && beforePasteNotCanceled && editor.fire( 'pasteDialog', onDialogOpen ) ) { editor.on( 'pasteDialogCommit', onDialogCommit ); // 'dialogHide' will be fired after 'pasteDialogCommit'. editor.on( 'dialogHide', function( evt ) { + // Reset dialog mode (#595). + editor._.forcePasteDialog = false; + evt.removeListener(); evt.data.removeListener( 'pasteDialogCommit', onDialogCommit ); @@ -515,7 +517,7 @@ } function onDialogOpen() { - this.customTitle = ( typeof callbackOrOptions === 'object' && callbackOrOptions.title ); + this.customTitle = ( callbackOrOptions && typeof callbackOrOptions === 'object' && callbackOrOptions.title ); } }; @@ -567,6 +569,19 @@ }; } ); } + + // Detect if paste button was touched. In such case we assume that user is using + // touch device and force displaying paste dialog (#595). + if ( editor.ui.addButton ) { + setTimeout( function() { + var pasteButton = editor.ui.get( 'Paste' ), + buttonElement = editor.container.findOne( '#' + pasteButton._.id ); + + buttonElement.on( 'touchend', function() { + editor._.forcePasteDialog = true; + } ); + }, 0 ); + } } // Add events listeners to editable. From 10615850a6d361c65df4a0f2cf115a73aa15245e Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 22 Nov 2017 17:58:53 +0100 Subject: [PATCH 556/642] Removed securityMsg area from dialog. --- plugins/clipboard/dialogs/paste.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/clipboard/dialogs/paste.js b/plugins/clipboard/dialogs/paste.js index 48e4072770e..a6fadfbe3d9 100644 --- a/plugins/clipboard/dialogs/paste.js +++ b/plugins/clipboard/dialogs/paste.js @@ -112,11 +112,6 @@ CKEDITOR.dialog.add( 'paste', function( editor ) { id: 'general', label: editor.lang.common.generalTab, elements: [ - { - type: 'html', - id: 'securityMsg', - html: '
' + lang.securityMsg + '
' - }, { type: 'html', id: 'pasteMsg', From 4caa9fce20efb54ddc0c52746dbca2c84537d829 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 25 Nov 2017 16:30:43 +0100 Subject: [PATCH 557/642] Introduce CKEDITOR.plugins.addPasteButton. --- plugins/clipboard/plugin.js | 52 ++++++++++++++++++++++++++++----- plugins/pastefromword/plugin.js | 2 +- plugins/pastetext/plugin.js | 2 +- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index ac0f1e76791..8c72dcf10f6 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -526,6 +526,12 @@ addButtonCommand( 'Copy', 'copy', createCutCopyCmd( 'copy' ), 20, 4 ); addButtonCommand( 'Paste', 'paste', createPasteCmd(), 30, 8 ); + // Force adding touchend handler to paste button (#595). + if ( !editor._.pasteButtons ) { + editor._.pasteButtons = []; + } + editor._.pasteButtons.push( 'Paste' ); + function addButtonCommand( buttonName, commandName, command, toolbarOrder, ctxMenuOrder ) { var lang = editor.lang.clipboard[ commandName ]; @@ -570,17 +576,27 @@ } ); } - // Detect if paste button was touched. In such case we assume that user is using + // Detect if any of paste buttons was touched. In such case we assume that user is using // touch device and force displaying paste dialog (#595). if ( editor.ui.addButton ) { - setTimeout( function() { - var pasteButton = editor.ui.get( 'Paste' ), - buttonElement = editor.container.findOne( '#' + pasteButton._.id ); + // Waiting for editor instance to be ready seems to be the most reliable way to + // be sure that paste buttons are already created. + editor.once( 'instanceReady', function() { + if ( !editor._.pasteButtons ) { + return; + } + + CKEDITOR.tools.array.forEach( editor._.pasteButtons, function( name ) { + var pasteButton = editor.ui.get( name ), + buttonElement = CKEDITOR.document.getById( pasteButton._.id ); - buttonElement.on( 'touchend', function() { - editor._.forcePasteDialog = true; + buttonElement.on( 'touchend', function() { + editor._.forcePasteDialog = true; + } ); } ); - }, 0 ); + + delete editor._.pasteButtons; + } ); } } @@ -1636,6 +1652,28 @@ */ mainPasteEvent: ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) ? 'beforepaste' : 'paste', + /** + * Adds new paste button to the editor. + * + * @since 4.8.0 + * @param {CKEDITOR.editor} editor The editor instance. + * @param {String} name Name of the button. + * @param {Object} definition Definition of the button. + */ + addPasteButton: function( editor, name, definition ) { + if ( !editor.ui.addButton ) { + return; + } + + editor.ui.addButton( name, definition ); + + if ( !editor._.pasteButtons ) { + editor._.pasteButtons = []; + } + + editor._.pasteButtons.push( name ); + }, + /** * Returns `true` if it is expected that a browser provides HTML data through the Clipboard API. * If not, this method returns `false` and as a result CKEditor will use the paste bin. Read more in diff --git a/plugins/pastefromword/plugin.js b/plugins/pastefromword/plugin.js index 7f07beb0d76..25a359da29c 100755 --- a/plugins/pastefromword/plugin.js +++ b/plugins/pastefromword/plugin.js @@ -47,7 +47,7 @@ } ); // Register the toolbar button. - editor.ui.addButton && editor.ui.addButton( 'PasteFromWord', { + CKEDITOR.plugins.clipboard.addPasteButton( editor, 'PasteFromWord', { label: editor.lang.pastefromword.toolbar, command: 'pastefromword', toolbar: 'clipboard,50' diff --git a/plugins/pastetext/plugin.js b/plugins/pastetext/plugin.js index 7bbb444db3d..83716c00833 100644 --- a/plugins/pastetext/plugin.js +++ b/plugins/pastetext/plugin.js @@ -62,7 +62,7 @@ editor.setKeystroke( pasteKeystroke, commandName ); - editor.ui.addButton && editor.ui.addButton( 'PasteText', { + CKEDITOR.plugins.clipboard.addPasteButton( editor, 'PasteText', { label: editor.lang.pastetext.button, command: commandName, toolbar: 'clipboard,40' From ca59b69719c6baa823fe7c00ab6a1710e4b7ed26 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 25 Nov 2017 16:40:01 +0100 Subject: [PATCH 558/642] Hide notification when dialog is forced. --- plugins/clipboard/plugin.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index 8c72dcf10f6..0bbb486ca44 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -472,9 +472,6 @@ // 'dialogHide' will be fired after 'pasteDialogCommit'. editor.on( 'dialogHide', function( evt ) { - // Reset dialog mode (#595). - editor._.forcePasteDialog = false; - evt.removeListener(); evt.data.removeListener( 'pasteDialogCommit', onDialogCommit ); @@ -823,10 +820,13 @@ } firePasteEvents( editor, data, withBeforePaste ); - } else if ( notification ) { + } else if ( notification && !editor._.forcePasteDialog ) { editor.showNotification( msg, 'info', editor.config.clipboard_notificationDuration ); } + // Reset dialog mode (#595). + editor._.forcePasteDialog = false; + editor.fire( 'afterCommandExec', { name: 'paste', command: cmd, From f0f26e5e140e0a1b2b5b4d7eb7452f98c794a4e0 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 25 Nov 2017 16:44:04 +0100 Subject: [PATCH 559/642] Revert "Removed dialog specific tests." This reverts commit 95fdd37269ab0fd4358726b7175f3a7b84cb096f. --- .../manual/pastedialogwordbreak.html | 8 + .../clipboard/manual/pastedialogwordbreak.md | 10 ++ tests/plugins/clipboard/pastedialog.js | 167 ++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 tests/plugins/clipboard/manual/pastedialogwordbreak.html create mode 100644 tests/plugins/clipboard/manual/pastedialogwordbreak.md create mode 100644 tests/plugins/clipboard/pastedialog.js diff --git a/tests/plugins/clipboard/manual/pastedialogwordbreak.html b/tests/plugins/clipboard/manual/pastedialogwordbreak.html new file mode 100644 index 00000000000..186abf093ee --- /dev/null +++ b/tests/plugins/clipboard/manual/pastedialogwordbreak.html @@ -0,0 +1,8 @@ + + + diff --git a/tests/plugins/clipboard/manual/pastedialogwordbreak.md b/tests/plugins/clipboard/manual/pastedialogwordbreak.md new file mode 100644 index 00000000000..bc68e1131f2 --- /dev/null +++ b/tests/plugins/clipboard/manual/pastedialogwordbreak.md @@ -0,0 +1,10 @@ +@bender-tags: tc, 4.5.2, 13495 +@bender-ui: collapsed +@bender-ckeditor-plugins: wysiwygarea, toolbar, clipboard, floatingspace, htmlwriter, + +1. Click paste button on the toolbar. +1. If the browser will ask for clipboard access permission - chose option that will **not allow** it. +1. In the paste dialog, put word longer than text area's width. + +#### Expected result: +Long words should be broken into separate lines and no horizontal scroll bar should be visible. diff --git a/tests/plugins/clipboard/pastedialog.js b/tests/plugins/clipboard/pastedialog.js new file mode 100644 index 00000000000..5da1e193d33 --- /dev/null +++ b/tests/plugins/clipboard/pastedialog.js @@ -0,0 +1,167 @@ +/* bender-tags: editor,unit,dialog */ +/* bender-ckeditor-plugins: entities,button,clipboard */ + +( function() { + 'use strict'; + + bender.editor = true; + + bender.test( { + setUp: function() { + // Force result data un-formatted. + this.editor.dataProcessor.writer._.rules = {}; + this.editor.focus(); + }, + + 'pasteDialog event': function() { + var tc = this, + editor = this.editor; + + editor.on( 'dialogShow', function( evt ) { + evt.removeListener(); + + tc.resume( function() { + var dialog = editor._.storedDialogs.paste; + assert.isTrue( !!dialog ); + + dialog.fire( 'cancel' ); + dialog.hide(); + } ); + } ); + + editor.fire( 'pasteDialog' ); + tc.wait(); + }, + + 'paste html': CKEDITOR.env.ie ? + function() { + var tc = this, + editor = this.editor; + + editor.on( 'pasteDialogCommit', function( evt ) { + evt.removeListener(); + + tc.resume( function() { + assert.areEqual( 'abcdef', evt.data.dataValue.toLowerCase() ); + } ); + } ); + + editor.on( 'dialogShow', function( evt ) { + evt.removeListener(); + + tc.resume( function() { + var dialog = editor._.storedDialogs.paste; + assert.isTrue( !!dialog ); + + var frameDoc = dialog.getContentElement( 'general', 'editing_area' ) + .getInputElement().getFrameDocument(); + + // IE needs some time to create editable body. + setTimeout( function() { + frameDoc.getBody().setHtml( 'abcdef' ); + + dialog.fire( 'ok' ); + dialog.hide(); + }, 10 ); + + tc.wait(); + } ); + } ); + + // Editor.execCommand( 'paste' ) opens IE security alert which breaks tests. + editor.openDialog( 'paste' ); + tc.wait(); + } + : + function() { + var tc = this, + editor = this.editor, + beforePasteFired = false; + + editor.on( 'beforePaste', function( evt ) { + evt.removeListener(); + + tc.resume( function() { + assert.areEqual( 'auto', evt.data.type ); + beforePasteFired = true; + tc.wait(); + } ); + } ); + + editor.on( 'paste', function( evt ) { + evt.removeListener(); + + tc.resume( function() { + assert.isTrue( beforePasteFired ); + assert.areEqual( 'html', evt.data.type ); + assert.areEqual( 'abcdef', evt.data.dataValue ); + } ); + } ); + + editor.on( 'dialogShow', function( evt ) { + evt.removeListener(); + + tc.resume( function() { + var dialog = editor._.storedDialogs.paste; + assert.isTrue( !!dialog ); + + var frameDoc = dialog.getContentElement( 'general', 'editing_area' ) + .getInputElement().getFrameDocument(); + + frameDoc.getBody().setHtml( 'abcdef' ); + + dialog.fire( 'ok' ); + dialog.hide(); + + tc.wait(); + } ); + } ); + + setTimeout( function() { + editor.execCommand( 'paste' ); + } ); + tc.wait(); + }, + + 'test paste dialog focus': function() { + var editor = this.editor; + + editor.on( 'ariaWidget', function( event ) { + if ( !event.data.is( 'iframe' ) ) + return; + + event.removeListener(); + + setTimeout( function() { + resume( function() { + var iframe = event.data, + active = CKEDITOR.document.getActive(), + dialog = editor._.storedDialogs.paste; + + assert.isTrue( editor.focusManager.hasFocus, 'editor has focus on paste dialog opened.' ); + assert.areSame( iframe, active, 'paste area has focused on paste dialog opened' ); + dialog.hide(); + } ); + } ); + } ); + + editor.openDialog( 'paste' ); + wait(); + }, + + 'test paste event structure': function() { + var editor = this.editor, + dataTransfer = CKEDITOR.plugins.clipboard.initPasteDataTransfer(); + + editor.once( 'paste', function( evt ) { + evt.cancel(); + + assert.areSame( 'foo', evt.data.dataValue, 'dataValue' ); + assert.areSame( 'paste', evt.data.method, 'method' ); + assert.areSame( dataTransfer, evt.data.dataTransfer, 'dataTransfer' ); + } ); + + editor.fire( 'pasteDialogCommit', { dataValue: 'foo', dataTransfer: dataTransfer } ); + } + } ); +} )(); \ No newline at end of file From 77906c20f025da47dd3c1e9ddab6134837d77a9b Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 25 Nov 2017 17:00:32 +0100 Subject: [PATCH 560/642] Update unit tests. --- tests/plugins/clipboard/pastedialog.js | 71 ++++++++++---------------- 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/tests/plugins/clipboard/pastedialog.js b/tests/plugins/clipboard/pastedialog.js index 5da1e193d33..6c1e8e7acb2 100644 --- a/tests/plugins/clipboard/pastedialog.js +++ b/tests/plugins/clipboard/pastedialog.js @@ -4,7 +4,12 @@ ( function() { 'use strict'; - bender.editor = true; + bender.editor = { + config: { + // Force language to avoid issues with missing dialog's title. + language: 'en' + } + }; bender.test( { setUp: function() { @@ -33,50 +38,18 @@ tc.wait(); }, - 'paste html': CKEDITOR.env.ie ? - function() { - var tc = this, - editor = this.editor; - - editor.on( 'pasteDialogCommit', function( evt ) { - evt.removeListener(); - - tc.resume( function() { - assert.areEqual( 'abcdef', evt.data.dataValue.toLowerCase() ); - } ); - } ); - - editor.on( 'dialogShow', function( evt ) { - evt.removeListener(); - - tc.resume( function() { - var dialog = editor._.storedDialogs.paste; - assert.isTrue( !!dialog ); - - var frameDoc = dialog.getContentElement( 'general', 'editing_area' ) - .getInputElement().getFrameDocument(); + 'paste html': function() { + if ( CKEDITOR.env.ie ) { + assert.ignore(); + } - // IE needs some time to create editable body. - setTimeout( function() { - frameDoc.getBody().setHtml( 'abcdef' ); - - dialog.fire( 'ok' ); - dialog.hide(); - }, 10 ); - - tc.wait(); - } ); - } ); - - // Editor.execCommand( 'paste' ) opens IE security alert which breaks tests. - editor.openDialog( 'paste' ); - tc.wait(); - } - : - function() { var tc = this, editor = this.editor, - beforePasteFired = false; + beforePasteFired = false, + notificationSpy = sinon.spy(), + notificationListener; + + notificationListener = editor.on( 'notificationShow', notificationSpy ); editor.on( 'beforePaste', function( evt ) { evt.removeListener(); @@ -95,6 +68,16 @@ assert.isTrue( beforePasteFired ); assert.areEqual( 'html', evt.data.type ); assert.areEqual( 'abcdef', evt.data.dataValue ); + + tc.wait(); + } ); + } ); + + editor.on( 'afterPaste', function() { + tc.resume( function() { + notificationListener.removeListener(); + + assert.areSame( 0, notificationSpy.callCount, 'notifications count' ); } ); } ); @@ -118,6 +101,8 @@ } ); setTimeout( function() { + //Force dialog. + editor._.forcePasteDialog = true; editor.execCommand( 'paste' ); } ); tc.wait(); @@ -164,4 +149,4 @@ editor.fire( 'pasteDialogCommit', { dataValue: 'foo', dataTransfer: dataTransfer } ); } } ); -} )(); \ No newline at end of file +} )(); From a126117d68864c52beff6b6a792e752bf7b0dba6 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 25 Nov 2017 18:57:40 +0100 Subject: [PATCH 561/642] Move info about commited state into dialog itself. --- plugins/clipboard/dialogs/paste.js | 5 +++++ plugins/clipboard/plugin.js | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/clipboard/dialogs/paste.js b/plugins/clipboard/dialogs/paste.js index a6fadfbe3d9..51fec85d324 100644 --- a/plugins/clipboard/dialogs/paste.js +++ b/plugins/clipboard/dialogs/paste.js @@ -97,6 +97,9 @@ CKEDITOR.dialog.add( 'paste', function( editor ) { // If custom title not set, use default one. this.parts.title.setHtml( this.customTitle || lang.title ); this.customTitle = null; + + // Reset commited indicator. + this._.commited = false; }, onLoad: function() { @@ -224,6 +227,8 @@ CKEDITOR.dialog.add( 'paste', function( editor ) { // Saving the contents so changes until paste is complete will not take place (#7500) html = body.getHtml(); + this.getDialog()._.commited = true; + // Opera needs some time to think about what has happened and what it should do now. setTimeout( function() { editor.fire( 'pasteDialogCommit', { diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index 0bbb486ca44..bf47acb98e3 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -441,7 +441,6 @@ */ editor.getClipboardData = function( callbackOrOptions, callback ) { var beforePasteNotCanceled = false, - dialogCommited = false, dataType = 'auto'; // Options are optional - args shift. @@ -478,8 +477,9 @@ // Because Opera has to wait a while in pasteDialog we have to wait here. setTimeout( function() { // Notify even if user canceled dialog (clicked 'cancel', ESC, etc). - if ( !dialogCommited ) + if ( !evt.data._.commited ) { callback( null ); + } }, 10 ); } ); } else { @@ -504,7 +504,7 @@ // Cancel pasteDialogCommit so paste dialog won't automatically fire // 'paste' evt by itself. evt.cancel(); - dialogCommited = true; + callback( { type: dataType, dataValue: evt.data.dataValue, From 0868a18f81c3a99a3f6909cda69a810666056f17 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 25 Nov 2017 18:59:18 +0100 Subject: [PATCH 562/642] Add and update unit tests. --- tests/plugins/clipboard/mobilefix.js | 118 +++++++++++++++++++++++++ tests/plugins/clipboard/pastedialog.js | 3 + 2 files changed, 121 insertions(+) create mode 100644 tests/plugins/clipboard/mobilefix.js diff --git a/tests/plugins/clipboard/mobilefix.js b/tests/plugins/clipboard/mobilefix.js new file mode 100644 index 00000000000..b4ce004236a --- /dev/null +++ b/tests/plugins/clipboard/mobilefix.js @@ -0,0 +1,118 @@ +/* bender-tags: editor,clipboard */ +/* bender-ckeditor-plugins: toolbar,clipboard,wysiwygarea */ + +( function() { + 'use strict'; + + bender.editors = { + classic: { + config: { + language: 'en' + } + }, + + divarea: { + config: { + language: 'en', + extraPlugins: 'divarea' + } + }, + + inline: { + creator: 'inline', + config: { + language: 'en' + } + } + }; + + function getButtonElement( editor, name ) { + var button = editor.ui.get( name ), + buttonElement = CKEDITOR.document.getById( button._.id ); + + return buttonElement; + } + + function assertTouchEnd( editor, buttonName ) { + var buttonElement = getButtonElement( editor, buttonName ), + dialogSpy = sinon.spy(), + dialogListener; + + //Reset forcePasteDialog just to be sure + editor._.forcePasteDialog = false; + + dialogListener = editor.on( 'pasteDialog', dialogSpy ); + + editor.once( 'dialogShow', function( evt ) { + resume( function() { + var dialog = evt.data; + + dialogListener.removeListener(); + + assert.areSame( 1, dialogSpy.callCount, 'pasteDialog event count' ); + + dialog.fire( 'cancel' ); + dialog.hide(); + } ); + } ); + + buttonElement.once( 'touchend', function() { + assert.isTrue( editor._.forcePasteDialog, 'Forcing paste dialog' ); + }, null, null, 999 ); + + buttonElement.fire( 'touchend' ); + buttonElement.$.click(); + wait(); + } + + function assertClick( editor, buttonName ) { + var buttonElement = getButtonElement( editor, buttonName ); + + //Reset forcePasteDialog just to be sure + editor._.forcePasteDialog = false; + + buttonElement.once( 'click', function() { + assert.isFalse( editor._.forcePasteDialog, 'Forcing paste dialog' ); + }, null, null, 999 ); + + buttonElement.$.click(); + } + + var tests = { + 'test force dialog when button is touched': function( editor ) { + assertTouchEnd( editor, 'Paste' ); + }, + + 'test does not force dialog when button is clicked': function( editor ) { + assertClick( editor, 'Paste' ); + } + }; + + tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); + + tests[ 'test add custom paste button' ] = function() { + bender.editorBot.create( { + name: 'custom_button', + config: { + language: 'en', + on: { + pluginsLoaded: function( evt ) { + var editor = evt.editor; + + CKEDITOR.plugins.clipboard.addPasteButton( editor, 'CustomPaste', { + label: 'test', + command: 'paste', + toolbar: 'clipboard,40' + } ); + + arrayAssert.itemsAreEqual( [ 'Paste', 'CustomPaste' ], editor._.pasteButtons ); + } + } + } + }, function( bot ) { + assertTouchEnd( bot.editor, 'CustomPaste' ); + } ); + }; + + bender.test( tests ); +}() ); diff --git a/tests/plugins/clipboard/pastedialog.js b/tests/plugins/clipboard/pastedialog.js index 6c1e8e7acb2..1660db31414 100644 --- a/tests/plugins/clipboard/pastedialog.js +++ b/tests/plugins/clipboard/pastedialog.js @@ -78,6 +78,8 @@ notificationListener.removeListener(); assert.areSame( 0, notificationSpy.callCount, 'notifications count' ); + assert.isTrue( editor._.storedDialogs.paste._.commited, 'Dialog commited state (after)' ); + assert.isFalse( editor._.forcePasteDialog, 'Force paste dialog' ); } ); } ); @@ -87,6 +89,7 @@ tc.resume( function() { var dialog = editor._.storedDialogs.paste; assert.isTrue( !!dialog ); + assert.isFalse( dialog._.commited, 'Dialog commited state (before)' ); var frameDoc = dialog.getContentElement( 'general', 'editing_area' ) .getInputElement().getFrameDocument(); From 90aed9f07399a5286e548a95aac71bf19955e3c4 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Sat, 25 Nov 2017 19:07:16 +0100 Subject: [PATCH 563/642] Add manual test. --- .../clipboard/manual/pastedialogmobile.html | 9 +++++ .../clipboard/manual/pastedialogmobile.md | 33 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 tests/plugins/clipboard/manual/pastedialogmobile.html create mode 100644 tests/plugins/clipboard/manual/pastedialogmobile.md diff --git a/tests/plugins/clipboard/manual/pastedialogmobile.html b/tests/plugins/clipboard/manual/pastedialogmobile.html new file mode 100644 index 00000000000..7f4af0a5063 --- /dev/null +++ b/tests/plugins/clipboard/manual/pastedialogmobile.html @@ -0,0 +1,9 @@ + + + diff --git a/tests/plugins/clipboard/manual/pastedialogmobile.md b/tests/plugins/clipboard/manual/pastedialogmobile.md new file mode 100644 index 00000000000..f70bd8a280b --- /dev/null +++ b/tests/plugins/clipboard/manual/pastedialogmobile.md @@ -0,0 +1,33 @@ +@bender-tags: bug, 4.8.0, 595 +@bender-ui: collapsed +@bender-ckeditor-plugins: wysiwygarea, toolbar, clipboard, floatingspace, htmlwriter, + +## On non-touch devices + +Click paste button on the toolbar. + +### Expected result: + +Notification about unability to paste in such way is displayed. + +## On touch devices + +Touch paste button on the toolbar. + +### Expected result: + +* Paste dialog is shown. +* Dismissing paste dialog does not trigger any notification. + +## On non-touch devices with touch emulation (e.g. responsive view in browser) + +1. Enable touch emulation. +2. Touch paste button on the toolbar. +3. Close paste dialog. +4. Disable touch emulation. +5. Click paste button on the toolbar. + +### Expected result: + +* Touching button should display paste dialog. +* Clicking button should display notification. From bdb0244b8bc2cddb27a57d4c8dd8c39727179cc2 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 29 Nov 2017 00:29:41 +0100 Subject: [PATCH 564/642] Tests added manual test for pasting without toolbar a button. --- tests/plugins/clipboard/manual/missingbutton.html | 8 ++++++++ tests/plugins/clipboard/manual/missingbutton.md | 13 +++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 tests/plugins/clipboard/manual/missingbutton.html create mode 100644 tests/plugins/clipboard/manual/missingbutton.md diff --git a/tests/plugins/clipboard/manual/missingbutton.html b/tests/plugins/clipboard/manual/missingbutton.html new file mode 100644 index 00000000000..8fa506665de --- /dev/null +++ b/tests/plugins/clipboard/manual/missingbutton.html @@ -0,0 +1,8 @@ + + + diff --git a/tests/plugins/clipboard/manual/missingbutton.md b/tests/plugins/clipboard/manual/missingbutton.md new file mode 100644 index 00000000000..1b5926ee5d3 --- /dev/null +++ b/tests/plugins/clipboard/manual/missingbutton.md @@ -0,0 +1,13 @@ +@bender-tags: bug, 4.8.0, 595 +@bender-ui: collapsed +@bender-ckeditor-plugins: wysiwygarea, toolbar, clipboard, floatingspace, htmlwriter + +1. Open dev console. + +## Expected + +No error is thrown. + +## Actual + +`plugin.js:588 Uncaught TypeError: Cannot read property '_' of undefined` error is logged. \ No newline at end of file From 466ecc5ebf792d2dcfd6705715882eea9001b116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Wed, 13 Dec 2017 10:42:35 +0100 Subject: [PATCH 565/642] Handle removed buttons. --- plugins/clipboard/plugin.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index bf47acb98e3..567a1d3d23c 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -584,12 +584,15 @@ } CKEDITOR.tools.array.forEach( editor._.pasteButtons, function( name ) { - var pasteButton = editor.ui.get( name ), - buttonElement = CKEDITOR.document.getById( pasteButton._.id ); - - buttonElement.on( 'touchend', function() { - editor._.forcePasteDialog = true; - } ); + var pasteButton = editor.ui.get( name ); + // Check if button was not removed by `removeButtons` config. + if ( pasteButton ) { + var buttonElement = CKEDITOR.document.getById( pasteButton._.id ); + + buttonElement.on( 'touchend', function() { + editor._.forcePasteDialog = true; + } ); + } } ); delete editor._.pasteButtons; @@ -1653,7 +1656,8 @@ mainPasteEvent: ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) ? 'beforepaste' : 'paste', /** - * Adds new paste button to the editor. + * Adds new paste button to the editor. In order for the button + * to displayPaste Dialog on mobile devices it should be added via this method. * * @since 4.8.0 * @param {CKEDITOR.editor} editor The editor instance. @@ -1670,7 +1674,6 @@ if ( !editor._.pasteButtons ) { editor._.pasteButtons = []; } - editor._.pasteButtons.push( name ); }, From 3442edd4dcc6014717263f0a69d0c6d151a73e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Wed, 13 Dec 2017 14:13:43 +0100 Subject: [PATCH 566/642] Tests: removed paste buttons tests. --- .../plugins/clipboard/manual/missingbutton.md | 4 +-- tests/plugins/clipboard/pastedialog.js | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/tests/plugins/clipboard/manual/missingbutton.md b/tests/plugins/clipboard/manual/missingbutton.md index 1b5926ee5d3..2f5daccd556 100644 --- a/tests/plugins/clipboard/manual/missingbutton.md +++ b/tests/plugins/clipboard/manual/missingbutton.md @@ -1,4 +1,4 @@ -@bender-tags: bug, 4.8.0, 595 +@bender-tags: bug, 4.8.1, 595 @bender-ui: collapsed @bender-ckeditor-plugins: wysiwygarea, toolbar, clipboard, floatingspace, htmlwriter @@ -10,4 +10,4 @@ No error is thrown. ## Actual -`plugin.js:588 Uncaught TypeError: Cannot read property '_' of undefined` error is logged. \ No newline at end of file +The `plugin.js:588 Uncaught TypeError: Cannot read property '_' of undefined` error is logged. diff --git a/tests/plugins/clipboard/pastedialog.js b/tests/plugins/clipboard/pastedialog.js index 1660db31414..2aac0375f36 100644 --- a/tests/plugins/clipboard/pastedialog.js +++ b/tests/plugins/clipboard/pastedialog.js @@ -150,6 +150,32 @@ } ); editor.fire( 'pasteDialogCommit', { dataValue: 'foo', dataTransfer: dataTransfer } ); + }, + + 'test paste dialog with some paste buttons removed': function() { + bender.editorBot.create( { + name: 'some_paste_buttons', + config: { + language: 'en', + extraPlugins: 'pastetext,pastefromword', + removeButtons: 'Paste,PasteText' + } + }, function( bot ) { + assert.isUndefined( bot.editor._.pasteButtons ); + } ); + }, + + 'test paste dialog with all paste buttons removed': function() { + bender.editorBot.create( { + name: 'no_paste_buttons', + config: { + language: 'en', + extraPlugins: 'pastetext', + removeButtons: 'Paste,PasteText' + } + }, function( bot ) { + assert.isUndefined( bot.editor._.pasteButtons ); + } ); } } ); } )(); From 75a4d217d1937d316794a265ca9087472797af6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Wed, 13 Dec 2017 14:34:12 +0100 Subject: [PATCH 567/642] Removed Opera workaround as it is not needed anymore. --- plugins/clipboard/dialogs/paste.js | 16 +++++++--------- plugins/clipboard/plugin.js | 11 ++++------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/plugins/clipboard/dialogs/paste.js b/plugins/clipboard/dialogs/paste.js index 51fec85d324..780c334fb38 100644 --- a/plugins/clipboard/dialogs/paste.js +++ b/plugins/clipboard/dialogs/paste.js @@ -72,13 +72,14 @@ CKEDITOR.dialog.add( 'paste', function( editor ) { // then fire paste event. // Do not use editor#paste, because it would start from beforePaste event. editor.on( 'pasteDialogCommit', function( evt ) { - if ( evt.data ) + if ( evt.data ) { editor.fire( 'paste', { type: 'auto', dataValue: evt.data.dataValue, method: 'paste', dataTransfer: evt.data.dataTransfer || clipboard.initPasteDataTransfer() } ); + } }, null, null, 1000 ); return { @@ -229,14 +230,11 @@ CKEDITOR.dialog.add( 'paste', function( editor ) { this.getDialog()._.commited = true; - // Opera needs some time to think about what has happened and what it should do now. - setTimeout( function() { - editor.fire( 'pasteDialogCommit', { - dataValue: html, - // Avoid error if there was no paste so lastDataTransfer is null. - dataTransfer: lastDataTransfer || clipboard.initPasteDataTransfer() - } ); - }, 0 ); + editor.fire( 'pasteDialogCommit', { + dataValue: html, + // Avoid error if there was no paste so lastDataTransfer is null. + dataTransfer: lastDataTransfer || clipboard.initPasteDataTransfer() + } ); } } ] diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index 567a1d3d23c..5a6034bf23b 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -474,13 +474,10 @@ evt.removeListener(); evt.data.removeListener( 'pasteDialogCommit', onDialogCommit ); - // Because Opera has to wait a while in pasteDialog we have to wait here. - setTimeout( function() { - // Notify even if user canceled dialog (clicked 'cancel', ESC, etc). - if ( !evt.data._.commited ) { - callback( null ); - } - }, 10 ); + // Notify even if user canceled dialog (clicked 'cancel', ESC, etc). + if ( !evt.data._.commited ) { + callback( null ); + } } ); } else { callback( null ); From 03a67d2785cfa07099f226cb10c0ceca10049171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Wed, 13 Dec 2017 16:09:45 +0100 Subject: [PATCH 568/642] Restore paste dialog lang entries - pastetext plugin. --- plugins/pastetext/lang/af.js | 3 ++- plugins/pastetext/lang/ar.js | 3 ++- plugins/pastetext/lang/az.js | 3 ++- plugins/pastetext/lang/bg.js | 3 ++- plugins/pastetext/lang/bn.js | 3 ++- plugins/pastetext/lang/bs.js | 3 ++- plugins/pastetext/lang/ca.js | 3 ++- plugins/pastetext/lang/cs.js | 3 ++- plugins/pastetext/lang/cy.js | 3 ++- plugins/pastetext/lang/da.js | 3 ++- plugins/pastetext/lang/de-ch.js | 3 ++- plugins/pastetext/lang/de.js | 3 ++- plugins/pastetext/lang/el.js | 3 ++- plugins/pastetext/lang/en-au.js | 3 ++- plugins/pastetext/lang/en-ca.js | 3 ++- plugins/pastetext/lang/en-gb.js | 3 ++- plugins/pastetext/lang/en.js | 3 ++- plugins/pastetext/lang/eo.js | 3 ++- plugins/pastetext/lang/es-mx.js | 3 ++- plugins/pastetext/lang/es.js | 3 ++- plugins/pastetext/lang/et.js | 3 ++- plugins/pastetext/lang/eu.js | 3 ++- plugins/pastetext/lang/fa.js | 3 ++- plugins/pastetext/lang/fi.js | 3 ++- plugins/pastetext/lang/fo.js | 3 ++- plugins/pastetext/lang/fr-ca.js | 3 ++- plugins/pastetext/lang/fr.js | 3 ++- plugins/pastetext/lang/gl.js | 3 ++- plugins/pastetext/lang/gu.js | 3 ++- plugins/pastetext/lang/he.js | 3 ++- plugins/pastetext/lang/hi.js | 3 ++- plugins/pastetext/lang/hr.js | 3 ++- plugins/pastetext/lang/hu.js | 3 ++- plugins/pastetext/lang/id.js | 3 ++- plugins/pastetext/lang/is.js | 3 ++- plugins/pastetext/lang/it.js | 3 ++- plugins/pastetext/lang/ja.js | 3 ++- plugins/pastetext/lang/ka.js | 3 ++- plugins/pastetext/lang/km.js | 3 ++- plugins/pastetext/lang/ko.js | 3 ++- plugins/pastetext/lang/ku.js | 3 ++- plugins/pastetext/lang/lt.js | 3 ++- plugins/pastetext/lang/lv.js | 3 ++- plugins/pastetext/lang/mk.js | 3 ++- plugins/pastetext/lang/mn.js | 3 ++- plugins/pastetext/lang/ms.js | 3 ++- plugins/pastetext/lang/nb.js | 3 ++- plugins/pastetext/lang/nl.js | 3 ++- plugins/pastetext/lang/no.js | 3 ++- plugins/pastetext/lang/oc.js | 3 ++- plugins/pastetext/lang/pl.js | 3 ++- plugins/pastetext/lang/pt-br.js | 3 ++- plugins/pastetext/lang/pt.js | 3 ++- plugins/pastetext/lang/ro.js | 3 ++- plugins/pastetext/lang/ru.js | 3 ++- plugins/pastetext/lang/si.js | 3 ++- plugins/pastetext/lang/sk.js | 3 ++- plugins/pastetext/lang/sl.js | 3 ++- plugins/pastetext/lang/sq.js | 3 ++- plugins/pastetext/lang/sr-latn.js | 3 ++- plugins/pastetext/lang/sr.js | 3 ++- plugins/pastetext/lang/sv.js | 3 ++- plugins/pastetext/lang/th.js | 3 ++- plugins/pastetext/lang/tr.js | 3 ++- plugins/pastetext/lang/tt.js | 3 ++- plugins/pastetext/lang/ug.js | 3 ++- plugins/pastetext/lang/uk.js | 3 ++- plugins/pastetext/lang/vi.js | 3 ++- plugins/pastetext/lang/zh-cn.js | 3 ++- plugins/pastetext/lang/zh.js | 3 ++- 70 files changed, 140 insertions(+), 70 deletions(-) diff --git a/plugins/pastetext/lang/af.js b/plugins/pastetext/lang/af.js index aa934f6ee3c..108c30ee55e 100644 --- a/plugins/pastetext/lang/af.js +++ b/plugins/pastetext/lang/af.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'af', { button: 'Plak as eenvoudige teks', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Plak as eenvoudige teks' } ); diff --git a/plugins/pastetext/lang/ar.js b/plugins/pastetext/lang/ar.js index 3059ccbc5c1..2e2a0c43d09 100644 --- a/plugins/pastetext/lang/ar.js +++ b/plugins/pastetext/lang/ar.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ar', { button: 'لصق كنص بسيط', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'لصق كنص بسيط' } ); diff --git a/plugins/pastetext/lang/az.js b/plugins/pastetext/lang/az.js index 70b673af5d7..81bf63f4bed 100644 --- a/plugins/pastetext/lang/az.js +++ b/plugins/pastetext/lang/az.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'az', { button: 'Yalnız mətni saxla', - pasteNotification: 'Sizin İnternet bələdçiniz bu cür mətnin köçürməsini dəstəklənmir. Əlavə etmək üçün %1 basın.' + pasteNotification: 'Sizin İnternet bələdçiniz bu cür mətnin köçürməsini dəstəklənmir. Əlavə etmək üçün %1 basın.', + title: 'Paste as Plain Text' // MISSING } ); diff --git a/plugins/pastetext/lang/bg.js b/plugins/pastetext/lang/bg.js index 07a799dfc6a..977d8190cfe 100644 --- a/plugins/pastetext/lang/bg.js +++ b/plugins/pastetext/lang/bg.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'bg', { button: 'Вмъкни като чист текст', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Вмъкни като чист текст' } ); diff --git a/plugins/pastetext/lang/bn.js b/plugins/pastetext/lang/bn.js index 0c4ae010d56..9bb6518dd50 100644 --- a/plugins/pastetext/lang/bn.js +++ b/plugins/pastetext/lang/bn.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'bn', { button: 'সাধারণ টেক্সট হিসেবে পেইস্ট করি', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'সাদা টেক্সট হিসেবে পেস্ট কর' } ); diff --git a/plugins/pastetext/lang/bs.js b/plugins/pastetext/lang/bs.js index 3760ca6ee1e..1e4edb2f84c 100644 --- a/plugins/pastetext/lang/bs.js +++ b/plugins/pastetext/lang/bs.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'bs', { button: 'Zalijepi kao obièan tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Zalijepi kao obièan tekst' } ); diff --git a/plugins/pastetext/lang/ca.js b/plugins/pastetext/lang/ca.js index dab04a3669a..ece87869837 100644 --- a/plugins/pastetext/lang/ca.js +++ b/plugins/pastetext/lang/ca.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ca', { button: 'Enganxa com a text no formatat', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Enganxa com a text no formatat' } ); diff --git a/plugins/pastetext/lang/cs.js b/plugins/pastetext/lang/cs.js index 1673b898e52..22b594164e7 100644 --- a/plugins/pastetext/lang/cs.js +++ b/plugins/pastetext/lang/cs.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'cs', { button: 'Vložit jako čistý text', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Vložit jako čistý text' } ); diff --git a/plugins/pastetext/lang/cy.js b/plugins/pastetext/lang/cy.js index e54feae280e..72a563b21f9 100644 --- a/plugins/pastetext/lang/cy.js +++ b/plugins/pastetext/lang/cy.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'cy', { button: 'Gludo fel testun plaen', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Gludo fel Testun Plaen' } ); diff --git a/plugins/pastetext/lang/da.js b/plugins/pastetext/lang/da.js index 2823d5b9ec9..25ff7ba1e27 100644 --- a/plugins/pastetext/lang/da.js +++ b/plugins/pastetext/lang/da.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'da', { button: 'Indsæt som ikke-formateret tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Indsæt som ikke-formateret tekst' } ); diff --git a/plugins/pastetext/lang/de-ch.js b/plugins/pastetext/lang/de-ch.js index 6e11031bd22..e7d72ae46b2 100644 --- a/plugins/pastetext/lang/de-ch.js +++ b/plugins/pastetext/lang/de-ch.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'de-ch', { button: 'Als Klartext einfügen', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Als Klartext einfügen' } ); diff --git a/plugins/pastetext/lang/de.js b/plugins/pastetext/lang/de.js index 008b81f5840..97659ecdd85 100644 --- a/plugins/pastetext/lang/de.js +++ b/plugins/pastetext/lang/de.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'de', { button: 'Als Klartext einfügen', - pasteNotification: 'Ihr Browser verhindert das Einfügen von Text über diesen Weg. Zum einfügen drücken Sie %1.' + pasteNotification: 'Ihr Browser verhindert das Einfügen von Text über diesen Weg. Zum einfügen drücken Sie %1.', + title: 'Als Klartext einfügen' } ); diff --git a/plugins/pastetext/lang/el.js b/plugins/pastetext/lang/el.js index 5b4185e1fca..007d732dafd 100644 --- a/plugins/pastetext/lang/el.js +++ b/plugins/pastetext/lang/el.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'el', { button: 'Επικόλληση ως απλό κείμενο', - pasteNotification: 'Ο φυλλομετρητής σας δεν επιτρέπει την επικόλληση απλού κειμένου με αυτόν τον τρόπο. Πατήστε 1% για να επικολλήστε.' + pasteNotification: 'Ο φυλλομετρητής σας δεν επιτρέπει την επικόλληση απλού κειμένου με αυτόν τον τρόπο. Πατήστε 1% για να επικολλήστε.', + title: 'Επικόλληση ως απλό κείμενο' } ); diff --git a/plugins/pastetext/lang/en-au.js b/plugins/pastetext/lang/en-au.js index b071d3a93ea..47f527a0727 100644 --- a/plugins/pastetext/lang/en-au.js +++ b/plugins/pastetext/lang/en-au.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'en-au', { button: 'Paste as plain text', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', + title: 'Paste as Plain Text' } ); diff --git a/plugins/pastetext/lang/en-ca.js b/plugins/pastetext/lang/en-ca.js index 10c799870bc..83306dba8af 100644 --- a/plugins/pastetext/lang/en-ca.js +++ b/plugins/pastetext/lang/en-ca.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'en-ca', { button: 'Paste as plain text', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Paste as Plain Text' } ); diff --git a/plugins/pastetext/lang/en-gb.js b/plugins/pastetext/lang/en-gb.js index a0ac28ca4be..dd89d7deaeb 100644 --- a/plugins/pastetext/lang/en-gb.js +++ b/plugins/pastetext/lang/en-gb.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'en-gb', { button: 'Paste as plain text', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Paste as Plain Text' } ); diff --git a/plugins/pastetext/lang/en.js b/plugins/pastetext/lang/en.js index eab4bb33988..b90800d8c63 100644 --- a/plugins/pastetext/lang/en.js +++ b/plugins/pastetext/lang/en.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'en', { button: 'Paste as plain text', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', + title: 'Paste as Plain Text' } ); diff --git a/plugins/pastetext/lang/eo.js b/plugins/pastetext/lang/eo.js index c6da27b027d..242091947a3 100644 --- a/plugins/pastetext/lang/eo.js +++ b/plugins/pastetext/lang/eo.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'eo', { button: 'Interglui kiel platan tekston', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Interglui kiel platan tekston' } ); diff --git a/plugins/pastetext/lang/es-mx.js b/plugins/pastetext/lang/es-mx.js index e056d91e5d0..5400f6ea474 100644 --- a/plugins/pastetext/lang/es-mx.js +++ b/plugins/pastetext/lang/es-mx.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'es-mx', { button: 'Pegar como texto plano', - pasteNotification: 'Su navegador no permite esta forma de pegar texto plano. Presiona %1 para pegar.' + pasteNotification: 'Su navegador no permite esta forma de pegar texto plano. Presiona %1 para pegar.', + title: 'Paste as Plain Text' // MISSING } ); diff --git a/plugins/pastetext/lang/es.js b/plugins/pastetext/lang/es.js index 8533557a46d..22efecbfe40 100644 --- a/plugins/pastetext/lang/es.js +++ b/plugins/pastetext/lang/es.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'es', { button: 'Pegar como Texto Plano', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Pegar como Texto Plano' } ); diff --git a/plugins/pastetext/lang/et.js b/plugins/pastetext/lang/et.js index aaaa00acf2f..4a6acd2c132 100644 --- a/plugins/pastetext/lang/et.js +++ b/plugins/pastetext/lang/et.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'et', { button: 'Asetamine tavalise tekstina', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Asetamine tavalise tekstina' } ); diff --git a/plugins/pastetext/lang/eu.js b/plugins/pastetext/lang/eu.js index 227ad3cf79b..d18377c8703 100644 --- a/plugins/pastetext/lang/eu.js +++ b/plugins/pastetext/lang/eu.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'eu', { button: 'Itsatsi testu arrunta bezala', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Itsatsi testu arrunta bezala' } ); diff --git a/plugins/pastetext/lang/fa.js b/plugins/pastetext/lang/fa.js index b549dce8adb..19794a9d2e0 100644 --- a/plugins/pastetext/lang/fa.js +++ b/plugins/pastetext/lang/fa.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'fa', { button: 'چسباندن به عنوان متن ساده', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'چسباندن به عنوان متن ساده' } ); diff --git a/plugins/pastetext/lang/fi.js b/plugins/pastetext/lang/fi.js index ca1d0c29d18..9edee11450f 100644 --- a/plugins/pastetext/lang/fi.js +++ b/plugins/pastetext/lang/fi.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'fi', { button: 'Liitä tekstinä', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Liitä tekstinä' } ); diff --git a/plugins/pastetext/lang/fo.js b/plugins/pastetext/lang/fo.js index 2bccfddad8c..1b1b524721a 100644 --- a/plugins/pastetext/lang/fo.js +++ b/plugins/pastetext/lang/fo.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'fo', { button: 'Innrita som reinan tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Innrita som reinan tekst' } ); diff --git a/plugins/pastetext/lang/fr-ca.js b/plugins/pastetext/lang/fr-ca.js index 1eda68f8854..3a8d44bc892 100644 --- a/plugins/pastetext/lang/fr-ca.js +++ b/plugins/pastetext/lang/fr-ca.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'fr-ca', { button: 'Coller comme texte', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Coller comme texte' } ); diff --git a/plugins/pastetext/lang/fr.js b/plugins/pastetext/lang/fr.js index fff8be7bcc8..ef95676bd0c 100644 --- a/plugins/pastetext/lang/fr.js +++ b/plugins/pastetext/lang/fr.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'fr', { button: 'Coller comme texte brut', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Coller comme texte brut' } ); diff --git a/plugins/pastetext/lang/gl.js b/plugins/pastetext/lang/gl.js index 403deb912a0..9ffe347398e 100644 --- a/plugins/pastetext/lang/gl.js +++ b/plugins/pastetext/lang/gl.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'gl', { button: 'Pegar como texto simple', - pasteNotification: 'O seu navegador non permite pegar texto simple deste xeito. Prema %1 para pegar.' + pasteNotification: 'O seu navegador non permite pegar texto simple deste xeito. Prema %1 para pegar.', + title: 'Pegar como texto simple' } ); diff --git a/plugins/pastetext/lang/gu.js b/plugins/pastetext/lang/gu.js index a6e1f1b49e3..32b3e72aa4f 100644 --- a/plugins/pastetext/lang/gu.js +++ b/plugins/pastetext/lang/gu.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'gu', { button: 'પેસ્ટ (ટેક્સ્ટ)', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'પેસ્ટ (ટેક્સ્ટ)' } ); diff --git a/plugins/pastetext/lang/he.js b/plugins/pastetext/lang/he.js index 75c32addd5d..23e698c3c72 100644 --- a/plugins/pastetext/lang/he.js +++ b/plugins/pastetext/lang/he.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'he', { button: 'הדבקה כטקסט פשוט', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'הדבקה כטקסט פשוט' } ); diff --git a/plugins/pastetext/lang/hi.js b/plugins/pastetext/lang/hi.js index cb4a301e00e..55a7124fa8c 100644 --- a/plugins/pastetext/lang/hi.js +++ b/plugins/pastetext/lang/hi.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'hi', { button: 'पेस्ट (सादा टॅक्स्ट)', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'पेस्ट (सादा टॅक्स्ट)' } ); diff --git a/plugins/pastetext/lang/hr.js b/plugins/pastetext/lang/hr.js index c52cfeab2d2..72630a93403 100644 --- a/plugins/pastetext/lang/hr.js +++ b/plugins/pastetext/lang/hr.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'hr', { button: 'Zalijepi kao čisti tekst', - pasteNotification: 'Vaš preglednik Vam ne dozvoljava lijepljenje običnog teksta na ovaj način. Za lijepljenje, pritisnite %1.' + pasteNotification: 'Vaš preglednik Vam ne dozvoljava lijepljenje običnog teksta na ovaj način. Za lijepljenje, pritisnite %1.', + title: 'Zalijepi kao čisti tekst' } ); diff --git a/plugins/pastetext/lang/hu.js b/plugins/pastetext/lang/hu.js index 91e305159cf..65a9c808123 100644 --- a/plugins/pastetext/lang/hu.js +++ b/plugins/pastetext/lang/hu.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'hu', { button: 'Beillesztés formázatlan szövegként', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Beillesztés formázatlan szövegként' } ); diff --git a/plugins/pastetext/lang/id.js b/plugins/pastetext/lang/id.js index 61176d3062c..0f49162f69a 100644 --- a/plugins/pastetext/lang/id.js +++ b/plugins/pastetext/lang/id.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'id', { button: 'Tempel sebagai teks polos', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Tempel sebagai Teks Polos' } ); diff --git a/plugins/pastetext/lang/is.js b/plugins/pastetext/lang/is.js index a8c7267d67c..b4360287026 100644 --- a/plugins/pastetext/lang/is.js +++ b/plugins/pastetext/lang/is.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'is', { button: 'Líma sem ósniðinn texta', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Líma sem ósniðinn texta' } ); diff --git a/plugins/pastetext/lang/it.js b/plugins/pastetext/lang/it.js index cbe1a4b7ce0..dd65bc27d49 100644 --- a/plugins/pastetext/lang/it.js +++ b/plugins/pastetext/lang/it.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'it', { button: 'Incolla come testo semplice', - pasteNotification: 'Il browser non permette di incollare il testo semplice in questo modo. Premere %1 per incollare.' + pasteNotification: 'Il browser non permette di incollare il testo semplice in questo modo. Premere %1 per incollare.', + title: 'Incolla come testo semplice' } ); diff --git a/plugins/pastetext/lang/ja.js b/plugins/pastetext/lang/ja.js index 6b824ed13ab..9ac178298de 100644 --- a/plugins/pastetext/lang/ja.js +++ b/plugins/pastetext/lang/ja.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ja', { button: 'プレーンテキストとして貼り付け', - pasteNotification: 'ブラウザの設定によりこの方法でプレーンテキストを貼り付けることはできません。手動で実行するにはキーボードの「%1」を押してくださ\r\nい。' + pasteNotification: 'ブラウザの設定によりこの方法でプレーンテキストを貼り付けることはできません。手動で実行するにはキーボードの「%1」を押してくださ\r\nい。', + title: 'プレーンテキストとして貼り付け' } ); diff --git a/plugins/pastetext/lang/ka.js b/plugins/pastetext/lang/ka.js index fe1d7189861..da92d23c7db 100644 --- a/plugins/pastetext/lang/ka.js +++ b/plugins/pastetext/lang/ka.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ka', { button: 'მხოლოდ ტექსტის ჩასმა', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'მხოლოდ ტექსტის ჩასმა' } ); diff --git a/plugins/pastetext/lang/km.js b/plugins/pastetext/lang/km.js index b92d9ad0b98..b95a1f9f582 100644 --- a/plugins/pastetext/lang/km.js +++ b/plugins/pastetext/lang/km.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'km', { button: 'បិទ​ភ្ជាប់​ជា​អត្ថបទ​ធម្មតា', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'បិទ​ភ្ជាប់​ជា​អត្ថបទ​ធម្មតា' } ); diff --git a/plugins/pastetext/lang/ko.js b/plugins/pastetext/lang/ko.js index a977d3f6d24..45c6ac8d634 100644 --- a/plugins/pastetext/lang/ko.js +++ b/plugins/pastetext/lang/ko.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ko', { button: '텍스트로 붙여넣기', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: '텍스트로 붙여넣기' } ); diff --git a/plugins/pastetext/lang/ku.js b/plugins/pastetext/lang/ku.js index 1ecd36276be..df61333c1e4 100644 --- a/plugins/pastetext/lang/ku.js +++ b/plugins/pastetext/lang/ku.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ku', { button: 'لکاندنی وەك دەقی ڕوون', - pasteNotification: 'وێبگەڕەکەت ڕێگەت پێنادات بۆ لکاندنی تێکست بە ڕێگایە. کلیکی %1 بۆ لکاندن.' + pasteNotification: 'وێبگەڕەکەت ڕێگەت پێنادات بۆ لکاندنی تێکست بە ڕێگایە. کلیکی %1 بۆ لکاندن.', + title: 'لکاندنی وەك دەقی ڕوون' } ); diff --git a/plugins/pastetext/lang/lt.js b/plugins/pastetext/lang/lt.js index 20e40472abb..d335af60e18 100644 --- a/plugins/pastetext/lang/lt.js +++ b/plugins/pastetext/lang/lt.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'lt', { button: 'Įdėti kaip gryną tekstą', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Įdėti kaip gryną tekstą' } ); diff --git a/plugins/pastetext/lang/lv.js b/plugins/pastetext/lang/lv.js index 1b8d28183de..ab53b49fe59 100644 --- a/plugins/pastetext/lang/lv.js +++ b/plugins/pastetext/lang/lv.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'lv', { button: 'Ievietot kā vienkāršu tekstu', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Ievietot kā vienkāršu tekstu' } ); diff --git a/plugins/pastetext/lang/mk.js b/plugins/pastetext/lang/mk.js index f732411786e..bcc82c2ccc7 100644 --- a/plugins/pastetext/lang/mk.js +++ b/plugins/pastetext/lang/mk.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'mk', { button: 'Paste as plain text', // MISSING - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Paste as Plain Text' // MISSING } ); diff --git a/plugins/pastetext/lang/mn.js b/plugins/pastetext/lang/mn.js index 2101bf42293..5b46b354888 100644 --- a/plugins/pastetext/lang/mn.js +++ b/plugins/pastetext/lang/mn.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'mn', { button: 'Энгийн бичвэрээр буулгах', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Энгийн бичвэрээр буулгах' } ); diff --git a/plugins/pastetext/lang/ms.js b/plugins/pastetext/lang/ms.js index e54fa47065f..7b65c9a7919 100644 --- a/plugins/pastetext/lang/ms.js +++ b/plugins/pastetext/lang/ms.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ms', { button: 'Tampal sebagai text biasa', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Tampal sebagai text biasa' } ); diff --git a/plugins/pastetext/lang/nb.js b/plugins/pastetext/lang/nb.js index b2b2e307829..ee79db07a91 100644 --- a/plugins/pastetext/lang/nb.js +++ b/plugins/pastetext/lang/nb.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'nb', { button: 'Lim inn som ren tekst', - pasteNotification: 'Nettleseren din lar deg ikke lime inn ren tekst på denne måten. Trykk %1 for å lime inn.' + pasteNotification: 'Nettleseren din lar deg ikke lime inn ren tekst på denne måten. Trykk %1 for å lime inn.', + title: 'Lim inn som ren tekst' } ); diff --git a/plugins/pastetext/lang/nl.js b/plugins/pastetext/lang/nl.js index 19d928722be..e1603c28520 100644 --- a/plugins/pastetext/lang/nl.js +++ b/plugins/pastetext/lang/nl.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'nl', { button: 'Plakken als platte tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Plakken als platte tekst' } ); diff --git a/plugins/pastetext/lang/no.js b/plugins/pastetext/lang/no.js index 9fa5bea69a3..05c2829b04a 100644 --- a/plugins/pastetext/lang/no.js +++ b/plugins/pastetext/lang/no.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'no', { button: 'Lim inn som ren tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Lim inn som ren tekst' } ); diff --git a/plugins/pastetext/lang/oc.js b/plugins/pastetext/lang/oc.js index 9bb589d7dd2..4c66b7a6029 100644 --- a/plugins/pastetext/lang/oc.js +++ b/plugins/pastetext/lang/oc.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'oc', { button: 'Pegar coma tèxte brut', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Paste as Plain Text' // MISSING } ); diff --git a/plugins/pastetext/lang/pl.js b/plugins/pastetext/lang/pl.js index 176520fc943..44546f0df05 100644 --- a/plugins/pastetext/lang/pl.js +++ b/plugins/pastetext/lang/pl.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'pl', { button: 'Wklej jako czysty tekst', - pasteNotification: 'Twoja przeglądarka nie pozwala na wklejanie treści w ten sposób. Naciśnij %1 by wkleić tekst.' + pasteNotification: 'Twoja przeglądarka nie pozwala na wklejanie treści w ten sposób. Naciśnij %1 by wkleić tekst.', + title: 'Wklej jako czysty tekst' } ); diff --git a/plugins/pastetext/lang/pt-br.js b/plugins/pastetext/lang/pt-br.js index 1c6fd617bd4..f239aca8a21 100644 --- a/plugins/pastetext/lang/pt-br.js +++ b/plugins/pastetext/lang/pt-br.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'pt-br', { button: 'Colar como Texto sem Formatação', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Colar como Texto sem Formatação' } ); diff --git a/plugins/pastetext/lang/pt.js b/plugins/pastetext/lang/pt.js index ad7695ef55b..d2d1ecf47f4 100644 --- a/plugins/pastetext/lang/pt.js +++ b/plugins/pastetext/lang/pt.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'pt', { button: 'Colar como texto simples', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Colar como texto simples' } ); diff --git a/plugins/pastetext/lang/ro.js b/plugins/pastetext/lang/ro.js index 80ae2bf2c6f..aaa964d9e3e 100644 --- a/plugins/pastetext/lang/ro.js +++ b/plugins/pastetext/lang/ro.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ro', { button: 'Adaugă ca text simplu (Plain Text)', - pasteNotification: 'Se lipește conținut din clipboard. Confirmați?' + pasteNotification: 'Se lipește conținut din clipboard. Confirmați?', + title: 'Adaugă ca text simplu (Plain Text)' } ); diff --git a/plugins/pastetext/lang/ru.js b/plugins/pastetext/lang/ru.js index 7cd531b2741..ed1ef26717d 100644 --- a/plugins/pastetext/lang/ru.js +++ b/plugins/pastetext/lang/ru.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ru', { button: 'Вставить только текст', - pasteNotification: 'Ваш браузер не поддерживает данный метод вставки. Для вставки нажмите %1' + pasteNotification: 'Ваш браузер не поддерживает данный метод вставки. Для вставки нажмите %1', + title: 'Вставить только текст' } ); diff --git a/plugins/pastetext/lang/si.js b/plugins/pastetext/lang/si.js index a1ab34d948a..80d004fe1f6 100644 --- a/plugins/pastetext/lang/si.js +++ b/plugins/pastetext/lang/si.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'si', { button: 'සාමාන්‍ය අක්ෂර ලෙස අලවන්න', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'සාමාන්‍ය අක්ෂර ලෙස අලවන්න' } ); diff --git a/plugins/pastetext/lang/sk.js b/plugins/pastetext/lang/sk.js index d14440cfba2..79bd02c43e8 100644 --- a/plugins/pastetext/lang/sk.js +++ b/plugins/pastetext/lang/sk.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sk', { button: 'Vložiť ako čistý text', - pasteNotification: 'Váš prehliadač neumožňuje vložiť text týmto spôsobom. Na vloženie textu stlačte %1.' + pasteNotification: 'Váš prehliadač neumožňuje vložiť text týmto spôsobom. Na vloženie textu stlačte %1.', + title: 'Vložiť ako čistý text' } ); diff --git a/plugins/pastetext/lang/sl.js b/plugins/pastetext/lang/sl.js index 74d02c3d09a..ee0197478f4 100644 --- a/plugins/pastetext/lang/sl.js +++ b/plugins/pastetext/lang/sl.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sl', { button: 'Prilepi kot golo besedilo', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Prilepi kot golo besedilo' } ); diff --git a/plugins/pastetext/lang/sq.js b/plugins/pastetext/lang/sq.js index ae8e1308239..18e248400e0 100644 --- a/plugins/pastetext/lang/sq.js +++ b/plugins/pastetext/lang/sq.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sq', { button: 'Hidhe si tekst të thjeshtë', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Hidhe si Tekst të Thjeshtë' } ); diff --git a/plugins/pastetext/lang/sr-latn.js b/plugins/pastetext/lang/sr-latn.js index a1e1ccd8b9c..001b385394d 100644 --- a/plugins/pastetext/lang/sr-latn.js +++ b/plugins/pastetext/lang/sr-latn.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sr-latn', { button: 'Zalepi kao čist tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Zalepi kao čist tekst' } ); diff --git a/plugins/pastetext/lang/sr.js b/plugins/pastetext/lang/sr.js index 6c409101fbc..6534ebe0f5e 100644 --- a/plugins/pastetext/lang/sr.js +++ b/plugins/pastetext/lang/sr.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sr', { button: 'Залепи као чист текст', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Залепи као чист текст' } ); diff --git a/plugins/pastetext/lang/sv.js b/plugins/pastetext/lang/sv.js index 22a4b62e215..d2321ef6368 100644 --- a/plugins/pastetext/lang/sv.js +++ b/plugins/pastetext/lang/sv.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sv', { button: 'Klistra in som vanlig text', - pasteNotification: 'Din webbläsare tillåter dig inte att klistra in vanlig text på detta vis. Tryck på %1 för att klistra in.' + pasteNotification: 'Din webbläsare tillåter dig inte att klistra in vanlig text på detta vis. Tryck på %1 för att klistra in.', + title: 'Klistra in som vanlig text' } ); diff --git a/plugins/pastetext/lang/th.js b/plugins/pastetext/lang/th.js index 47e4adbc01d..47e55aba89f 100644 --- a/plugins/pastetext/lang/th.js +++ b/plugins/pastetext/lang/th.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'th', { button: 'วางแบบตัวอักษรธรรมดา', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'วางแบบตัวอักษรธรรมดา' } ); diff --git a/plugins/pastetext/lang/tr.js b/plugins/pastetext/lang/tr.js index b60364edd40..af26d37d5c7 100644 --- a/plugins/pastetext/lang/tr.js +++ b/plugins/pastetext/lang/tr.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'tr', { button: 'Düz Metin Olarak Yapıştır', - pasteNotification: 'Web tarayıcınız bu şekilde düz metni yapıştırmanıza izin vermiyor. Yapıştırmak için %1 basınız.' + pasteNotification: 'Web tarayıcınız bu şekilde düz metni yapıştırmanıza izin vermiyor. Yapıştırmak için %1 basınız.', + title: 'Düz Metin Olarak Yapıştır' } ); diff --git a/plugins/pastetext/lang/tt.js b/plugins/pastetext/lang/tt.js index 418ac721d8c..4d2502cb779 100644 --- a/plugins/pastetext/lang/tt.js +++ b/plugins/pastetext/lang/tt.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'tt', { button: 'Форматлаусыз текст өстәү', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Форматлаусыз текст өстәү' } ); diff --git a/plugins/pastetext/lang/ug.js b/plugins/pastetext/lang/ug.js index 30c75f7b818..6a6a10860c1 100644 --- a/plugins/pastetext/lang/ug.js +++ b/plugins/pastetext/lang/ug.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ug', { button: 'پىچىمى يوق تېكىست سۈپىتىدە چاپلا', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'پىچىمى يوق تېكىست سۈپىتىدە چاپلا' } ); diff --git a/plugins/pastetext/lang/uk.js b/plugins/pastetext/lang/uk.js index d00c1a09174..3d958eccab9 100644 --- a/plugins/pastetext/lang/uk.js +++ b/plugins/pastetext/lang/uk.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'uk', { button: 'Вставити тільки текст', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Вставити тільки текст' } ); diff --git a/plugins/pastetext/lang/vi.js b/plugins/pastetext/lang/vi.js index eeac7da20b2..138914d0c98 100644 --- a/plugins/pastetext/lang/vi.js +++ b/plugins/pastetext/lang/vi.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'vi', { button: 'Dán theo định dạng văn bản thuần', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: 'Dán theo định dạng văn bản thuần' } ); diff --git a/plugins/pastetext/lang/zh-cn.js b/plugins/pastetext/lang/zh-cn.js index 271fc6f9fdf..0a8d5efd6c6 100644 --- a/plugins/pastetext/lang/zh-cn.js +++ b/plugins/pastetext/lang/zh-cn.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'zh-cn', { button: '粘贴为无格式文本', - pasteNotification: '您的浏览器不允许用此方式粘贴成纯文本,要粘贴请按 %1。' + pasteNotification: '您的浏览器不允许用此方式粘贴成纯文本,要粘贴请按 %1。', + title: '粘贴为无格式文本' } ); diff --git a/plugins/pastetext/lang/zh.js b/plugins/pastetext/lang/zh.js index 749e6de1664..f07cc0fc978 100644 --- a/plugins/pastetext/lang/zh.js +++ b/plugins/pastetext/lang/zh.js @@ -4,5 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'zh', { button: '貼成純文字', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + title: '貼成純文字' } ); From 5cd3fe77a1a6dda5eda2471127a458032eb00561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Wed, 13 Dec 2017 17:05:09 +0100 Subject: [PATCH 569/642] Restore paste dialog lang entries - clipboard plugin. --- plugins/clipboard/lang/af.js | 5 ++++- plugins/clipboard/lang/ar.js | 5 ++++- plugins/clipboard/lang/az.js | 5 ++++- plugins/clipboard/lang/bg.js | 5 ++++- plugins/clipboard/lang/bn.js | 5 ++++- plugins/clipboard/lang/bs.js | 5 ++++- plugins/clipboard/lang/ca.js | 5 ++++- plugins/clipboard/lang/cs.js | 5 ++++- plugins/clipboard/lang/cy.js | 5 ++++- plugins/clipboard/lang/da.js | 5 ++++- plugins/clipboard/lang/de-ch.js | 5 ++++- plugins/clipboard/lang/de.js | 5 ++++- plugins/clipboard/lang/el.js | 5 ++++- plugins/clipboard/lang/en-au.js | 5 ++++- plugins/clipboard/lang/en-ca.js | 5 ++++- plugins/clipboard/lang/en-gb.js | 5 ++++- plugins/clipboard/lang/eo.js | 5 ++++- plugins/clipboard/lang/es-mx.js | 5 ++++- plugins/clipboard/lang/es.js | 5 ++++- plugins/clipboard/lang/et.js | 5 ++++- plugins/clipboard/lang/eu.js | 5 ++++- plugins/clipboard/lang/fa.js | 5 ++++- plugins/clipboard/lang/fi.js | 5 ++++- plugins/clipboard/lang/fo.js | 5 ++++- plugins/clipboard/lang/fr-ca.js | 5 ++++- plugins/clipboard/lang/fr.js | 5 ++++- plugins/clipboard/lang/gl.js | 5 ++++- plugins/clipboard/lang/gu.js | 5 ++++- plugins/clipboard/lang/he.js | 5 ++++- plugins/clipboard/lang/hi.js | 5 ++++- plugins/clipboard/lang/hr.js | 5 ++++- plugins/clipboard/lang/hu.js | 5 ++++- plugins/clipboard/lang/id.js | 5 ++++- plugins/clipboard/lang/is.js | 5 ++++- plugins/clipboard/lang/it.js | 5 ++++- plugins/clipboard/lang/ja.js | 5 ++++- plugins/clipboard/lang/ka.js | 5 ++++- plugins/clipboard/lang/km.js | 5 ++++- plugins/clipboard/lang/ko.js | 5 ++++- plugins/clipboard/lang/ku.js | 5 ++++- plugins/clipboard/lang/lt.js | 5 ++++- plugins/clipboard/lang/lv.js | 5 ++++- plugins/clipboard/lang/mk.js | 5 ++++- plugins/clipboard/lang/mn.js | 5 ++++- plugins/clipboard/lang/ms.js | 5 ++++- plugins/clipboard/lang/nb.js | 5 ++++- plugins/clipboard/lang/nl.js | 5 ++++- plugins/clipboard/lang/no.js | 5 ++++- plugins/clipboard/lang/oc.js | 5 ++++- plugins/clipboard/lang/pl.js | 5 ++++- plugins/clipboard/lang/pt-br.js | 5 ++++- plugins/clipboard/lang/pt.js | 5 ++++- plugins/clipboard/lang/ro.js | 5 ++++- plugins/clipboard/lang/ru.js | 5 ++++- plugins/clipboard/lang/si.js | 5 ++++- plugins/clipboard/lang/sk.js | 5 ++++- plugins/clipboard/lang/sl.js | 5 ++++- plugins/clipboard/lang/sq.js | 5 ++++- plugins/clipboard/lang/sr-latn.js | 5 ++++- plugins/clipboard/lang/sr.js | 5 ++++- plugins/clipboard/lang/sv.js | 5 ++++- plugins/clipboard/lang/th.js | 5 ++++- plugins/clipboard/lang/tr.js | 5 ++++- plugins/clipboard/lang/tt.js | 5 ++++- plugins/clipboard/lang/ug.js | 5 ++++- plugins/clipboard/lang/uk.js | 5 ++++- plugins/clipboard/lang/vi.js | 5 ++++- plugins/clipboard/lang/zh-cn.js | 5 ++++- plugins/clipboard/lang/zh.js | 5 ++++- 69 files changed, 276 insertions(+), 69 deletions(-) diff --git a/plugins/clipboard/lang/af.js b/plugins/clipboard/lang/af.js index 20213ae5976..dd222d8d82c 100644 --- a/plugins/clipboard/lang/af.js +++ b/plugins/clipboard/lang/af.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'af', { cut: 'Knip', cutError: 'U blaaier se sekuriteitsinstelling belet die outomatiese knip-aksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+X).', paste: 'Plak', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Plak-area', + pasteMsg: 'Plak die teks in die volgende teks-area met die sleutelbordkombinasie (Ctrl/Cmd+V) en druk OK.', + title: 'Byvoeg' } ); diff --git a/plugins/clipboard/lang/ar.js b/plugins/clipboard/lang/ar.js index 9a8bcb81848..8fc696a15fa 100644 --- a/plugins/clipboard/lang/ar.js +++ b/plugins/clipboard/lang/ar.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ar', { cut: 'قص', cutError: 'الإعدادات الأمنية للمتصفح الذي تستخدمه تمنع القص التلقائي. فضلاً إستخدم لوحة المفاتيح لفعل ذلك (Ctrl/Cmd+X).', paste: 'لصق', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'منطقة اللصق', + pasteMsg: 'الصق داخل الصندوق بإستخدام زرائر (Ctrl/Cmd+V) في لوحة المفاتيح، ثم اضغط زر موافق.', + title: 'لصق' } ); diff --git a/plugins/clipboard/lang/az.js b/plugins/clipboard/lang/az.js index a4011738566..7cfcc8ac703 100644 --- a/plugins/clipboard/lang/az.js +++ b/plugins/clipboard/lang/az.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'az', { cut: 'Kəs', cutError: 'Avtomatik kəsmə mümkün deyil. Ctrl+X basın.', paste: 'Əlavə et', - pasteNotification: 'Sizin İnternet bələdçisi bu cür mətnin köçürməsi dəstəklənmir. Əlavə etmək üçün %1 basın.' + pasteNotification: 'Sizin İnternet bələdçisi bu cür mətnin köçürməsi dəstəklənmir. Əlavə etmək üçün %1 basın.', + pasteArea: 'Paste Area', // MISSING + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING + title: 'Paste' // MISSING } ); diff --git a/plugins/clipboard/lang/bg.js b/plugins/clipboard/lang/bg.js index 49827a2d981..d6bc07a8f07 100644 --- a/plugins/clipboard/lang/bg.js +++ b/plugins/clipboard/lang/bg.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'bg', { cut: 'Отрежи', cutError: 'Настройките за сигурност на Вашия браузър не позволяват на редактора автоматично да изъплни действията за отрязване. Моля ползвайте клавиатурните команди за целта (ctrl+x).', paste: 'Вмъкни', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Зона за вмъкване', + pasteMsg: 'Вмъкнете тук съдъжанието с клавиатуарата (Ctrl/Cmd+V) и натиснете OK.', + title: 'Вмъкни' } ); diff --git a/plugins/clipboard/lang/bn.js b/plugins/clipboard/lang/bn.js index 0c955124510..19ee8754e71 100644 --- a/plugins/clipboard/lang/bn.js +++ b/plugins/clipboard/lang/bn.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'bn', { cut: 'কাট', cutError: 'আপনার ব্রাউজারের সুরক্ষা সেটিংস এডিটরকে অটোমেটিক কাট করার অনুমতি দেয়নি। দয়া করে এই কাজের জন্য কিবোর্ড ব্যবহার করুন (Ctrl/Cmd+X)।', paste: 'পেস্ট', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Paste Area', // MISSING + pasteMsg: 'অনুগ্রহ করে নীচের বাক্সে কিবোর্ড ব্যবহার করে (Ctrl/Cmd+V) পেস্ট করুন এবং OK চাপ দিন', + title: 'পেস্ট' } ); diff --git a/plugins/clipboard/lang/bs.js b/plugins/clipboard/lang/bs.js index 1a7058e8ce8..a1aae54324e 100644 --- a/plugins/clipboard/lang/bs.js +++ b/plugins/clipboard/lang/bs.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'bs', { cut: 'Izreži', cutError: 'Sigurnosne postavke vašeg pretraživaèa ne dozvoljavaju operacije automatskog rezanja. Molimo koristite kraticu na tastaturi (Ctrl/Cmd+X).', paste: 'Zalijepi', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Paste Area', // MISSING + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING + title: 'Zalijepi' } ); diff --git a/plugins/clipboard/lang/ca.js b/plugins/clipboard/lang/ca.js index 06ee14603d2..cfcd204ea8a 100644 --- a/plugins/clipboard/lang/ca.js +++ b/plugins/clipboard/lang/ca.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ca', { cut: 'Retallar', cutError: 'La configuració de seguretat del vostre navegador no permet executar automàticament les operacions de retallar. Si us plau, utilitzeu el teclat (Ctrl/Cmd+X).', paste: 'Enganxar', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Àrea d\'enganxat', + pasteMsg: 'Si us plau, enganxi dins del següent camp utilitzant el teclat (Ctrl/Cmd+V) i premi OK.', + title: 'Enganxar' } ); diff --git a/plugins/clipboard/lang/cs.js b/plugins/clipboard/lang/cs.js index 7bbff88faa2..0d44f860cea 100644 --- a/plugins/clipboard/lang/cs.js +++ b/plugins/clipboard/lang/cs.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'cs', { cut: 'Vyjmout', cutError: 'Bezpečnostní nastavení vašeho prohlížeče nedovolují editoru spustit funkci pro vyjmutí zvoleného textu do schránky. Prosím vyjměte zvolený text do schránky pomocí klávesnice (Ctrl/Cmd+X).', paste: 'Vložit', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Oblast vkládání', + pasteMsg: 'Do následujícího pole vložte požadovaný obsah pomocí klávesnice (Ctrl/Cmd+V) a stiskněte OK.', + title: 'Vložit' } ); diff --git a/plugins/clipboard/lang/cy.js b/plugins/clipboard/lang/cy.js index e09f4324ed7..95866034b8f 100644 --- a/plugins/clipboard/lang/cy.js +++ b/plugins/clipboard/lang/cy.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'cy', { cut: 'Torri', cutError: 'Nid yw gosodiadau diogelwch eich porwr yn caniatàu\'r golygydd i gynnal \'gweithredoedd torri\' yn awtomatig. Defnyddiwch y bysellfwrdd (Ctrl/Cmd+X).', paste: 'Gludo', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Ardal Gludo', + pasteMsg: 'Gludwch i mewn i\'r blwch canlynol gan ddefnyddio\'r bysellfwrdd (Ctrl/Cmd+V) a phwyso Iawn.', + title: 'Gludo' } ); diff --git a/plugins/clipboard/lang/da.js b/plugins/clipboard/lang/da.js index e2a78031006..9077c52e294 100644 --- a/plugins/clipboard/lang/da.js +++ b/plugins/clipboard/lang/da.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'da', { cut: 'Klip', cutError: 'Din browsers sikkerhedsindstillinger tillader ikke editoren at få automatisk adgang til udklipsholderen.

Brug i stedet tastaturet til at klippe teksten (Ctrl/Cmd+X).', paste: 'Indsæt', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Indsæt område', + pasteMsg: 'Indsæt i feltet herunder (Ctrl/Cmd+V) og klik på OK.', + title: 'Indsæt' } ); diff --git a/plugins/clipboard/lang/de-ch.js b/plugins/clipboard/lang/de-ch.js index 96680ee3069..e5505e43b86 100644 --- a/plugins/clipboard/lang/de-ch.js +++ b/plugins/clipboard/lang/de-ch.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'de-ch', { cut: 'Ausschneiden', cutError: 'Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).', paste: 'Einfügen', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Einfügebereich', + pasteMsg: 'Bitte fügen Sie den Text in der folgenden Box über die Tastatur (mit Strg+V) ein und bestätigen Sie mit OK.', + title: 'Einfügen' } ); diff --git a/plugins/clipboard/lang/de.js b/plugins/clipboard/lang/de.js index 2469a3fc5ab..fbd924f71e7 100644 --- a/plugins/clipboard/lang/de.js +++ b/plugins/clipboard/lang/de.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'de', { cut: 'Ausschneiden', cutError: 'Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).', paste: 'Einfügen', - pasteNotification: 'Ihr Browser verhindert das Einfügen über diesen Weg. Zum einfügen drücken Sie %1.' + pasteNotification: 'Ihr Browser verhindert das Einfügen über diesen Weg. Zum einfügen drücken Sie %1.', + pasteArea: 'Einfügebereich', + pasteMsg: 'Bitte fügen Sie den Text in der folgenden Box über die Tastatur (mit Strg+V) ein und bestätigen Sie mit OK.', + title: 'Einfügen' } ); diff --git a/plugins/clipboard/lang/el.js b/plugins/clipboard/lang/el.js index 6e23ee31732..9f61627a1d6 100644 --- a/plugins/clipboard/lang/el.js +++ b/plugins/clipboard/lang/el.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'el', { cut: 'Αποκοπή', cutError: 'Οι ρυθμίσεις ασφαλείας του περιηγητή σας δεν επιτρέπουν την επιλεγμένη εργασία αποκοπής. Παρακαλώ χρησιμοποιείστε το πληκτρολόγιο (Ctrl/Cmd+X).', paste: 'Επικόλληση', - pasteNotification: 'Ο περιηγητής σας δεν σας επιτρέπει να επικολλήσετε με αυτόν τον τρόπο. Πατήστε %1 για επικόλληση.' + pasteNotification: 'Ο περιηγητής σας δεν σας επιτρέπει να επικολλήσετε με αυτόν τον τρόπο. Πατήστε %1 για επικόλληση.', + pasteArea: 'Περιοχή Επικόλλησης', + pasteMsg: 'Παρακαλώ επικολλήστε στο ακόλουθο κουτί χρησιμοποιώντας το πληκτρολόγιο (Ctrl/Cmd+V) και πατήστε OK.', + title: 'Επικόλληση' } ); diff --git a/plugins/clipboard/lang/en-au.js b/plugins/clipboard/lang/en-au.js index 1f1f61fe9ce..b05700d98b5 100644 --- a/plugins/clipboard/lang/en-au.js +++ b/plugins/clipboard/lang/en-au.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en-au', { cut: 'Cut', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', paste: 'Paste', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', + pasteArea: 'Paste Area', // MISSING + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', + title: 'Paste' } ); diff --git a/plugins/clipboard/lang/en-ca.js b/plugins/clipboard/lang/en-ca.js index 6fa60645478..3df1af6d434 100644 --- a/plugins/clipboard/lang/en-ca.js +++ b/plugins/clipboard/lang/en-ca.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en-ca', { cut: 'Cut', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', paste: 'Paste', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Paste Area', // MISSING + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', + title: 'Paste' } ); diff --git a/plugins/clipboard/lang/en-gb.js b/plugins/clipboard/lang/en-gb.js index a52ad203e8f..e1595ace7c2 100644 --- a/plugins/clipboard/lang/en-gb.js +++ b/plugins/clipboard/lang/en-gb.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en-gb', { cut: 'Cut', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', paste: 'Paste', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Paste Area', + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', + title: 'Paste' } ); diff --git a/plugins/clipboard/lang/eo.js b/plugins/clipboard/lang/eo.js index 0d5223a16e3..18044886a57 100644 --- a/plugins/clipboard/lang/eo.js +++ b/plugins/clipboard/lang/eo.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'eo', { cut: 'Eltondi', cutError: 'La sekurecagordo de via TTT-legilo ne permesas, ke la redaktilo faras eltondajn operaciojn. Bonvolu uzi la klavaron por tio (Ctrl/Cmd-X).', paste: 'Interglui', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Intergluoareo', + pasteMsg: 'Bonvolu glui la tekston en la jenan areon per uzado de la klavaro (Ctrl/Cmd+V) kaj premu OK', + title: 'Interglui' } ); diff --git a/plugins/clipboard/lang/es-mx.js b/plugins/clipboard/lang/es-mx.js index 745575cb727..affb7f77940 100644 --- a/plugins/clipboard/lang/es-mx.js +++ b/plugins/clipboard/lang/es-mx.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'es-mx', { cut: 'Cortar', cutError: 'La configuración de seguridad de su navegador no permite al editor ejecutar automáticamente operaciones de corte. Por favor, utilice el teclado para (Ctrl/Cmd+X).', paste: 'Pegar', - pasteNotification: 'Tu navegador no permite pegar de esta manera. Presiona %1 para pegar.' + pasteNotification: 'Tu navegador no permite pegar de esta manera. Presiona %1 para pegar.', + pasteArea: 'Paste Area', // MISSING + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING + title: 'Paste' // MISSING } ); diff --git a/plugins/clipboard/lang/es.js b/plugins/clipboard/lang/es.js index 8de4371689c..1539eb481a5 100644 --- a/plugins/clipboard/lang/es.js +++ b/plugins/clipboard/lang/es.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'es', { cut: 'Cortar', cutError: 'La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de cortado.\r\nPor favor use el teclado (Ctrl/Cmd+X).', paste: 'Pegar', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Zona de pegado', + pasteMsg: 'Por favor pegue dentro del cuadro utilizando el teclado (Ctrl/Cmd+V);\r\nluego presione Aceptar.', + title: 'Pegar' } ); diff --git a/plugins/clipboard/lang/et.js b/plugins/clipboard/lang/et.js index d044ff56a71..933123417a1 100644 --- a/plugins/clipboard/lang/et.js +++ b/plugins/clipboard/lang/et.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'et', { cut: 'Lõika', cutError: 'Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt lõigata. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+X).', paste: 'Aseta', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Asetamise ala', + pasteMsg: 'Palun aseta tekst järgnevasse kasti kasutades klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+V) ja vajuta seejärel OK.', + title: 'Asetamine' } ); diff --git a/plugins/clipboard/lang/eu.js b/plugins/clipboard/lang/eu.js index 8a20548a503..cb6388a3b13 100644 --- a/plugins/clipboard/lang/eu.js +++ b/plugins/clipboard/lang/eu.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'eu', { cut: 'Ebaki', cutError: 'Zure web nabigatzailearen segurtasun ezarpenek ez dute baimentzen testuak automatikoki moztea. Mesedez teklatua erabil ezazu (Ctrl/Cmd+X).', paste: 'Itsatsi', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Itsasteko area', + pasteMsg: 'Mesedez teklatua erabiliz (Ctrl/Cmd+V) ondorengo eremuan testua itsatsi eta sakatu Ados.', + title: 'Itsatsi' } ); diff --git a/plugins/clipboard/lang/fa.js b/plugins/clipboard/lang/fa.js index 520aec0f655..8bc938e620f 100644 --- a/plugins/clipboard/lang/fa.js +++ b/plugins/clipboard/lang/fa.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fa', { cut: 'برش', cutError: 'تنظیمات امنیتی مرورگر شما اجازه نمیدهد که ویرایشگر به طور خودکار عملکردهای برش را انجام دهد. لطفا با دکمههای صفحه کلید این کار را انجام دهید (Ctrl/Cmd+X).', paste: 'چسباندن', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'محل چسباندن', + pasteMsg: 'لطفا متن را با کلیدهای (Ctrl/Cmd+V) در این جعبهٴ متنی بچسبانید و پذیرش را بزنید.', + title: 'چسباندن' } ); diff --git a/plugins/clipboard/lang/fi.js b/plugins/clipboard/lang/fi.js index c4287088e0e..01980e6111c 100644 --- a/plugins/clipboard/lang/fi.js +++ b/plugins/clipboard/lang/fi.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fi', { cut: 'Leikkaa', cutError: 'Selaimesi turva-asetukset eivät salli editorin toteuttaa leikkaamista. Käytä näppäimistöä leikkaamiseen (Ctrl+X).', paste: 'Liitä', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Leikealue', + pasteMsg: 'Liitä painamalla (Ctrl+V) ja painamalla OK.', + title: 'Liitä' } ); diff --git a/plugins/clipboard/lang/fo.js b/plugins/clipboard/lang/fo.js index 45c4fe25de7..a8df006b955 100644 --- a/plugins/clipboard/lang/fo.js +++ b/plugins/clipboard/lang/fo.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fo', { cut: 'Kvett', cutError: 'Trygdaruppseting alnótskagans forðar tekstviðgeranum í at kvetta tekstin. Vinarliga nýt knappaborðið til at kvetta tekstin (Ctrl/Cmd+X).', paste: 'Innrita', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Avritingarumráði', + pasteMsg: 'Vinarliga koyr tekstin í hendan rútin við knappaborðinum (Ctrl/Cmd+V) og klikk á Góðtak.', + title: 'Innrita' } ); diff --git a/plugins/clipboard/lang/fr-ca.js b/plugins/clipboard/lang/fr-ca.js index e5d9ad35091..1064c3abcf7 100644 --- a/plugins/clipboard/lang/fr-ca.js +++ b/plugins/clipboard/lang/fr-ca.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fr-ca', { cut: 'Couper', cutError: 'Les paramètres de sécurité de votre navigateur empêchent l\'éditeur de couper automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl/Cmd+X).', paste: 'Coller', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Coller la zone', + pasteMsg: 'Veuillez coller dans la zone ci-dessous en utilisant le clavier (Ctrl/Cmd+V) et appuyer sur OK.', + title: 'Coller' } ); diff --git a/plugins/clipboard/lang/fr.js b/plugins/clipboard/lang/fr.js index 8ef739a6a53..fef154c7f28 100644 --- a/plugins/clipboard/lang/fr.js +++ b/plugins/clipboard/lang/fr.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fr', { cut: 'Couper', cutError: 'Les paramètres de sécurité de votre navigateur n\'autorisent pas l\'éditeur à exécuter automatiquement l\'opération « Couper ». Veuillez utiliser le raccourci clavier à cet effet (Ctrl/Cmd+X).', paste: 'Coller', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Coller la zone', + pasteMsg: 'Veuillez coller le texte dans la zone suivante en utilisant le raccourci clavier (Ctrl/Cmd+V) et cliquez sur OK.', + title: 'Coller' } ); diff --git a/plugins/clipboard/lang/gl.js b/plugins/clipboard/lang/gl.js index 0bd52bd4827..e34434715b0 100644 --- a/plugins/clipboard/lang/gl.js +++ b/plugins/clipboard/lang/gl.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'gl', { cut: 'Cortar', cutError: 'Os axustes de seguranza do seu navegador non permiten que o editor realice automaticamente as tarefas de corte. Use o teclado para iso (Ctrl/Cmd+X).', paste: 'Pegar', - pasteNotification: 'O seu navegador non permite pegar deste xeito. Prema %1 para pegar.' + pasteNotification: 'O seu navegador non permite pegar deste xeito. Prema %1 para pegar.', + pasteArea: 'Zona de pegado', + pasteMsg: 'Pegue dentro do seguinte cadro usando o teclado (Ctrl/Cmd+V) e prema en Aceptar', + title: 'Pegar' } ); diff --git a/plugins/clipboard/lang/gu.js b/plugins/clipboard/lang/gu.js index 342073d280e..9920e44cbd8 100644 --- a/plugins/clipboard/lang/gu.js +++ b/plugins/clipboard/lang/gu.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'gu', { cut: 'કાપવું', cutError: 'તમારા બ્રાઉઝર ની સુરક્ષિત સેટિંગસ કટ કરવાની પરવાનગી નથી આપતી. (Ctrl/Cmd+X) નો ઉપયોગ કરો.', paste: 'પેસ્ટ', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'પેસ્ટ કરવાની જગ્યા', + pasteMsg: 'Ctrl/Cmd+V નો પ્રયોગ કરી પેસ્ટ કરો', + title: 'પેસ્ટ' } ); diff --git a/plugins/clipboard/lang/he.js b/plugins/clipboard/lang/he.js index 7a1f12750c4..f2f17fce689 100644 --- a/plugins/clipboard/lang/he.js +++ b/plugins/clipboard/lang/he.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'he', { cut: 'גזירה', cutError: 'הגדרות האבטחה בדפדפן שלך לא מאפשרות לעורך לבצע פעולות גזירה אוטומטיות. יש להשתמש במקלדת לשם כך (Ctrl/Cmd+X).', paste: 'הדבקה', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'איזור הדבקה', + pasteMsg: 'נא להדביק בתוך הקופסה באמצעות (Ctrl/Cmd+V) וללחוץ על אישור.', + title: 'הדבקה' } ); diff --git a/plugins/clipboard/lang/hi.js b/plugins/clipboard/lang/hi.js index e8b7ead91f4..a4f0e7602d7 100644 --- a/plugins/clipboard/lang/hi.js +++ b/plugins/clipboard/lang/hi.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'hi', { cut: 'कट', cutError: 'आपके ब्राउज़र की सुरक्षा सॅटिन्ग्स ने कट करने की अनुमति नहीं प्रदान की है। (Ctrl/Cmd+X) का प्रयोग करें।', paste: 'पेस्ट', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Paste Area', // MISSING + pasteMsg: 'Ctrl/Cmd+V का प्रयोग करके पेस्ट करें और ठीक है करें.', + title: 'पेस्ट' } ); diff --git a/plugins/clipboard/lang/hr.js b/plugins/clipboard/lang/hr.js index 5a392395bdb..b92710441f5 100644 --- a/plugins/clipboard/lang/hr.js +++ b/plugins/clipboard/lang/hr.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'hr', { cut: 'Izreži', cutError: 'Sigurnosne postavke Vašeg pretraživača ne dozvoljavaju operacije automatskog izrezivanja. Molimo koristite kraticu na tipkovnici (Ctrl/Cmd+X).', paste: 'Zalijepi', - pasteNotification: 'Vaš preglednik Vam ne dozvoljava lijepljenje na ovaj način. Za lijepljenje, pritisnite %1.' + pasteNotification: 'Vaš preglednik Vam ne dozvoljava lijepljenje na ovaj način. Za lijepljenje, pritisnite %1.', + pasteArea: 'Prostor za ljepljenje', + pasteMsg: 'Molimo zaljepite unutar doljnjeg okvira koristeći tipkovnicu (Ctrl/Cmd+V) i kliknite OK.', + title: 'Zalijepi' } ); diff --git a/plugins/clipboard/lang/hu.js b/plugins/clipboard/lang/hu.js index 51cc0cbb3cd..cba7861f7d5 100644 --- a/plugins/clipboard/lang/hu.js +++ b/plugins/clipboard/lang/hu.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'hu', { cut: 'Kivágás', cutError: 'A böngésző biztonsági beállításai nem engedélyezik a szerkesztőnek, hogy végrehajtsa a kivágás műveletet. Használja az alábbi billentyűkombinációt (Ctrl/Cmd+X).', paste: 'Beillesztés', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Beszúrás mező', + pasteMsg: 'Másolja be az alábbi mezőbe a Ctrl/Cmd+V billentyűk lenyomásával, majd nyomjon Rendben-t.', + title: 'Beillesztés' } ); diff --git a/plugins/clipboard/lang/id.js b/plugins/clipboard/lang/id.js index 6ebcdf5fd47..28a71c0eee0 100644 --- a/plugins/clipboard/lang/id.js +++ b/plugins/clipboard/lang/id.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'id', { cut: 'Potong', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', // MISSING paste: 'Tempel', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Area Tempel', + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING + title: 'Tempel' } ); diff --git a/plugins/clipboard/lang/is.js b/plugins/clipboard/lang/is.js index 5175a50dd4f..fe14280e4c5 100644 --- a/plugins/clipboard/lang/is.js +++ b/plugins/clipboard/lang/is.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'is', { cut: 'Klippa', cutError: 'Öryggisstillingar vafrans þíns leyfa ekki klippingu texta með músaraðgerð. Notaðu lyklaborðið í klippa (Ctrl/Cmd+X).', paste: 'Líma', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Paste Area', // MISSING + pasteMsg: 'Límdu í svæðið hér að neðan og (Ctrl/Cmd+V) og smelltu á OK.', + title: 'Líma' } ); diff --git a/plugins/clipboard/lang/it.js b/plugins/clipboard/lang/it.js index 36fd154b8a0..14264204557 100644 --- a/plugins/clipboard/lang/it.js +++ b/plugins/clipboard/lang/it.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'it', { cut: 'Taglia', cutError: 'Le impostazioni di sicurezza del browser non permettono di tagliare automaticamente il testo. Usa la tastiera (Ctrl/Cmd+X).', paste: 'Incolla', - pasteNotification: 'Il browser non permette di incollare in questo modo. Premere %1 per incollare.' + pasteNotification: 'Il browser non permette di incollare in questo modo. Premere %1 per incollare.', + pasteArea: 'Incolla', + pasteMsg: 'Incolla il testo all\'interno dell\'area sottostante usando la scorciatoia di tastiere (Ctrl/Cmd+V) e premi OK.', + title: 'Incolla' } ); diff --git a/plugins/clipboard/lang/ja.js b/plugins/clipboard/lang/ja.js index b7aae01a0cd..03ecbb76e6f 100644 --- a/plugins/clipboard/lang/ja.js +++ b/plugins/clipboard/lang/ja.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ja', { cut: '切り取り', cutError: 'ブラウザーのセキュリティ設定によりエディタの切り取り操作を自動で実行することができません。実行するには手動でキーボードの(Ctrl/Cmd+X)を使用してください。', paste: '貼り付け', - pasteNotification: 'ブラウザの設定によりこの方法で貼り付けることはできません。手動で実行するにはキーボードの「%1」を押してください。' + pasteNotification: 'ブラウザの設定によりこの方法で貼り付けることはできません。手動で実行するにはキーボードの「%1」を押してください。', + pasteArea: '貼り付け場所', + pasteMsg: 'キーボード(Ctrl/Cmd+V)を使用して、次の入力エリア内で貼り付けて、OKを押してください。', + title: '貼り付け' } ); diff --git a/plugins/clipboard/lang/ka.js b/plugins/clipboard/lang/ka.js index 3b71c51d020..a80267e0a0a 100644 --- a/plugins/clipboard/lang/ka.js +++ b/plugins/clipboard/lang/ka.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ka', { cut: 'ამოჭრა', cutError: 'თქვენი ბროუზერის უსაფრთხოების პარამეტრები არ იძლევა ამოჭრის ოპერაციის ავტომატურად განხორციელების საშუალებას. გამოიყენეთ კლავიატურა ამისთვის (Ctrl/Cmd+X).', paste: 'ჩასმა', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'ჩასმის არე', + pasteMsg: 'ჩასვით ამ არის შიგნით კლავიატურის გამოყენებით (Ctrl/Cmd+V) და დააჭირეთ OK-ს', + title: 'ჩასმა' } ); diff --git a/plugins/clipboard/lang/km.js b/plugins/clipboard/lang/km.js index ca8d6bd1320..5310072917c 100644 --- a/plugins/clipboard/lang/km.js +++ b/plugins/clipboard/lang/km.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'km', { cut: 'កាត់យក', cutError: 'ការកំណត់សុវត្ថភាពរបស់កម្មវិធីរុករករបស់លោកអ្នក នេះ​មិនអាចធ្វើកម្មវិធីតាក់តែងអត្ថបទ កាត់អត្ថបទយកដោយស្វ័យប្រវត្តបានឡើយ ។ សូមប្រើប្រាស់បន្សំ ឃីដូចនេះ (Ctrl/Cmd+X) ។', paste: 'បិទ​ភ្ជាប់', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'តំបន់​បិទ​ភ្ជាប់', + pasteMsg: 'សូមចំលងអត្ថបទទៅដាក់ក្នុងប្រអប់ដូចខាងក្រោមដោយប្រើប្រាស់ ឃី ​(Ctrl/Cmd+V) ហើយចុច OK ។', + title: 'បិទ​ភ្ជាប់' } ); diff --git a/plugins/clipboard/lang/ko.js b/plugins/clipboard/lang/ko.js index 2d68069d035..d4bac6b6d7f 100644 --- a/plugins/clipboard/lang/ko.js +++ b/plugins/clipboard/lang/ko.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ko', { cut: '잘라내기', cutError: '브라우저의 보안설정 때문에 잘라내기 기능을 실행할 수 없습니다. 키보드(Ctrl/Cmd+X)를 이용해서 잘라내기 하십시오', paste: '붙여넣기', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: '붙여넣기 범위', + pasteMsg: '키보드(Ctrl/Cmd+V)를 이용해서 상자안에 붙여넣고 확인 를 누르세요.', + title: '붙여넣기' } ); diff --git a/plugins/clipboard/lang/ku.js b/plugins/clipboard/lang/ku.js index eab78a0cb38..84cccffa574 100644 --- a/plugins/clipboard/lang/ku.js +++ b/plugins/clipboard/lang/ku.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ku', { cut: 'بڕین', cutError: 'پارێزی وێبگەڕەکەت ڕێگەنادات بە سەرنووسەکە لەبڕینی خۆکارانە. تکایە لەبری ئەمە ئەم فەرمانە بەکاربهێنە بەداگرتنی کلیلی (Ctrl/Cmd+X).', paste: 'لکاندن', - pasteNotification: 'وێبگەڕەکەت ڕێگەت پێنادات بۆ لکاندنی تێکست بە ڕێگایە. کلیکی %1 بۆ لکاندن.' + pasteNotification: 'وێبگەڕەکەت ڕێگەت پێنادات بۆ لکاندنی تێکست بە ڕێگایە. کلیکی %1 بۆ لکاندن.', + pasteArea: 'ناوچەی لکاندن', + pasteMsg: 'تکایە بیلکێنە لەناوەوەی ئەم سنوقە لەڕێی تەختەکلیلەکەت بە بەکارهێنانی کلیلی (Ctrl/Cmd+V) دووای کلیکی باشە بکە.', + title: 'لکاندن' } ); diff --git a/plugins/clipboard/lang/lt.js b/plugins/clipboard/lang/lt.js index de6787e27e0..017b8d7cf4e 100644 --- a/plugins/clipboard/lang/lt.js +++ b/plugins/clipboard/lang/lt.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'lt', { cut: 'Iškirpti', cutError: 'Jūsų naršyklės saugumo nustatymai neleidžia redaktoriui automatiškai įvykdyti iškirpimo operacijų. Tam prašome naudoti klaviatūrą (Ctrl/Cmd+X).', paste: 'Įdėti', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Įkelti dalį', + pasteMsg: 'Žemiau esančiame įvedimo lauke įdėkite tekstą, naudodami klaviatūrą (Ctrl/Cmd+V) ir paspauskite mygtuką OK.', + title: 'Įdėti' } ); diff --git a/plugins/clipboard/lang/lv.js b/plugins/clipboard/lang/lv.js index 5c3cddff92c..be3153b5bf7 100644 --- a/plugins/clipboard/lang/lv.js +++ b/plugins/clipboard/lang/lv.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'lv', { cut: 'Izgriezt', cutError: 'Jūsu pārlūkprogrammas drošības iestatījumi nepieļauj redaktoram automātiski veikt izgriezšanas darbību. Lūdzu, izmantojiet (Ctrl/Cmd+X), lai veiktu šo darbību.', paste: 'Ielīmēt', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Ielīmēšanas zona', + pasteMsg: 'Lūdzu, ievietojiet tekstu šajā laukumā, izmantojot klaviatūru (Ctrl/Cmd+V) un apstipriniet ar Darīts!.', + title: 'Ievietot' } ); diff --git a/plugins/clipboard/lang/mk.js b/plugins/clipboard/lang/mk.js index 3b652902a72..e9850f13b55 100644 --- a/plugins/clipboard/lang/mk.js +++ b/plugins/clipboard/lang/mk.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'mk', { cut: 'Исечи (Cut)', cutError: 'Опциите за безбедност на вашиот прелистувач не дозволуваат уредувачот автоматски да изврши сечење. Ве молиме употребете ја тастатурата. (Ctrl/Cmd+C)', paste: 'Залепи (Paste)', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Простор за залепување', + pasteMsg: 'Ве молиме да залепите во следниот квадрат користејќи ја тастатурата (Ctrl/Cmd+V) и да притиснете OK', + title: 'Залепи (Paste)' } ); diff --git a/plugins/clipboard/lang/mn.js b/plugins/clipboard/lang/mn.js index 148043af191..54e49e17f88 100644 --- a/plugins/clipboard/lang/mn.js +++ b/plugins/clipboard/lang/mn.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'mn', { cut: 'Хайчлах', cutError: 'Таны browser-ын хамгаалалтын тохиргоо editor-д автоматаар хайчлах үйлдэлийг зөвшөөрөхгүй байна. (Ctrl/Cmd+X) товчны хослолыг ашиглана уу.', paste: 'Буулгах', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Paste Area', // MISSING + pasteMsg: '(Ctrl/Cmd+V) товчийг ашиглан paste хийнэ үү. Мөн OK дар.', + title: 'Буулгах' } ); diff --git a/plugins/clipboard/lang/ms.js b/plugins/clipboard/lang/ms.js index 23612b3e7a2..049f56750bc 100644 --- a/plugins/clipboard/lang/ms.js +++ b/plugins/clipboard/lang/ms.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ms', { cut: 'Potong', cutError: 'Keselamatan perisian browser anda tidak membenarkan operasi suntingan text/imej. Sila gunakan papan kekunci (Ctrl/Cmd+X).', paste: 'Tampal', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Paste Area', // MISSING + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING + title: 'Tampal' } ); diff --git a/plugins/clipboard/lang/nb.js b/plugins/clipboard/lang/nb.js index 57e36b55525..34101d544d8 100644 --- a/plugins/clipboard/lang/nb.js +++ b/plugins/clipboard/lang/nb.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'nb', { cut: 'Klipp ut', cutError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk utklipping av tekst. Vennligst bruk tastatursnarveien (Ctrl/Cmd+X).', paste: 'Lim inn', - pasteNotification: 'Nettleseren din lar deg ikke lime inn på denne måten. Trykk %1 for å lime inn.' + pasteNotification: 'Nettleseren din lar deg ikke lime inn på denne måten. Trykk %1 for å lime inn.', + pasteArea: 'Innlimingsområde', + pasteMsg: 'Vennligst lim inn i følgende boks med tastaturet (Ctrl/Cmd+V) og trykk OK.', + title: 'Lim inn' } ); diff --git a/plugins/clipboard/lang/nl.js b/plugins/clipboard/lang/nl.js index 7bc1e9d09da..d6c06d0de0a 100644 --- a/plugins/clipboard/lang/nl.js +++ b/plugins/clipboard/lang/nl.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'nl', { cut: 'Knippen', cutError: 'De beveiligingsinstelling van de browser verhinderen het automatisch knippen. Gebruik de sneltoets Ctrl/Cmd+X van het toetsenbord.', paste: 'Plakken', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Plakgebied', + pasteMsg: 'Plak de tekst in het volgende vak gebruikmakend van uw toetsenbord (Ctrl/Cmd+V) en klik op OK.', + title: 'Plakken' } ); diff --git a/plugins/clipboard/lang/no.js b/plugins/clipboard/lang/no.js index 25bda145114..01e9da520f5 100644 --- a/plugins/clipboard/lang/no.js +++ b/plugins/clipboard/lang/no.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'no', { cut: 'Klipp ut', cutError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk utklipping av tekst. Vennligst bruk snarveien (Ctrl/Cmd+X).', paste: 'Lim inn', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Innlimingsområde', + pasteMsg: 'Vennligst lim inn i følgende boks med tastaturet (Ctrl/Cmd+V) og trykk OK.', + title: 'Lim inn' } ); diff --git a/plugins/clipboard/lang/oc.js b/plugins/clipboard/lang/oc.js index 054c207df61..95613a6b014 100644 --- a/plugins/clipboard/lang/oc.js +++ b/plugins/clipboard/lang/oc.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'oc', { cut: 'Talhar', cutError: 'Los paramètres de seguretat de vòstre navigador autorizan pas l\'editor a executar automaticament l\'operacion « Talhar ». Utilizatz l\'acorchi de clavièr a aqueste efièit (Ctrl/Cmd+X).', paste: 'Pegar', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Paste Area', // MISSING + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING + title: 'Paste' // MISSING } ); diff --git a/plugins/clipboard/lang/pl.js b/plugins/clipboard/lang/pl.js index 0f3a36d0686..8431c2a4d91 100644 --- a/plugins/clipboard/lang/pl.js +++ b/plugins/clipboard/lang/pl.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'pl', { cut: 'Wytnij', cutError: 'Ustawienia bezpieczeństwa Twojej przeglądarki nie pozwalają na automatyczne wycinanie tekstu. Użyj skrótu klawiszowego Ctrl/Cmd+X.', paste: 'Wklej', - pasteNotification: 'Twoja przeglądarka nie pozwala na wklejanie treści w ten sposób. Naciśnij %1 by wkleić tekst.' + pasteNotification: 'Twoja przeglądarka nie pozwala na wklejanie treści w ten sposób. Naciśnij %1 by wkleić tekst.', + pasteArea: 'Obszar wklejania', + pasteMsg: 'Wklej tekst w poniższym polu, używając skrótu klawiaturowego (Ctrl/Cmd+V), i kliknij OK.', + title: 'Wklej' } ); diff --git a/plugins/clipboard/lang/pt-br.js b/plugins/clipboard/lang/pt-br.js index c17a60c430f..2df0b1ac882 100644 --- a/plugins/clipboard/lang/pt-br.js +++ b/plugins/clipboard/lang/pt-br.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'pt-br', { cut: 'Recortar', cutError: 'As configurações de segurança do seu navegador não permitem que o editor execute operações de recortar automaticamente. Por favor, utilize o teclado para recortar (Ctrl/Cmd+X).', paste: 'Colar', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Área para Colar', + pasteMsg: 'Transfira o link usado na caixa usando o teclado com (Ctrl/Cmd+V) e OK.', + title: 'Colar' } ); diff --git a/plugins/clipboard/lang/pt.js b/plugins/clipboard/lang/pt.js index 36beec81cdf..ebbff92f5a5 100644 --- a/plugins/clipboard/lang/pt.js +++ b/plugins/clipboard/lang/pt.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'pt', { cut: 'Cortar', cutError: 'A configuração de segurança do navegador não permite a execução automática de operações de cortar. Por favor use o teclado (Ctrl/Cmd+X).', paste: 'Colar', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Colar área', + pasteMsg: 'Por favor, cole dentro da seguinte caixa usando o teclado (Ctrl/Cmd+V) e carregue em OK.', + title: 'Colar' } ); diff --git a/plugins/clipboard/lang/ro.js b/plugins/clipboard/lang/ro.js index 836c26a30ca..62bc304f650 100644 --- a/plugins/clipboard/lang/ro.js +++ b/plugins/clipboard/lang/ro.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ro', { cut: 'Decupează', cutError: 'Setările de securitate ale navigatorului (browser) pe care îl folosiţi nu permit editorului să execute automat operaţiunea de tăiere. Vă rugăm folosiţi tastatura (Ctrl/Cmd+X).', paste: 'Adaugă din clipboard', - pasteNotification: 'Permiteți accesul la clipboard pentru a adăuga conținut?' + pasteNotification: 'Permiteți accesul la clipboard pentru a adăuga conținut?', + pasteArea: 'Suprafața de adăugare', + pasteMsg: 'Vă rugăm adăugaţi în căsuţa următoare folosind tastatura (Ctrl/Cmd+V) şi apăsaţi OK', + title: 'Adaugă' } ); diff --git a/plugins/clipboard/lang/ru.js b/plugins/clipboard/lang/ru.js index 987dd9a363b..3c03636fd67 100644 --- a/plugins/clipboard/lang/ru.js +++ b/plugins/clipboard/lang/ru.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ru', { cut: 'Вырезать', cutError: 'Настройки безопасности вашего браузера не разрешают редактору выполнять операции по вырезке текста. Пожалуйста, используйте для этого клавиатуру (Ctrl/Cmd+X).', paste: 'Вставить', - pasteNotification: 'Ваш браузер не поддерживает данный метод вставки. Для вставки нажмите %1' + pasteNotification: 'Ваш браузер не поддерживает данный метод вставки. Для вставки нажмите %1', + pasteArea: 'Зона для вставки', + pasteMsg: 'Пожалуйста, вставьте текст в зону ниже, используя клавиатуру (Ctrl/Cmd+V) и нажмите кнопку "OK".', + title: 'Вставить' } ); diff --git a/plugins/clipboard/lang/si.js b/plugins/clipboard/lang/si.js index 3cdc372b177..4c03cf8873f 100644 --- a/plugins/clipboard/lang/si.js +++ b/plugins/clipboard/lang/si.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'si', { cut: 'කපාගන්න', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', // MISSING paste: 'අලවන්න', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'අලවන ප්‍රදේශ', + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING + title: 'අලවන්න' } ); diff --git a/plugins/clipboard/lang/sk.js b/plugins/clipboard/lang/sk.js index 0940bca00c8..e53ce92f84f 100644 --- a/plugins/clipboard/lang/sk.js +++ b/plugins/clipboard/lang/sk.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sk', { cut: 'Vystrihnúť', cutError: 'Bezpečnostné nastavenia vášho prehliadača nedovoľujú editoru automaticky spustiť operáciu vystrihnutia. Použite na to klávesnicu (Ctrl/Cmd+X).', paste: 'Vložiť', - pasteNotification: 'Váš prehliadač nepovoľuje prilepiť text takýmto spôsobom. Pre prilepenie stlačte %1.' + pasteNotification: 'Váš prehliadač nepovoľuje prilepiť text takýmto spôsobom. Pre prilepenie stlačte %1.', + pasteArea: 'Miesto na vloženie', + pasteMsg: 'Použitím klávesnice (Ctrl/Cmd+V) vložte text do rámčeka a stlačte OK.', + title: 'Vložiť' } ); diff --git a/plugins/clipboard/lang/sl.js b/plugins/clipboard/lang/sl.js index 7a00664dfdc..d992c9242c1 100644 --- a/plugins/clipboard/lang/sl.js +++ b/plugins/clipboard/lang/sl.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sl', { cut: 'Izreži', cutError: 'Varnostne nastavitve brskalnika ne dopuščajo samodejnega izrezovanja. Uporabite kombinacijo tipk na tipkovnici (Ctrl/Cmd+X).', paste: 'Prilepi', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Prilepi območje', + pasteMsg: 'Prosimo, prilepite v sleči okvir s pomočjo tipkovnice (Ctrl/Cmd+V) in pritisnite V redu.', + title: 'Prilepi' } ); diff --git a/plugins/clipboard/lang/sq.js b/plugins/clipboard/lang/sq.js index 0bed6be2f5f..f47a1e15e55 100644 --- a/plugins/clipboard/lang/sq.js +++ b/plugins/clipboard/lang/sq.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sq', { cut: 'Preje', cutError: 'Të dhënat e sigurisë së shfletuesit tuaj nuk lejojnë që redaktuesi automatikisht të kryej veprimin e prerjes. Ju lutemi shfrytëzoni tastierën për këtë veprim (Ctrl/Cmd+X).', paste: 'Hidhe', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Hapësira Hedhëse', + pasteMsg: 'Ju lutemi hidhni brenda kutizës në vijim duke shfrytëzuar tastierën (Ctrl/Cmd+V) dhe shtypni Mirë.', + title: 'Hidhe' } ); diff --git a/plugins/clipboard/lang/sr-latn.js b/plugins/clipboard/lang/sr-latn.js index 1621ea4a110..bde1d4efb13 100644 --- a/plugins/clipboard/lang/sr-latn.js +++ b/plugins/clipboard/lang/sr-latn.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sr-latn', { cut: 'Iseci', cutError: 'Sigurnosna podešavanja Vašeg pretraživača ne dozvoljavaju operacije automatskog isecanja teksta. Molimo Vas da koristite prečicu sa tastature (Ctrl/Cmd+X).', paste: 'Zalepi', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Prostor za lepljenje', + pasteMsg: 'Molimo Vas da zalepite unutar donje povrine koristeći tastaturnu prečicu (Ctrl/Cmd+V) i da pritisnete OK.', + title: 'Zalepi' } ); diff --git a/plugins/clipboard/lang/sr.js b/plugins/clipboard/lang/sr.js index b30385d439c..8003cf48dd4 100644 --- a/plugins/clipboard/lang/sr.js +++ b/plugins/clipboard/lang/sr.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sr', { cut: 'Исеци', cutError: 'Сигурносна подешавања Вашег претраживача не дозвољавају операције аутоматског исецања текста. Молимо Вас да користите пречицу са тастатуре (Ctrl/Cmd+X).', paste: 'Залепи', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Залепи зону', + pasteMsg: 'Молимо Вас да залепите унутар доње површине користећи тастатурну пречицу (Ctrl/Cmd+V) и да притиснете OK.', + title: 'Залепи' } ); diff --git a/plugins/clipboard/lang/sv.js b/plugins/clipboard/lang/sv.js index 464fb932c3b..e34a9b7f0a1 100644 --- a/plugins/clipboard/lang/sv.js +++ b/plugins/clipboard/lang/sv.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sv', { cut: 'Klipp ut', cutError: 'Säkerhetsinställningar i din webbläsare tillåter inte åtgärden klipp ut. Använd (Ctrl/Cmd+X) istället.', paste: 'Klistra in', - pasteNotification: 'Din webbläsare tillåter dig inte att klistra in på detta vis. Tryck på %1 för att klistra in.' + pasteNotification: 'Din webbläsare tillåter dig inte att klistra in på detta vis. Tryck på %1 för att klistra in.', + pasteArea: 'Paste Area', + pasteMsg: 'Var god och klistra in Er text i rutan nedan genom att använda (Ctrl/Cmd+V) klicka sen på OK.', + title: 'Klistra in' } ); diff --git a/plugins/clipboard/lang/th.js b/plugins/clipboard/lang/th.js index 8dde68a300e..dbf1de7bfab 100644 --- a/plugins/clipboard/lang/th.js +++ b/plugins/clipboard/lang/th.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'th', { cut: 'ตัด', cutError: 'ไม่สามารถตัดข้อความที่เลือกไว้ได้เนื่องจากการกำหนดค่าระดับความปลอดภัย. กรุณาใช้ปุ่มลัดเพื่อวางข้อความแทน (กดปุ่ม Ctrl/Cmd และตัว X พร้อมกัน).', paste: 'วาง', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Paste Area', // MISSING + pasteMsg: 'กรุณาใช้คีย์บอร์ดเท่านั้น โดยกดปุ๋ม (Ctrl/Cmd และ V)พร้อมๆกัน และกด OK.', + title: 'วาง' } ); diff --git a/plugins/clipboard/lang/tr.js b/plugins/clipboard/lang/tr.js index 7e6593a7ebc..40c4c25cbc2 100644 --- a/plugins/clipboard/lang/tr.js +++ b/plugins/clipboard/lang/tr.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'tr', { cut: 'Kes', cutError: 'Gezgin yazılımınızın güvenlik ayarları düzenleyicinin otomatik kesme işlemine izin vermiyor. İşlem için (Ctrl/Cmd+X) tuşlarını kullanın.', paste: 'Yapıştır', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Yapıştırma Alanı', + pasteMsg: 'Lütfen aşağıdaki kutunun içine yapıştırın. (Ctrl/Cmd+V) ve Tamam butonunu tıklayın.', + title: 'Yapıştır' } ); diff --git a/plugins/clipboard/lang/tt.js b/plugins/clipboard/lang/tt.js index 99e1e844f33..386202e1283 100644 --- a/plugins/clipboard/lang/tt.js +++ b/plugins/clipboard/lang/tt.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'tt', { cut: 'Кисеп алу', cutError: 'Браузерыгызның иминлек үзлекләре автоматик рәвештә күчермәләү үтәүне тыя. Тиз төймәләрне (Ctrl/Cmd+C) кулланыгыз.', paste: 'Өстәү', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Өстәү мәйданы', + pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING + title: 'Өстәү' } ); diff --git a/plugins/clipboard/lang/ug.js b/plugins/clipboard/lang/ug.js index 941cde6b1da..b8a5ada69f0 100644 --- a/plugins/clipboard/lang/ug.js +++ b/plugins/clipboard/lang/ug.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ug', { cut: 'كەس', cutError: 'تور كۆرگۈڭىزنىڭ بىخەتەرلىك تەڭشىكى تەھرىرلىگۈچنىڭ كەس مەشغۇلاتىنى ئۆزلۈكىدىن ئىجرا قىلىشىغا يول قويمايدۇ، ھەرپتاختا تېز كۇنۇپكا (Ctrl/Cmd+X) ئارقىلىق تاماملاڭ', paste: 'چاپلا', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'چاپلاش دائىرىسى', + pasteMsg: 'ھەرپتاختا تېز كۇنۇپكا (Ctrl/Cmd+V) نى ئىشلىتىپ مەزمۇننى تۆۋەندىكى رامكىغا كۆچۈرۈڭ، ئاندىن جەزملەنى بېسىڭ', + title: 'چاپلا' } ); diff --git a/plugins/clipboard/lang/uk.js b/plugins/clipboard/lang/uk.js index 60e16ea7e32..f41ab5ed23e 100644 --- a/plugins/clipboard/lang/uk.js +++ b/plugins/clipboard/lang/uk.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'uk', { cut: 'Вирізати', cutError: 'Налаштування безпеки Вашого браузера не дозволяють редактору автоматично виконувати операції вирізування. Будь ласка, використовуйте клавіатуру для цього (Ctrl/Cmd+X)', paste: 'Вставити', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: 'Область вставки', + pasteMsg: 'Будь ласка, вставте інформацію з буфера обміну в цю область, користуючись комбінацією клавіш (Ctrl/Cmd+V), та натисніть OK.', + title: 'Вставити' } ); diff --git a/plugins/clipboard/lang/vi.js b/plugins/clipboard/lang/vi.js index 2b1f33aff3d..5c7f061d48d 100644 --- a/plugins/clipboard/lang/vi.js +++ b/plugins/clipboard/lang/vi.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'vi', { cut: 'Cắt', cutError: 'Các thiết lập bảo mật của trình duyệt không cho phép trình biên tập tự động thực thi lệnh cắt. Hãy sử dụng bàn phím cho lệnh này (Ctrl/Cmd+X).', paste: 'Dán', - pasteNotification: 'Trình duyệt của bạn không cho phép bạn dán theo cách này. Nhấn %1 để dán' + pasteNotification: 'Trình duyệt của bạn không cho phép bạn dán theo cách này. Nhấn %1 để dán', + pasteArea: 'Khu vực dán', + pasteMsg: 'Hãy dán nội dung vào trong khung bên dưới, sử dụng tổ hợp phím (Ctrl/Cmd+V) và nhấn vào nút Đồng ý.', + title: 'Dán' } ); diff --git a/plugins/clipboard/lang/zh-cn.js b/plugins/clipboard/lang/zh-cn.js index 0aa54c70582..9a62a6d68aa 100644 --- a/plugins/clipboard/lang/zh-cn.js +++ b/plugins/clipboard/lang/zh-cn.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'zh-cn', { cut: '剪切', cutError: '您的浏览器安全设置不允许编辑器自动执行剪切操作,请使用键盘快捷键(Ctrl/Cmd+X)来完成。', paste: '粘贴', - pasteNotification: '您的浏览器不允许用此方式粘贴,要粘贴请按 %1。' + pasteNotification: '您的浏览器不允许用此方式粘贴,要粘贴请按 %1。', + pasteArea: '粘贴区域', + pasteMsg: '请使用键盘快捷键(Ctrl/Cmd+V)把内容粘贴到下面的方框里,再按 确定', + title: '粘贴' } ); diff --git a/plugins/clipboard/lang/zh.js b/plugins/clipboard/lang/zh.js index 56eb3a7e1e5..734c8b1c702 100644 --- a/plugins/clipboard/lang/zh.js +++ b/plugins/clipboard/lang/zh.js @@ -8,5 +8,8 @@ CKEDITOR.plugins.setLang( 'clipboard', 'zh', { cut: '剪下', cutError: '瀏覽器的安全性設定不允許編輯器自動執行剪下動作。請使用鏐盤快捷鍵 (Ctrl/Cmd+X) 剪下。', paste: '貼上', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.' // MISSING + pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteArea: '貼上區', + pasteMsg: '請使用鍵盤快捷鍵 (Ctrl/Cmd+V) 貼到下方區域中並按下「確定」。', + title: '貼上' } ); From 050e51750fccdfa0275b19b7f186487f2d6dc149 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 6 Feb 2018 15:00:24 +0100 Subject: [PATCH 570/642] Updated license header. --- plugins/clipboard/dialogs/paste.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/clipboard/dialogs/paste.js b/plugins/clipboard/dialogs/paste.js index 780c334fb38..8ba6ef29635 100644 --- a/plugins/clipboard/dialogs/paste.js +++ b/plugins/clipboard/dialogs/paste.js @@ -1,6 +1,6 @@ /** - * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or http://ckeditor.com/license + * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.dialog.add( 'paste', function( editor ) { From a7c2fa4f55a1d8388a85322a32529093f4fac7a6 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 6 Feb 2018 17:40:30 +0100 Subject: [PATCH 571/642] Feature is retargetted to 4.9.0. --- plugins/clipboard/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index 5a6034bf23b..62810af3af0 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -1656,7 +1656,7 @@ * Adds new paste button to the editor. In order for the button * to displayPaste Dialog on mobile devices it should be added via this method. * - * @since 4.8.0 + * @since 4.9.0 * @param {CKEDITOR.editor} editor The editor instance. * @param {String} name Name of the button. * @param {Object} definition Definition of the button. From a7012e0375ec8db3a69ed4285b7828123b8e672a Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Tue, 6 Feb 2018 21:08:52 +0100 Subject: [PATCH 572/642] Rephrased API docs for addPasteButton in the clipboard plugin. --- plugins/clipboard/plugin.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index 62810af3af0..9d4340a4a2d 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -1653,8 +1653,11 @@ mainPasteEvent: ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) ? 'beforepaste' : 'paste', /** - * Adds new paste button to the editor. In order for the button - * to displayPaste Dialog on mobile devices it should be added via this method. + * Adds a new paste button to the editor. + * + * This method should be called for buttons that should display the Paste Dialog fallback in mobile environments. + * See {@link https://github.com/ckeditor/ckeditor-dev/issues/595#issuecomment-345971174 the rationale} for more + * details. * * @since 4.9.0 * @param {CKEDITOR.editor} editor The editor instance. From 66687c82ce7c54d6161dfe7d7bf6731d6ab66ea8 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 7 Feb 2018 10:41:08 +0100 Subject: [PATCH 573/642] Tests: corrected pasting manual tests. --- tests/plugins/clipboard/manual/missingbutton.md | 4 ++-- tests/plugins/clipboard/manual/pastedialogmobile.md | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/plugins/clipboard/manual/missingbutton.md b/tests/plugins/clipboard/manual/missingbutton.md index 2f5daccd556..0e95875a174 100644 --- a/tests/plugins/clipboard/manual/missingbutton.md +++ b/tests/plugins/clipboard/manual/missingbutton.md @@ -1,4 +1,4 @@ -@bender-tags: bug, 4.8.1, 595 +@bender-tags: bug, 4.9.0, 595 @bender-ui: collapsed @bender-ckeditor-plugins: wysiwygarea, toolbar, clipboard, floatingspace, htmlwriter @@ -8,6 +8,6 @@ No error is thrown. -## Actual +## Unexpected The `plugin.js:588 Uncaught TypeError: Cannot read property '_' of undefined` error is logged. diff --git a/tests/plugins/clipboard/manual/pastedialogmobile.md b/tests/plugins/clipboard/manual/pastedialogmobile.md index f70bd8a280b..d71bfbf3587 100644 --- a/tests/plugins/clipboard/manual/pastedialogmobile.md +++ b/tests/plugins/clipboard/manual/pastedialogmobile.md @@ -1,4 +1,4 @@ -@bender-tags: bug, 4.8.0, 595 +@bender-tags: bug, 4.9.0, 595 @bender-ui: collapsed @bender-ckeditor-plugins: wysiwygarea, toolbar, clipboard, floatingspace, htmlwriter, @@ -6,7 +6,7 @@ Click paste button on the toolbar. -### Expected result: +### Expected Notification about unability to paste in such way is displayed. @@ -14,7 +14,7 @@ Notification about unability to paste in such way is displayed. Touch paste button on the toolbar. -### Expected result: +### Expected * Paste dialog is shown. * Dismissing paste dialog does not trigger any notification. @@ -27,7 +27,7 @@ Touch paste button on the toolbar. 4. Disable touch emulation. 5. Click paste button on the toolbar. -### Expected result: +### Expected * Touching button should display paste dialog. * Clicking button should display notification. From 57fda2c0951c5cdfdfc23ff92fddbebd6f74fc32 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 7 Feb 2018 11:29:06 +0100 Subject: [PATCH 574/642] Fix typo in committed. --- plugins/clipboard/dialogs/paste.js | 6 +++--- plugins/clipboard/plugin.js | 2 +- tests/plugins/clipboard/pastedialog.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/clipboard/dialogs/paste.js b/plugins/clipboard/dialogs/paste.js index 8ba6ef29635..bdc03821075 100644 --- a/plugins/clipboard/dialogs/paste.js +++ b/plugins/clipboard/dialogs/paste.js @@ -99,8 +99,8 @@ CKEDITOR.dialog.add( 'paste', function( editor ) { this.parts.title.setHtml( this.customTitle || lang.title ); this.customTitle = null; - // Reset commited indicator. - this._.commited = false; + // Reset committed indicator. + this._.committed = false; }, onLoad: function() { @@ -228,7 +228,7 @@ CKEDITOR.dialog.add( 'paste', function( editor ) { // Saving the contents so changes until paste is complete will not take place (#7500) html = body.getHtml(); - this.getDialog()._.commited = true; + this.getDialog()._.committed = true; editor.fire( 'pasteDialogCommit', { dataValue: html, diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index 9d4340a4a2d..bc7d461a7b2 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -475,7 +475,7 @@ evt.data.removeListener( 'pasteDialogCommit', onDialogCommit ); // Notify even if user canceled dialog (clicked 'cancel', ESC, etc). - if ( !evt.data._.commited ) { + if ( !evt.data._.committed ) { callback( null ); } } ); diff --git a/tests/plugins/clipboard/pastedialog.js b/tests/plugins/clipboard/pastedialog.js index 2aac0375f36..c925c482044 100644 --- a/tests/plugins/clipboard/pastedialog.js +++ b/tests/plugins/clipboard/pastedialog.js @@ -78,7 +78,7 @@ notificationListener.removeListener(); assert.areSame( 0, notificationSpy.callCount, 'notifications count' ); - assert.isTrue( editor._.storedDialogs.paste._.commited, 'Dialog commited state (after)' ); + assert.isTrue( editor._.storedDialogs.paste._.committed, 'Dialog committed state (after)' ); assert.isFalse( editor._.forcePasteDialog, 'Force paste dialog' ); } ); } ); @@ -89,7 +89,7 @@ tc.resume( function() { var dialog = editor._.storedDialogs.paste; assert.isTrue( !!dialog ); - assert.isFalse( dialog._.commited, 'Dialog commited state (before)' ); + assert.isFalse( dialog._.committed, 'Dialog committed state (before)' ); var frameDoc = dialog.getContentElement( 'general', 'editing_area' ) .getInputElement().getFrameDocument(); From 64739d282a48094e1a76ec766fae35076adb5be5 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 7 Feb 2018 12:13:40 +0100 Subject: [PATCH 575/642] Preserver editor's private member pasteButtons. --- plugins/clipboard/plugin.js | 2 -- tests/plugins/clipboard/pastedialog.js | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index bc7d461a7b2..3d6da4226eb 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -591,8 +591,6 @@ } ); } } ); - - delete editor._.pasteButtons; } ); } } diff --git a/tests/plugins/clipboard/pastedialog.js b/tests/plugins/clipboard/pastedialog.js index c925c482044..b94954042fa 100644 --- a/tests/plugins/clipboard/pastedialog.js +++ b/tests/plugins/clipboard/pastedialog.js @@ -161,7 +161,7 @@ removeButtons: 'Paste,PasteText' } }, function( bot ) { - assert.isUndefined( bot.editor._.pasteButtons ); + arrayAssert.containsItems( [ 'Paste', 'PasteText', 'PasteFromWord' ], bot.editor._.pasteButtons ); } ); }, @@ -174,7 +174,7 @@ removeButtons: 'Paste,PasteText' } }, function( bot ) { - assert.isUndefined( bot.editor._.pasteButtons ); + arrayAssert.containsItems( [ 'Paste', 'PasteText' ], bot.editor._.pasteButtons ); } ); } } ); From 05fc1377f02ead5721df8b140f097a6387a88443 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 7 Feb 2018 12:46:59 +0100 Subject: [PATCH 576/642] Add note about non-availability of events in 4.7.0-4.8.0 versions. --- plugins/clipboard/dialogs/paste.js | 2 ++ plugins/clipboard/plugin.js | 3 +++ 2 files changed, 5 insertions(+) diff --git a/plugins/clipboard/dialogs/paste.js b/plugins/clipboard/dialogs/paste.js index bdc03821075..3138da009eb 100644 --- a/plugins/clipboard/dialogs/paste.js +++ b/plugins/clipboard/dialogs/paste.js @@ -245,6 +245,8 @@ CKEDITOR.dialog.add( 'paste', function( editor ) { /** * Internal event to pass paste dialog's data to the listeners. * + * This event was not available in 4.7.0-4.8.0 versions. + * * @private * @event pasteDialogCommit * @member CKEDITOR.editor diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index 3d6da4226eb..e1bb1344de3 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -3124,6 +3124,9 @@ /** * Internal event to open the Paste dialog window. * + * + * This event was not available in 4.7.0-4.8.0 versions. + * * @private * @event pasteDialog * @member CKEDITOR.editor From 64197d04f7b5ea1a6b322bc72f7ed16987c854a2 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 7 Feb 2018 12:56:29 +0100 Subject: [PATCH 577/642] Drop handling of options in editor.getClipboardData. --- plugins/clipboard/dialogs/paste.js | 5 ----- plugins/clipboard/plugin.js | 6 +----- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/plugins/clipboard/dialogs/paste.js b/plugins/clipboard/dialogs/paste.js index 3138da009eb..7b118503534 100644 --- a/plugins/clipboard/dialogs/paste.js +++ b/plugins/clipboard/dialogs/paste.js @@ -94,11 +94,6 @@ CKEDITOR.dialog.add( 'paste', function( editor ) { this.setupContent(); - // Set dialog title to the custom value (set e.g. in editor.openDialog callback) and reset this value. - // If custom title not set, use default one. - this.parts.title.setHtml( this.customTitle || lang.title ); - this.customTitle = null; - // Reset committed indicator. this._.committed = false; }, diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index e1bb1344de3..744db38cc66 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -466,7 +466,7 @@ // If beforePaste was canceled do not open dialog. // Add listeners only if dialog really opened. 'pasteDialog' can be canceled. - if ( editor._.forcePasteDialog && beforePasteNotCanceled && editor.fire( 'pasteDialog', onDialogOpen ) ) { + if ( editor._.forcePasteDialog && beforePasteNotCanceled && editor.fire( 'pasteDialog' ) ) { editor.on( 'pasteDialogCommit', onDialogCommit ); // 'dialogHide' will be fired after 'pasteDialogCommit'. @@ -509,10 +509,6 @@ method: 'paste' } ); } - - function onDialogOpen() { - this.customTitle = ( callbackOrOptions && typeof callbackOrOptions === 'object' && callbackOrOptions.title ); - } }; function addButtonsCommands() { From c26cf4733920f24b870d416b899f5960a98a8537 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 7 Feb 2018 13:09:28 +0100 Subject: [PATCH 578/642] =?UTF-8?q?Make=20paste=20message=20gre=E2=80=A6?= =?UTF-8?q?=20more=20generic.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/clipboard/lang/en.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/clipboard/lang/en.js b/plugins/clipboard/lang/en.js index 5c6d7ab38cf..e0643d43dcf 100644 --- a/plugins/clipboard/lang/en.js +++ b/plugins/clipboard/lang/en.js @@ -10,6 +10,6 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en', { paste: 'Paste', pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', pasteArea: 'Paste Area', - pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', + pasteMsg: 'Please paste inside the following box and hit OK', title: 'Paste' } ); From 0003fa1a7c1ab598ad52a163bcdf7d129c18c002 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 7 Feb 2018 13:29:23 +0100 Subject: [PATCH 579/642] Update tests names. --- tests/plugins/clipboard/pastedialog.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plugins/clipboard/pastedialog.js b/tests/plugins/clipboard/pastedialog.js index b94954042fa..139d5cadb18 100644 --- a/tests/plugins/clipboard/pastedialog.js +++ b/tests/plugins/clipboard/pastedialog.js @@ -18,7 +18,7 @@ this.editor.focus(); }, - 'pasteDialog event': function() { + 'test pasteDialog event': function() { var tc = this, editor = this.editor; @@ -38,7 +38,7 @@ tc.wait(); }, - 'paste html': function() { + 'test paste html': function() { if ( CKEDITOR.env.ie ) { assert.ignore(); } From bfae678e6ca83576538851efc04349dc803f066b Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 7 Feb 2018 13:46:38 +0100 Subject: [PATCH 580/642] Fix test of event structure. --- tests/plugins/clipboard/pastedialog.js | 31 +++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tests/plugins/clipboard/pastedialog.js b/tests/plugins/clipboard/pastedialog.js index 139d5cadb18..47245c19fcc 100644 --- a/tests/plugins/clipboard/pastedialog.js +++ b/tests/plugins/clipboard/pastedialog.js @@ -13,6 +13,8 @@ bender.test( { setUp: function() { + //Force dialog. + this.editor._.forcePasteDialog = true; // Force result data un-formatted. this.editor.dataProcessor.writer._.rules = {}; this.editor.focus(); @@ -73,7 +75,9 @@ } ); } ); - editor.on( 'afterPaste', function() { + editor.on( 'afterPaste', function( evt ) { + evt.removeListener(); + tc.resume( function() { notificationListener.removeListener(); @@ -104,8 +108,6 @@ } ); setTimeout( function() { - //Force dialog. - editor._.forcePasteDialog = true; editor.execCommand( 'paste' ); } ); tc.wait(); @@ -142,14 +144,27 @@ dataTransfer = CKEDITOR.plugins.clipboard.initPasteDataTransfer(); editor.once( 'paste', function( evt ) { - evt.cancel(); + resume( function() { + evt.cancel(); - assert.areSame( 'foo', evt.data.dataValue, 'dataValue' ); - assert.areSame( 'paste', evt.data.method, 'method' ); - assert.areSame( dataTransfer, evt.data.dataTransfer, 'dataTransfer' ); + assert.areSame( 'foo', evt.data.dataValue, 'dataValue' ); + assert.areSame( 'paste', evt.data.method, 'method' ); + assert.areSame( dataTransfer, evt.data.dataTransfer, 'dataTransfer' ); + } ); } ); - editor.fire( 'pasteDialogCommit', { dataValue: 'foo', dataTransfer: dataTransfer } ); + editor.once( 'dialogShow', function() { + resume( function() { + var dialog = editor._.storedDialogs.paste; + + editor.fire( 'pasteDialogCommit', { dataValue: 'foo', dataTransfer: dataTransfer } ); + dialog.hide(); + wait(); + } ); + } ); + + editor.fire( 'pasteDialog' ); + wait(); }, 'test paste dialog with some paste buttons removed': function() { From cbdf823e437c69ae69bd0d83ac3b95c2cbc793aa Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 7 Feb 2018 13:59:53 +0100 Subject: [PATCH 581/642] Add unit test for paste events count. --- tests/plugins/clipboard/pastedialog.js | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/plugins/clipboard/pastedialog.js b/tests/plugins/clipboard/pastedialog.js index 47245c19fcc..e82ef0d9d13 100644 --- a/tests/plugins/clipboard/pastedialog.js +++ b/tests/plugins/clipboard/pastedialog.js @@ -167,6 +167,44 @@ wait(); }, + 'test paste event count': function() { + var editor = this.editor, + spy = sinon.spy(), + listener; + + listener = editor.on( 'paste', spy ); + + editor.once( 'afterPaste', function() { + setTimeout( function() { + resume( function() { + listener.removeListener(); + + assert.areSame( 1, spy.callCount, 'Paste count' ); + } ); + }, 100 ); + } ); + + editor.once( 'dialogShow', function() { + resume( function() { + var dialog = editor._.storedDialogs.paste; + + var frameDoc = dialog.getContentElement( 'general', 'editing_area' ) + .getInputElement().getFrameDocument(); + + frameDoc.getBody().setHtml( 'foo' ); + + dialog.fire( 'ok' ); + dialog.hide(); + wait(); + } ); + } ); + + setTimeout( function() { + editor.execCommand( 'paste' ); + } ); + wait(); + }, + 'test paste dialog with some paste buttons removed': function() { bender.editorBot.create( { name: 'some_paste_buttons', From 0da6ca7bc4491171007c26903c94976ebdf724c7 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 7 Feb 2018 14:01:41 +0100 Subject: [PATCH 582/642] Add changelog entry. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index b69659171cd..6214f9cafcc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,7 @@ New Features: Fixed Issues: +* [#595](https://github.com/ckeditor/ckeditor-dev/issues/595): Fixed: Pasting does not work on mobile devices. * [#869](https://github.com/ckeditor/ckeditor-dev/issues/869): Fixed: Empty selection clears cached clipboard data in editor. * [#1419](https://github.com/ckeditor/ckeditor-dev/issues/1419): Fixed: [Widged Selection](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widgetselection) selects editor content with `alt + a` key combination on Windows. * [#1274](https://github.com/ckeditor/ckeditor-dev/issues/1274): Fixed: [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) does not match a single selected image using [`contextDefinition.cssSelector`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.balloontoolbar.contextDefinition-property-cssSelector) matcher. From adc9503bd7e3beb20961a4a0408dc69831a58cd8 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 7 Feb 2018 16:58:09 +0100 Subject: [PATCH 583/642] Tests: disabled mobile fix check for IE/Edge. Minor corrections. --- tests/plugins/clipboard/mobilefix.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/plugins/clipboard/mobilefix.js b/tests/plugins/clipboard/mobilefix.js index b4ce004236a..d5893d0ec7b 100644 --- a/tests/plugins/clipboard/mobilefix.js +++ b/tests/plugins/clipboard/mobilefix.js @@ -38,7 +38,7 @@ dialogSpy = sinon.spy(), dialogListener; - //Reset forcePasteDialog just to be sure + // Reset forcePasteDialog just to be sure editor._.forcePasteDialog = false; dialogListener = editor.on( 'pasteDialog', dialogSpy ); @@ -68,7 +68,7 @@ function assertClick( editor, buttonName ) { var buttonElement = getButtonElement( editor, buttonName ); - //Reset forcePasteDialog just to be sure + // Reset forcePasteDialog just to be sure editor._.forcePasteDialog = false; buttonElement.once( 'click', function() { @@ -79,6 +79,13 @@ } var tests = { + setUp: function() { + if ( CKEDITOR.env.ie ) { + // IE and Edge are not supported on mobile. + assert.ignore(); + } + }, + 'test force dialog when button is touched': function( editor ) { assertTouchEnd( editor, 'Paste' ); }, From 0c23d2259670c71fac0c096d27a0e531a3e63373 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 7 Feb 2018 16:58:56 +0100 Subject: [PATCH 584/642] Tests: stubbed document.execCommand so that IE does not display a security dialog. --- tests/plugins/clipboard/pastedialog.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/plugins/clipboard/pastedialog.js b/tests/plugins/clipboard/pastedialog.js index e82ef0d9d13..32061a0fc3b 100644 --- a/tests/plugins/clipboard/pastedialog.js +++ b/tests/plugins/clipboard/pastedialog.js @@ -170,13 +170,21 @@ 'test paste event count': function() { var editor = this.editor, spy = sinon.spy(), + // Stub execCommand so that IE does not put the paste permission popup. Normally we'd use sinon here + // unfortunately IE8 will cry that document.execCommand is an object, not a function. + originalDocumentExec = editor.document.$.execCommand, listener; + editor.document.$.execCommand = function() { + return true; + }; + listener = editor.on( 'paste', spy ); editor.once( 'afterPaste', function() { setTimeout( function() { resume( function() { + editor.document.$.execCommand = originalDocumentExec; listener.removeListener(); assert.areSame( 1, spy.callCount, 'Paste count' ); From 2a66a29bac53ae3be15da109b3b466fd49952405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Thu, 14 Dec 2017 13:37:09 +0100 Subject: [PATCH 585/642] CKEDITOR.menu improvements. --- plugins/menu/plugin.js | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/plugins/menu/plugin.js b/plugins/menu/plugin.js index c43aaa43c0d..a44e0b67f15 100644 --- a/plugins/menu/plugin.js +++ b/plugins/menu/plugin.js @@ -405,12 +405,15 @@ CKEDITOR.plugins.add( 'menu', { CKEDITOR.ui.fire( 'ready', this ); // Show the panel. - if ( this.parent ) + if ( this.parent ) { this.parent._.panel.showAsChild( panel, this.id, offsetParent, corner, offsetX, offsetY ); - else + } else { panel.showBlock( this.id, offsetParent, corner, offsetX, offsetY ); + } - editor.fire( 'menuShow', [ panel ] ); + var data = [ panel ]; + data.menu = this; + editor.fire( 'menuShow', data ); }, /** @@ -435,6 +438,35 @@ CKEDITOR.plugins.add( 'menu', { hide: function( returnFocus ) { this._.onHide && this._.onHide(); this._.panel && this._.panel.hide( returnFocus ); + }, + + /** + * Finds menu item corresponding to a given command. + * + * **Notice**: keep in mind that menu is rerendered on each open so caching items (especially DOM elements) + * may not work. Also executing this method when menu is not visible may result in unexpected results as the + * items may not be rendered. + * + * @param {String} commandName + * @returns {Object|null} return Object containing given item. If item was not found, null is returned. + * @returns {CKEDITOR.menuItem} return.item Item definition. + * @returns {CKEDITOR.dom.element} return.element Rendered element representing item in the menu. + */ + findItemByCommandName: function( commandName ) { + var commands = CKEDITOR.tools.array.filter( this.items, function( item ) { + return commandName === item.command; + } ); + + if ( commands.length ) { + var commandItem = commands[ 0 ]; + + return { + item: commandItem, + element: this._.element.findOne( '.' + commandItem.className ) + }; + } + + return null; } } } ); @@ -553,6 +585,7 @@ CKEDITOR.plugins.add( 'menu', { * @member CKEDITOR.editor * @param {CKEDITOR.editor} editor This editor instance. * @param {CKEDITOR.ui.panel[]} data + * @param {CKEDITOR.menu} data.menu */ /** From 56f5bf91554c63a305466f15959a1ccaa5fd28ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Thu, 14 Dec 2017 13:38:01 +0100 Subject: [PATCH 586/642] Integrate context menu paste item with 'touchend' event. --- plugins/clipboard/plugin.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index 744db38cc66..e61d3385bb6 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -564,6 +564,24 @@ paste: stateFromNamedCommand( 'paste' ) }; } ); + + // Adds 'touchend' integration with context menu paste item (#1347). + var pasteListener = null; + editor.on( 'menuShow', function( evt ) { + // Remove previous listener. + if ( pasteListener ) { + pasteListener.removeListener(); + pasteListener = null; + } + + // Attach new 'touchend' listeners to context menu paste items. + var item = evt.data.menu.findItemByCommandName( 'paste' ); + if ( item && item.element ) { + pasteListener = item.element.on( 'touchend', function() { + editor._.forcePasteDialog = true; + } ); + } + } ); } // Detect if any of paste buttons was touched. In such case we assume that user is using From ba6e4989233c0697e77e9774481f34bf16ca8444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Thu, 14 Dec 2017 14:45:43 +0100 Subject: [PATCH 587/642] Tests: context menu integration manual test. --- .../manual/pastedialogmenumobile.html | 17 ++++++++++ .../clipboard/manual/pastedialogmenumobile.md | 34 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 tests/plugins/clipboard/manual/pastedialogmenumobile.html create mode 100644 tests/plugins/clipboard/manual/pastedialogmenumobile.md diff --git a/tests/plugins/clipboard/manual/pastedialogmenumobile.html b/tests/plugins/clipboard/manual/pastedialogmenumobile.html new file mode 100644 index 00000000000..934a62c6aee --- /dev/null +++ b/tests/plugins/clipboard/manual/pastedialogmenumobile.html @@ -0,0 +1,17 @@ + + + diff --git a/tests/plugins/clipboard/manual/pastedialogmenumobile.md b/tests/plugins/clipboard/manual/pastedialogmenumobile.md new file mode 100644 index 00000000000..180f8866696 --- /dev/null +++ b/tests/plugins/clipboard/manual/pastedialogmenumobile.md @@ -0,0 +1,34 @@ +@bender-tags: bug, 4.8.1, 595, 1347 +@bender-ui: collapsed +@bender-ckeditor-plugins: wysiwygarea, toolbar, clipboard, floatingspace, htmlwriter, contextmenu, undo + +## On non-touch devices + +1. Right click to open context menu. +1. Click paste. + +### Expected result: + +Notification about inability to paste in such way is displayed. + +## On touch devices + +1. Touch and hold to open context menu. +1. Click paste. + +### Expected result: + +* Paste dialog is shown. +* Dismissing paste dialog does not trigger any notification. + +## On non-touch devices with touch emulation (e.g. responsive view in browser) + +1. Enable touch emulation. +1. Right click to open context menu. +1. Click paste. + * **Expected**: Paste dialog is shown. +1. Close paste dialog. +1. Disable touch emulation. +1. Right click to open context menu. +1. Click paste. + * **Expected**: Notification about inability to paste in such way is displayed. From cc901f9abcde87ec7f551cb8ea4f09a053c786e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Fri, 15 Dec 2017 12:22:16 +0100 Subject: [PATCH 588/642] Tests: context menu integration unit tests. --- .../plugins/clipboard/mobilefixcontextmenu.js | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 tests/plugins/clipboard/mobilefixcontextmenu.js diff --git a/tests/plugins/clipboard/mobilefixcontextmenu.js b/tests/plugins/clipboard/mobilefixcontextmenu.js new file mode 100644 index 00000000000..9cec2e58fc7 --- /dev/null +++ b/tests/plugins/clipboard/mobilefixcontextmenu.js @@ -0,0 +1,104 @@ +/* bender-tags: editor,clipboard */ +/* bender-ckeditor-plugins: toolbar,clipboard,wysiwygarea,contextmenu */ + +( function() { + 'use strict'; + + bender.editors = { + classic: { + config: { + language: 'en' + } + }, + + divarea: { + config: { + language: 'en', + extraPlugins: 'divarea' + } + }, + + inline: { + creator: 'inline', + config: { + language: 'en' + } + } + }; + + function assertTouchEnd( bot, editor ) { + var notificationSpy = sinon.spy( editor, 'showNotification' ), + dialogSpy = sinon.spy(), + dialogListener; + + dialogListener = editor.on( 'pasteDialog', dialogSpy ); + + editor.once( 'dialogShow', function( evt ) { + resume( function() { + var dialog = evt.data; + + dialogListener.removeListener(); + + assert.areSame( 1, dialogSpy.callCount, 'pasteDialog event count' ); + + dialog.fire( 'cancel' ); + dialog.hide(); + } ); + } ); + + bot.contextmenu( function( menu ) { + var menuItem = menu.findItemByCommandName( 'paste' ); + + menuItem.element.once( 'touchend', function() { + assert.isTrue( editor._.forcePasteDialog, 'Forcing paste dialog' ); + assert.isFalse( notificationSpy.called, 'Notification not shown' ); + notificationSpy.restore(); + }, null, null, 999 ); + + menuItem.element.fire( 'touchend' ); + menuItem.element.$.click(); + + wait(); + } ); + } + + function assertClick( bot, editor ) { + var notificationSpy = sinon.spy( editor, 'showNotification' ); + + bot.contextmenu( function( menu ) { + var menuItem = menu.findItemByCommandName( 'paste' ); + + menuItem.element.once( 'click', function() { + assert.isFalse( editor._.forcePasteDialog, 'Forcing paste dialog' ); + assert.areSame( 1, notificationSpy.callCount, 'Notification shown' ); + notificationSpy.restore(); + }, null, null, 999 ); + + menuItem.element.$.click(); + } ); + } + + var editorBots, + tests = { + init: function() { + editorBots = this.editorBots; + }, + + setUp: function() { + this.editors.classic._.forcePasteDialog = false; + this.editors.divarea._.forcePasteDialog = false; + this.editors.inline._.forcePasteDialog = false; + }, + + 'test force dialog when button is touched': function( editor ) { + assertTouchEnd( editorBots[ editor.name ], editor ); + }, + + 'test does not force dialog when button is clicked': function( editor ) { + assertClick( editorBots[ editor.name ], editor ); + } + }; + + bender.test( + bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ) ); +}() ); From 1e3d648e2a50cd76106e9dcd7a8d0836e368ef83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Fri, 15 Dec 2017 14:05:26 +0100 Subject: [PATCH 589/642] Tests: context menu unit tests. --- tests/plugins/contextmenu/integration.js | 113 +++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 tests/plugins/contextmenu/integration.js diff --git a/tests/plugins/contextmenu/integration.js b/tests/plugins/contextmenu/integration.js new file mode 100644 index 00000000000..576774f2fa0 --- /dev/null +++ b/tests/plugins/contextmenu/integration.js @@ -0,0 +1,113 @@ +/* bender-tags: editor */ +/* bender-ckeditor-plugins: clipboard,contextmenu */ + +( function() { + 'use strict'; + + bender.editor = true; + + bender.test( { + 'test getItemByCommandName - not rendered menu': function() { + assert.isNull( this.editor.contextMenu.findItemByCommandName( 'paste' ) ); + }, + + 'test getItemByCommandName - opened menu': function() { + bender.editorBot.create( { + name: 'editor_cm1' + }, function( bot ) { + var editor = bot.editor; + + editor.once( 'menuShow', function() { + resume( function() { + var item = editor.contextMenu.findItemByCommandName( 'paste' ); + assert.isObject( item ); + assert.isTrue( item.item instanceof CKEDITOR.menuItem, 'Holds CKEDITOR.menuItem under item' ); + assert.isTrue( item.element instanceof CKEDITOR.dom.element, 'Holds CKEDITOR.dom.element under element' ); + + assert.isNull( editor.contextMenu.findItemByCommandName( 'non-existent-item' ), 'Null for non-existing item' ); + } ); + } ); + + editor.contextMenu.open( editor.editable() ); + + wait(); + } ); + }, + + 'test getItemByCommandName - closed menu': function() { + bender.editorBot.create( { + name: 'editor_cm2' + }, function( bot ) { + var editor = bot.editor; + + editor.once( 'menuShow', function() { + editor.contextMenu.hide(); + } ); + + editor.once( 'panelHide', function() { + resume( function() { + var item = editor.contextMenu.findItemByCommandName( 'paste' ); + assert.isObject( item ); + assert.isTrue( item.item instanceof CKEDITOR.menuItem, 'Holds CKEDITOR.menuItem under item' ); + assert.isTrue( item.element instanceof CKEDITOR.dom.element, 'Holds CKEDITOR.dom.element under element' ); + + assert.isNull( editor.contextMenu.findItemByCommandName( 'non-existent-item' ), 'Null for non-existing item' ); + } ); + } ); + + editor.contextMenu.open( editor.editable() ); + + wait(); + } ); + }, + + 'test getItemByCommandName - reopened menu': function() { + bender.editorBot.create( { + name: 'editor_cm3' + }, function( bot ) { + var editor = bot.editor, + item1, + item2; + + editor.once( 'menuShow', function() { + item1 = editor.contextMenu.findItemByCommandName( 'paste' ); + editor.contextMenu.hide(); + } ); + + editor.once( 'panelHide', function() { + + editor.once( 'menuShow', function() { + resume( function() { + item2 = editor.contextMenu.findItemByCommandName( 'paste' ); + assert.areSame( item1.item, item2.item, 'Menu item is the same' ); + assert.areNotSame( item1.element, item2.element, 'Element is updated' ); + } ); + } ); + + editor.contextMenu.open( editor.editable() ); + } ); + + editor.contextMenu.open( editor.editable() ); + + wait(); + } ); + }, + + 'test "menuShow" event params': function() { + bender.editorBot.create( { + name: 'editor_cm4' + }, function( bot ) { + bot.editor.on( 'menuShow', function( evt ) { + resume( function() { + assert.isTrue( evt.data[ 0 ] instanceof CKEDITOR.ui.floatPanel, 'CKEDITOR.ui.panel available' ); + assert.isTrue( evt.data.menu instanceof CKEDITOR.menu, 'CKEDITOR.menu available' ); + } ); + } ); + + bot.editor.contextMenu.open( bot.editor.editable() ); + + wait(); + } ); + } + } ); +} )(); From 53fa754095bb1d16f60da115585928898146741c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Mon, 18 Dec 2017 14:11:05 +0100 Subject: [PATCH 590/642] Tests: fix unit tests for IE/Edge. --- tests/plugins/clipboard/mobilefix.js | 14 ++++++++++++++ tests/plugins/clipboard/mobilefixcontextmenu.js | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/plugins/clipboard/mobilefix.js b/tests/plugins/clipboard/mobilefix.js index d5893d0ec7b..addfa4710ac 100644 --- a/tests/plugins/clipboard/mobilefix.js +++ b/tests/plugins/clipboard/mobilefix.js @@ -62,6 +62,11 @@ buttonElement.fire( 'touchend' ); buttonElement.$.click(); + if ( CKEDITOR.env.edge ) { + // Trigger Paste command directly as button click does not trigger it on Edge. + editor.execCommand( 'paste' ); + } + wait(); } @@ -87,6 +92,10 @@ }, 'test force dialog when button is touched': function( editor ) { + if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) { + // Ignore `touchend` tests for IE as there is not paste dialog due to different flow. + assert.ignore(); + } assertTouchEnd( editor, 'Paste' ); }, @@ -98,6 +107,11 @@ tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests ); tests[ 'test add custom paste button' ] = function() { + if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) { + // Ignore for IE as there is not paste dialog due to different flow. + assert.ignore(); + } + bender.editorBot.create( { name: 'custom_button', config: { diff --git a/tests/plugins/clipboard/mobilefixcontextmenu.js b/tests/plugins/clipboard/mobilefixcontextmenu.js index 9cec2e58fc7..ce0cdca96ca 100644 --- a/tests/plugins/clipboard/mobilefixcontextmenu.js +++ b/tests/plugins/clipboard/mobilefixcontextmenu.js @@ -56,6 +56,10 @@ }, null, null, 999 ); menuItem.element.fire( 'touchend' ); + if ( CKEDITOR.env.edge ) { + // Trigger Paste command directly as button click does not trigger it on Edge. + editor.execCommand( 'paste' ); + } menuItem.element.$.click(); wait(); @@ -70,10 +74,17 @@ menuItem.element.once( 'click', function() { assert.isFalse( editor._.forcePasteDialog, 'Forcing paste dialog' ); - assert.areSame( 1, notificationSpy.callCount, 'Notification shown' ); + if ( !CKEDITOR.env.ie || CKEDITOR.env.edge ) { + // There are no paste notifications on IE browsers. + assert.areSame( 1, notificationSpy.callCount, 'Notification shown' ); + } notificationSpy.restore(); }, null, null, 999 ); + if ( CKEDITOR.env.edge ) { + // Trigger Paste command directly as button click does not trigger it on Edge. + editor.execCommand( 'paste' ); + } menuItem.element.$.click(); } ); } @@ -91,6 +102,10 @@ }, 'test force dialog when button is touched': function( editor ) { + if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) { + // Ignore `touchend` tests for IE as there is not paste dialog due to different flow. + assert.ignore(); + } assertTouchEnd( editorBots[ editor.name ], editor ); }, From 0029403a508fd2bb5f648baad8cb3aca3c217022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Mon, 18 Dec 2017 15:21:37 +0100 Subject: [PATCH 591/642] Tests: manual tests adjustments. --- tests/plugins/clipboard/manual/pastedialogmenumobile.html | 5 +++++ tests/plugins/clipboard/manual/pastedialogmenumobile.md | 3 ++- tests/plugins/clipboard/manual/pastedialogmobile.md | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/plugins/clipboard/manual/pastedialogmenumobile.html b/tests/plugins/clipboard/manual/pastedialogmenumobile.html index 934a62c6aee..46459623aa7 100644 --- a/tests/plugins/clipboard/manual/pastedialogmenumobile.html +++ b/tests/plugins/clipboard/manual/pastedialogmenumobile.html @@ -10,6 +10,11 @@ + \ No newline at end of file From 5817a2d510ebc821b189e7e840e037ff7292b131 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 8 Feb 2018 10:46:23 +0100 Subject: [PATCH 597/642] Tests: moved CSS from a manual test into a dedicated stylesheet. --- tests/plugins/easyimage/manual/_assets/progress.css | 4 ++++ tests/plugins/easyimage/manual/customprogressbar.html | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/plugins/easyimage/manual/_assets/progress.css b/tests/plugins/easyimage/manual/_assets/progress.css index eeb6e0aa04c..c3e1addd213 100644 --- a/tests/plugins/easyimage/manual/_assets/progress.css +++ b/tests/plugins/easyimage/manual/_assets/progress.css @@ -13,6 +13,10 @@ transition: height 0.1s; } +.cke_widget_wrapper_easyimage.cke_widget_wrapper_uploading.cke_skip_uploading figure img { + opacity: 1; +} + /* Circle prgoress indicator */ .cke_progress_circle { diff --git a/tests/plugins/easyimage/manual/customprogressbar.html b/tests/plugins/easyimage/manual/customprogressbar.html index 116aa826afa..ccd7278b32b 100644 --- a/tests/plugins/easyimage/manual/customprogressbar.html +++ b/tests/plugins/easyimage/manual/customprogressbar.html @@ -28,8 +28,6 @@

Overlapping progress reporter

bender.ignore(); } - CKEDITOR.addCss( '.cke_widget_wrapper_easyimage.cke_widget_wrapper_uploading.cke_skip_uploading figure img { opacity: 1; }' ); - var commonConfig = { cloudServices_url: easyImageTools.CLOUD_SERVICES_UPLOAD_GATEWAY, contentsCss: [ '%TEST_DIR%/_assets/progress.css' ], From 9c77e3b81a2b2a0dac7614c72b00476168fc42a6 Mon Sep 17 00:00:00 2001 From: Kajetan Litwinowicz Date: Wed, 7 Feb 2018 12:59:02 +0100 Subject: [PATCH 598/642] Fixed: Paste notification isn't very straightforward and it might confuse users --- CHANGES.md | 1 + tests/plugins/clipboard/manual/pastenotification.md | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 6214f9cafcc..d81f980019d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -30,6 +30,7 @@ Fixed Issues: * [#1535](https://github.com/ckeditor/ckeditor-dev/issues/1535): Fixed: Improve [Widget](https://ckeditor.com/cke4/addon/widget) mouse over border contrast. * [#1516](https://github.com/ckeditor/ckeditor-dev/issues/1516): Fixed: Fake selection allows removing in a readonly mode using `Backspace`/`Delete` keys. * [#1570](https://github.com/ckeditor/ckeditor-dev/issues/1570): Fixed: Fake selection allows cutting in a readonly mode using `Ctrl`/`Cmd` + `X` keys. +* [#1363](https://github.com/ckeditor/ckeditor-dev/issues/1363): Fixed: Paste notification isn't very straightforward and it might confuse users. API Changes: diff --git a/tests/plugins/clipboard/manual/pastenotification.md b/tests/plugins/clipboard/manual/pastenotification.md index d3169ebdffc..3ee63c0bafd 100644 --- a/tests/plugins/clipboard/manual/pastenotification.md +++ b/tests/plugins/clipboard/manual/pastenotification.md @@ -1,4 +1,4 @@ -@bender-tags: bug, 4.7.0, tp2098 +@bender-tags: bug, 4.7.0, tp2098, 4.9.0, 1363 @bender-ui: collapsed @bender-ckeditor-plugins: wysiwygarea, toolbar, clipboard, pastefromword, pastetext @@ -6,7 +6,9 @@ 2. Repeat it for "Paste from Word" and "Paste as plain text" #### Expected result: -* For "Paste" and "Paste from Word" the notification is shown mentioning "Cmd/Ctrl+V" keystroke. +* For each button the notification is shown: + * Press `keystroke` to paste. Your browser doesn't support pasting with the toolbar button or context menu option. +* For "Paste" and "Paste from Word" the notification keystroke is "Cmd/Ctrl+V". * For "Paste as plain text" the notification is shown mentioning: * `Cmd+Alt+Shift+V` keystroke in Safari; * `Ctrl+V` keystroke in Edge and IE; From 2f4425f8cde6f822ede2c0613a33bd2fe708944b Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Wed, 7 Feb 2018 15:32:01 +0100 Subject: [PATCH 599/642] Update manual test description. --- tests/plugins/clipboard/manual/pastenotification.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plugins/clipboard/manual/pastenotification.md b/tests/plugins/clipboard/manual/pastenotification.md index 3ee63c0bafd..3c6638b866d 100644 --- a/tests/plugins/clipboard/manual/pastenotification.md +++ b/tests/plugins/clipboard/manual/pastenotification.md @@ -7,8 +7,8 @@ #### Expected result: * For each button the notification is shown: - * Press `keystroke` to paste. Your browser doesn't support pasting with the toolbar button or context menu option. -* For "Paste" and "Paste from Word" the notification keystroke is "Cmd/Ctrl+V". + > Press `keystroke` to paste. Your browser doesn't support pasting with the toolbar button or context menu option. +* For "Paste" and "Paste from Word" the notification keystroke is `Cmd/Ctrl+V`. * For "Paste as plain text" the notification is shown mentioning: * `Cmd+Alt+Shift+V` keystroke in Safari; * `Ctrl+V` keystroke in Edge and IE; From d8ea19a101eb89e1fbd239aa231f84fd4cdf41fa Mon Sep 17 00:00:00 2001 From: Kajetan Litwinowicz Date: Thu, 8 Feb 2018 10:36:13 +0100 Subject: [PATCH 600/642] Fixed text files after rebase --- plugins/clipboard/lang/af.js | 2 +- plugins/clipboard/lang/ar.js | 2 +- plugins/clipboard/lang/az.js | 2 +- plugins/clipboard/lang/bg.js | 2 +- plugins/clipboard/lang/bn.js | 2 +- plugins/clipboard/lang/bs.js | 2 +- plugins/clipboard/lang/ca.js | 2 +- plugins/clipboard/lang/cs.js | 2 +- plugins/clipboard/lang/cy.js | 2 +- plugins/clipboard/lang/da.js | 2 +- plugins/clipboard/lang/de-ch.js | 2 +- plugins/clipboard/lang/de.js | 2 +- plugins/clipboard/lang/el.js | 2 +- plugins/clipboard/lang/en-au.js | 2 +- plugins/clipboard/lang/en-ca.js | 2 +- plugins/clipboard/lang/en-gb.js | 2 +- plugins/clipboard/lang/en.js | 2 +- plugins/clipboard/lang/eo.js | 2 +- plugins/clipboard/lang/es-mx.js | 2 +- plugins/clipboard/lang/es.js | 2 +- plugins/clipboard/lang/et.js | 2 +- plugins/clipboard/lang/eu.js | 2 +- plugins/clipboard/lang/fa.js | 2 +- plugins/clipboard/lang/fi.js | 2 +- plugins/clipboard/lang/fo.js | 2 +- plugins/clipboard/lang/fr-ca.js | 2 +- plugins/clipboard/lang/fr.js | 2 +- plugins/clipboard/lang/gl.js | 2 +- plugins/clipboard/lang/gu.js | 2 +- plugins/clipboard/lang/he.js | 2 +- plugins/clipboard/lang/hi.js | 2 +- plugins/clipboard/lang/hr.js | 2 +- plugins/clipboard/lang/hu.js | 2 +- plugins/clipboard/lang/id.js | 2 +- plugins/clipboard/lang/is.js | 2 +- plugins/clipboard/lang/it.js | 2 +- plugins/clipboard/lang/ja.js | 2 +- plugins/clipboard/lang/ka.js | 2 +- plugins/clipboard/lang/km.js | 2 +- plugins/clipboard/lang/ko.js | 2 +- plugins/clipboard/lang/ku.js | 2 +- plugins/clipboard/lang/lt.js | 2 +- plugins/clipboard/lang/lv.js | 2 +- plugins/clipboard/lang/mk.js | 2 +- plugins/clipboard/lang/mn.js | 2 +- plugins/clipboard/lang/ms.js | 2 +- plugins/clipboard/lang/nb.js | 2 +- plugins/clipboard/lang/nl.js | 2 +- plugins/clipboard/lang/no.js | 2 +- plugins/clipboard/lang/oc.js | 2 +- plugins/clipboard/lang/pl.js | 2 +- plugins/clipboard/lang/pt-br.js | 2 +- plugins/clipboard/lang/pt.js | 2 +- plugins/clipboard/lang/ro.js | 2 +- plugins/clipboard/lang/ru.js | 2 +- plugins/clipboard/lang/si.js | 2 +- plugins/clipboard/lang/sk.js | 2 +- plugins/clipboard/lang/sl.js | 2 +- plugins/clipboard/lang/sq.js | 2 +- plugins/clipboard/lang/sr-latn.js | 2 +- plugins/clipboard/lang/sr.js | 2 +- plugins/clipboard/lang/sv.js | 2 +- plugins/clipboard/lang/th.js | 2 +- plugins/clipboard/lang/tr.js | 2 +- plugins/clipboard/lang/tt.js | 2 +- plugins/clipboard/lang/ug.js | 2 +- plugins/clipboard/lang/uk.js | 2 +- plugins/clipboard/lang/vi.js | 2 +- plugins/clipboard/lang/zh-cn.js | 2 +- plugins/clipboard/lang/zh.js | 2 +- plugins/pastetext/lang/af.js | 2 +- plugins/pastetext/lang/ar.js | 2 +- plugins/pastetext/lang/az.js | 2 +- plugins/pastetext/lang/bg.js | 2 +- plugins/pastetext/lang/bn.js | 2 +- plugins/pastetext/lang/bs.js | 2 +- plugins/pastetext/lang/ca.js | 2 +- plugins/pastetext/lang/cs.js | 2 +- plugins/pastetext/lang/cy.js | 2 +- plugins/pastetext/lang/da.js | 2 +- plugins/pastetext/lang/de-ch.js | 2 +- plugins/pastetext/lang/de.js | 2 +- plugins/pastetext/lang/el.js | 2 +- plugins/pastetext/lang/en-au.js | 2 +- plugins/pastetext/lang/en-ca.js | 2 +- plugins/pastetext/lang/en-gb.js | 2 +- plugins/pastetext/lang/en.js | 2 +- plugins/pastetext/lang/eo.js | 2 +- plugins/pastetext/lang/es-mx.js | 2 +- plugins/pastetext/lang/es.js | 2 +- plugins/pastetext/lang/et.js | 2 +- plugins/pastetext/lang/eu.js | 2 +- plugins/pastetext/lang/fa.js | 2 +- plugins/pastetext/lang/fi.js | 2 +- plugins/pastetext/lang/fo.js | 2 +- plugins/pastetext/lang/fr-ca.js | 2 +- plugins/pastetext/lang/fr.js | 2 +- plugins/pastetext/lang/gl.js | 2 +- plugins/pastetext/lang/gu.js | 2 +- plugins/pastetext/lang/he.js | 2 +- plugins/pastetext/lang/hi.js | 2 +- plugins/pastetext/lang/hr.js | 2 +- plugins/pastetext/lang/hu.js | 2 +- plugins/pastetext/lang/id.js | 2 +- plugins/pastetext/lang/is.js | 2 +- plugins/pastetext/lang/it.js | 2 +- plugins/pastetext/lang/ja.js | 2 +- plugins/pastetext/lang/ka.js | 2 +- plugins/pastetext/lang/km.js | 2 +- plugins/pastetext/lang/ko.js | 2 +- plugins/pastetext/lang/ku.js | 2 +- plugins/pastetext/lang/lt.js | 2 +- plugins/pastetext/lang/lv.js | 2 +- plugins/pastetext/lang/mk.js | 2 +- plugins/pastetext/lang/mn.js | 2 +- plugins/pastetext/lang/ms.js | 2 +- plugins/pastetext/lang/nb.js | 2 +- plugins/pastetext/lang/nl.js | 2 +- plugins/pastetext/lang/no.js | 2 +- plugins/pastetext/lang/oc.js | 2 +- plugins/pastetext/lang/pl.js | 2 +- plugins/pastetext/lang/pt-br.js | 2 +- plugins/pastetext/lang/pt.js | 2 +- plugins/pastetext/lang/ro.js | 2 +- plugins/pastetext/lang/ru.js | 2 +- plugins/pastetext/lang/si.js | 2 +- plugins/pastetext/lang/sk.js | 2 +- plugins/pastetext/lang/sl.js | 2 +- plugins/pastetext/lang/sq.js | 2 +- plugins/pastetext/lang/sr-latn.js | 2 +- plugins/pastetext/lang/sr.js | 2 +- plugins/pastetext/lang/sv.js | 2 +- plugins/pastetext/lang/th.js | 2 +- plugins/pastetext/lang/tr.js | 2 +- plugins/pastetext/lang/tt.js | 2 +- plugins/pastetext/lang/ug.js | 2 +- plugins/pastetext/lang/uk.js | 2 +- plugins/pastetext/lang/vi.js | 2 +- plugins/pastetext/lang/zh-cn.js | 2 +- plugins/pastetext/lang/zh.js | 2 +- 140 files changed, 140 insertions(+), 140 deletions(-) diff --git a/plugins/clipboard/lang/af.js b/plugins/clipboard/lang/af.js index dd222d8d82c..509885fa25d 100644 --- a/plugins/clipboard/lang/af.js +++ b/plugins/clipboard/lang/af.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'af', { cut: 'Knip', cutError: 'U blaaier se sekuriteitsinstelling belet die outomatiese knip-aksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+X).', paste: 'Plak', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Plak-area', pasteMsg: 'Plak die teks in die volgende teks-area met die sleutelbordkombinasie (Ctrl/Cmd+V) en druk OK.', title: 'Byvoeg' diff --git a/plugins/clipboard/lang/ar.js b/plugins/clipboard/lang/ar.js index 8fc696a15fa..248ab4beb0f 100644 --- a/plugins/clipboard/lang/ar.js +++ b/plugins/clipboard/lang/ar.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ar', { cut: 'قص', cutError: 'الإعدادات الأمنية للمتصفح الذي تستخدمه تمنع القص التلقائي. فضلاً إستخدم لوحة المفاتيح لفعل ذلك (Ctrl/Cmd+X).', paste: 'لصق', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'منطقة اللصق', pasteMsg: 'الصق داخل الصندوق بإستخدام زرائر (Ctrl/Cmd+V) في لوحة المفاتيح، ثم اضغط زر موافق.', title: 'لصق' diff --git a/plugins/clipboard/lang/az.js b/plugins/clipboard/lang/az.js index 7cfcc8ac703..fe64171144c 100644 --- a/plugins/clipboard/lang/az.js +++ b/plugins/clipboard/lang/az.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'az', { cut: 'Kəs', cutError: 'Avtomatik kəsmə mümkün deyil. Ctrl+X basın.', paste: 'Əlavə et', - pasteNotification: 'Sizin İnternet bələdçisi bu cür mətnin köçürməsi dəstəklənmir. Əlavə etmək üçün %1 basın.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING title: 'Paste' // MISSING diff --git a/plugins/clipboard/lang/bg.js b/plugins/clipboard/lang/bg.js index d6bc07a8f07..81ceb7fd118 100644 --- a/plugins/clipboard/lang/bg.js +++ b/plugins/clipboard/lang/bg.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'bg', { cut: 'Отрежи', cutError: 'Настройките за сигурност на Вашия браузър не позволяват на редактора автоматично да изъплни действията за отрязване. Моля ползвайте клавиатурните команди за целта (ctrl+x).', paste: 'Вмъкни', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Зона за вмъкване', pasteMsg: 'Вмъкнете тук съдъжанието с клавиатуарата (Ctrl/Cmd+V) и натиснете OK.', title: 'Вмъкни' diff --git a/plugins/clipboard/lang/bn.js b/plugins/clipboard/lang/bn.js index 19ee8754e71..fdd98549b7c 100644 --- a/plugins/clipboard/lang/bn.js +++ b/plugins/clipboard/lang/bn.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'bn', { cut: 'কাট', cutError: 'আপনার ব্রাউজারের সুরক্ষা সেটিংস এডিটরকে অটোমেটিক কাট করার অনুমতি দেয়নি। দয়া করে এই কাজের জন্য কিবোর্ড ব্যবহার করুন (Ctrl/Cmd+X)।', paste: 'পেস্ট', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: 'অনুগ্রহ করে নীচের বাক্সে কিবোর্ড ব্যবহার করে (Ctrl/Cmd+V) পেস্ট করুন এবং OK চাপ দিন', title: 'পেস্ট' diff --git a/plugins/clipboard/lang/bs.js b/plugins/clipboard/lang/bs.js index a1aae54324e..6c750ab6018 100644 --- a/plugins/clipboard/lang/bs.js +++ b/plugins/clipboard/lang/bs.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'bs', { cut: 'Izreži', cutError: 'Sigurnosne postavke vašeg pretraživaèa ne dozvoljavaju operacije automatskog rezanja. Molimo koristite kraticu na tastaturi (Ctrl/Cmd+X).', paste: 'Zalijepi', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING title: 'Zalijepi' diff --git a/plugins/clipboard/lang/ca.js b/plugins/clipboard/lang/ca.js index cfcd204ea8a..8382819fc03 100644 --- a/plugins/clipboard/lang/ca.js +++ b/plugins/clipboard/lang/ca.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ca', { cut: 'Retallar', cutError: 'La configuració de seguretat del vostre navegador no permet executar automàticament les operacions de retallar. Si us plau, utilitzeu el teclat (Ctrl/Cmd+X).', paste: 'Enganxar', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Àrea d\'enganxat', pasteMsg: 'Si us plau, enganxi dins del següent camp utilitzant el teclat (Ctrl/Cmd+V) i premi OK.', title: 'Enganxar' diff --git a/plugins/clipboard/lang/cs.js b/plugins/clipboard/lang/cs.js index 0d44f860cea..a9576e66b52 100644 --- a/plugins/clipboard/lang/cs.js +++ b/plugins/clipboard/lang/cs.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'cs', { cut: 'Vyjmout', cutError: 'Bezpečnostní nastavení vašeho prohlížeče nedovolují editoru spustit funkci pro vyjmutí zvoleného textu do schránky. Prosím vyjměte zvolený text do schránky pomocí klávesnice (Ctrl/Cmd+X).', paste: 'Vložit', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Oblast vkládání', pasteMsg: 'Do následujícího pole vložte požadovaný obsah pomocí klávesnice (Ctrl/Cmd+V) a stiskněte OK.', title: 'Vložit' diff --git a/plugins/clipboard/lang/cy.js b/plugins/clipboard/lang/cy.js index 95866034b8f..75a204aa732 100644 --- a/plugins/clipboard/lang/cy.js +++ b/plugins/clipboard/lang/cy.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'cy', { cut: 'Torri', cutError: 'Nid yw gosodiadau diogelwch eich porwr yn caniatàu\'r golygydd i gynnal \'gweithredoedd torri\' yn awtomatig. Defnyddiwch y bysellfwrdd (Ctrl/Cmd+X).', paste: 'Gludo', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Ardal Gludo', pasteMsg: 'Gludwch i mewn i\'r blwch canlynol gan ddefnyddio\'r bysellfwrdd (Ctrl/Cmd+V) a phwyso Iawn.', title: 'Gludo' diff --git a/plugins/clipboard/lang/da.js b/plugins/clipboard/lang/da.js index 9077c52e294..372109457c9 100644 --- a/plugins/clipboard/lang/da.js +++ b/plugins/clipboard/lang/da.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'da', { cut: 'Klip', cutError: 'Din browsers sikkerhedsindstillinger tillader ikke editoren at få automatisk adgang til udklipsholderen.

Brug i stedet tastaturet til at klippe teksten (Ctrl/Cmd+X).', paste: 'Indsæt', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Indsæt område', pasteMsg: 'Indsæt i feltet herunder (Ctrl/Cmd+V) og klik på OK.', title: 'Indsæt' diff --git a/plugins/clipboard/lang/de-ch.js b/plugins/clipboard/lang/de-ch.js index e5505e43b86..62a204e1340 100644 --- a/plugins/clipboard/lang/de-ch.js +++ b/plugins/clipboard/lang/de-ch.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'de-ch', { cut: 'Ausschneiden', cutError: 'Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).', paste: 'Einfügen', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Einfügebereich', pasteMsg: 'Bitte fügen Sie den Text in der folgenden Box über die Tastatur (mit Strg+V) ein und bestätigen Sie mit OK.', title: 'Einfügen' diff --git a/plugins/clipboard/lang/de.js b/plugins/clipboard/lang/de.js index fbd924f71e7..7410b59c64e 100644 --- a/plugins/clipboard/lang/de.js +++ b/plugins/clipboard/lang/de.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'de', { cut: 'Ausschneiden', cutError: 'Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).', paste: 'Einfügen', - pasteNotification: 'Ihr Browser verhindert das Einfügen über diesen Weg. Zum einfügen drücken Sie %1.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Einfügebereich', pasteMsg: 'Bitte fügen Sie den Text in der folgenden Box über die Tastatur (mit Strg+V) ein und bestätigen Sie mit OK.', title: 'Einfügen' diff --git a/plugins/clipboard/lang/el.js b/plugins/clipboard/lang/el.js index 9f61627a1d6..5e005051831 100644 --- a/plugins/clipboard/lang/el.js +++ b/plugins/clipboard/lang/el.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'el', { cut: 'Αποκοπή', cutError: 'Οι ρυθμίσεις ασφαλείας του περιηγητή σας δεν επιτρέπουν την επιλεγμένη εργασία αποκοπής. Παρακαλώ χρησιμοποιείστε το πληκτρολόγιο (Ctrl/Cmd+X).', paste: 'Επικόλληση', - pasteNotification: 'Ο περιηγητής σας δεν σας επιτρέπει να επικολλήσετε με αυτόν τον τρόπο. Πατήστε %1 για επικόλληση.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Περιοχή Επικόλλησης', pasteMsg: 'Παρακαλώ επικολλήστε στο ακόλουθο κουτί χρησιμοποιώντας το πληκτρολόγιο (Ctrl/Cmd+V) και πατήστε OK.', title: 'Επικόλληση' diff --git a/plugins/clipboard/lang/en-au.js b/plugins/clipboard/lang/en-au.js index b05700d98b5..4dd6aad6b77 100644 --- a/plugins/clipboard/lang/en-au.js +++ b/plugins/clipboard/lang/en-au.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en-au', { cut: 'Cut', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', paste: 'Paste', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', title: 'Paste' diff --git a/plugins/clipboard/lang/en-ca.js b/plugins/clipboard/lang/en-ca.js index 3df1af6d434..d1047681409 100644 --- a/plugins/clipboard/lang/en-ca.js +++ b/plugins/clipboard/lang/en-ca.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en-ca', { cut: 'Cut', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', paste: 'Paste', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', title: 'Paste' diff --git a/plugins/clipboard/lang/en-gb.js b/plugins/clipboard/lang/en-gb.js index e1595ace7c2..5d8a5b7e13a 100644 --- a/plugins/clipboard/lang/en-gb.js +++ b/plugins/clipboard/lang/en-gb.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en-gb', { cut: 'Cut', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', paste: 'Paste', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', title: 'Paste' diff --git a/plugins/clipboard/lang/en.js b/plugins/clipboard/lang/en.js index e0643d43dcf..06bd83dbd48 100644 --- a/plugins/clipboard/lang/en.js +++ b/plugins/clipboard/lang/en.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'en', { cut: 'Cut', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', paste: 'Paste', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', pasteArea: 'Paste Area', pasteMsg: 'Please paste inside the following box and hit OK', title: 'Paste' diff --git a/plugins/clipboard/lang/eo.js b/plugins/clipboard/lang/eo.js index 18044886a57..380d25b2370 100644 --- a/plugins/clipboard/lang/eo.js +++ b/plugins/clipboard/lang/eo.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'eo', { cut: 'Eltondi', cutError: 'La sekurecagordo de via TTT-legilo ne permesas, ke la redaktilo faras eltondajn operaciojn. Bonvolu uzi la klavaron por tio (Ctrl/Cmd-X).', paste: 'Interglui', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Intergluoareo', pasteMsg: 'Bonvolu glui la tekston en la jenan areon per uzado de la klavaro (Ctrl/Cmd+V) kaj premu OK', title: 'Interglui' diff --git a/plugins/clipboard/lang/es-mx.js b/plugins/clipboard/lang/es-mx.js index affb7f77940..6ae2d20f172 100644 --- a/plugins/clipboard/lang/es-mx.js +++ b/plugins/clipboard/lang/es-mx.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'es-mx', { cut: 'Cortar', cutError: 'La configuración de seguridad de su navegador no permite al editor ejecutar automáticamente operaciones de corte. Por favor, utilice el teclado para (Ctrl/Cmd+X).', paste: 'Pegar', - pasteNotification: 'Tu navegador no permite pegar de esta manera. Presiona %1 para pegar.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING title: 'Paste' // MISSING diff --git a/plugins/clipboard/lang/es.js b/plugins/clipboard/lang/es.js index 1539eb481a5..a804cfb7d71 100644 --- a/plugins/clipboard/lang/es.js +++ b/plugins/clipboard/lang/es.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'es', { cut: 'Cortar', cutError: 'La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de cortado.\r\nPor favor use el teclado (Ctrl/Cmd+X).', paste: 'Pegar', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Zona de pegado', pasteMsg: 'Por favor pegue dentro del cuadro utilizando el teclado (Ctrl/Cmd+V);\r\nluego presione Aceptar.', title: 'Pegar' diff --git a/plugins/clipboard/lang/et.js b/plugins/clipboard/lang/et.js index 933123417a1..acd38103293 100644 --- a/plugins/clipboard/lang/et.js +++ b/plugins/clipboard/lang/et.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'et', { cut: 'Lõika', cutError: 'Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt lõigata. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+X).', paste: 'Aseta', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Asetamise ala', pasteMsg: 'Palun aseta tekst järgnevasse kasti kasutades klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+V) ja vajuta seejärel OK.', title: 'Asetamine' diff --git a/plugins/clipboard/lang/eu.js b/plugins/clipboard/lang/eu.js index cb6388a3b13..d53cae06929 100644 --- a/plugins/clipboard/lang/eu.js +++ b/plugins/clipboard/lang/eu.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'eu', { cut: 'Ebaki', cutError: 'Zure web nabigatzailearen segurtasun ezarpenek ez dute baimentzen testuak automatikoki moztea. Mesedez teklatua erabil ezazu (Ctrl/Cmd+X).', paste: 'Itsatsi', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Itsasteko area', pasteMsg: 'Mesedez teklatua erabiliz (Ctrl/Cmd+V) ondorengo eremuan testua itsatsi eta sakatu Ados.', title: 'Itsatsi' diff --git a/plugins/clipboard/lang/fa.js b/plugins/clipboard/lang/fa.js index 8bc938e620f..ae25d1527ba 100644 --- a/plugins/clipboard/lang/fa.js +++ b/plugins/clipboard/lang/fa.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fa', { cut: 'برش', cutError: 'تنظیمات امنیتی مرورگر شما اجازه نمیدهد که ویرایشگر به طور خودکار عملکردهای برش را انجام دهد. لطفا با دکمههای صفحه کلید این کار را انجام دهید (Ctrl/Cmd+X).', paste: 'چسباندن', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'محل چسباندن', pasteMsg: 'لطفا متن را با کلیدهای (Ctrl/Cmd+V) در این جعبهٴ متنی بچسبانید و پذیرش را بزنید.', title: 'چسباندن' diff --git a/plugins/clipboard/lang/fi.js b/plugins/clipboard/lang/fi.js index 01980e6111c..ad88755618e 100644 --- a/plugins/clipboard/lang/fi.js +++ b/plugins/clipboard/lang/fi.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fi', { cut: 'Leikkaa', cutError: 'Selaimesi turva-asetukset eivät salli editorin toteuttaa leikkaamista. Käytä näppäimistöä leikkaamiseen (Ctrl+X).', paste: 'Liitä', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Leikealue', pasteMsg: 'Liitä painamalla (Ctrl+V) ja painamalla OK.', title: 'Liitä' diff --git a/plugins/clipboard/lang/fo.js b/plugins/clipboard/lang/fo.js index a8df006b955..df5c3339428 100644 --- a/plugins/clipboard/lang/fo.js +++ b/plugins/clipboard/lang/fo.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fo', { cut: 'Kvett', cutError: 'Trygdaruppseting alnótskagans forðar tekstviðgeranum í at kvetta tekstin. Vinarliga nýt knappaborðið til at kvetta tekstin (Ctrl/Cmd+X).', paste: 'Innrita', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Avritingarumráði', pasteMsg: 'Vinarliga koyr tekstin í hendan rútin við knappaborðinum (Ctrl/Cmd+V) og klikk á Góðtak.', title: 'Innrita' diff --git a/plugins/clipboard/lang/fr-ca.js b/plugins/clipboard/lang/fr-ca.js index 1064c3abcf7..4660f86e1d8 100644 --- a/plugins/clipboard/lang/fr-ca.js +++ b/plugins/clipboard/lang/fr-ca.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fr-ca', { cut: 'Couper', cutError: 'Les paramètres de sécurité de votre navigateur empêchent l\'éditeur de couper automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl/Cmd+X).', paste: 'Coller', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Coller la zone', pasteMsg: 'Veuillez coller dans la zone ci-dessous en utilisant le clavier (Ctrl/Cmd+V) et appuyer sur OK.', title: 'Coller' diff --git a/plugins/clipboard/lang/fr.js b/plugins/clipboard/lang/fr.js index fef154c7f28..71373521226 100644 --- a/plugins/clipboard/lang/fr.js +++ b/plugins/clipboard/lang/fr.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'fr', { cut: 'Couper', cutError: 'Les paramètres de sécurité de votre navigateur n\'autorisent pas l\'éditeur à exécuter automatiquement l\'opération « Couper ». Veuillez utiliser le raccourci clavier à cet effet (Ctrl/Cmd+X).', paste: 'Coller', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Coller la zone', pasteMsg: 'Veuillez coller le texte dans la zone suivante en utilisant le raccourci clavier (Ctrl/Cmd+V) et cliquez sur OK.', title: 'Coller' diff --git a/plugins/clipboard/lang/gl.js b/plugins/clipboard/lang/gl.js index e34434715b0..1edf8eefcbd 100644 --- a/plugins/clipboard/lang/gl.js +++ b/plugins/clipboard/lang/gl.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'gl', { cut: 'Cortar', cutError: 'Os axustes de seguranza do seu navegador non permiten que o editor realice automaticamente as tarefas de corte. Use o teclado para iso (Ctrl/Cmd+X).', paste: 'Pegar', - pasteNotification: 'O seu navegador non permite pegar deste xeito. Prema %1 para pegar.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Zona de pegado', pasteMsg: 'Pegue dentro do seguinte cadro usando o teclado (Ctrl/Cmd+V) e prema en Aceptar', title: 'Pegar' diff --git a/plugins/clipboard/lang/gu.js b/plugins/clipboard/lang/gu.js index 9920e44cbd8..3a7c9a311ed 100644 --- a/plugins/clipboard/lang/gu.js +++ b/plugins/clipboard/lang/gu.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'gu', { cut: 'કાપવું', cutError: 'તમારા બ્રાઉઝર ની સુરક્ષિત સેટિંગસ કટ કરવાની પરવાનગી નથી આપતી. (Ctrl/Cmd+X) નો ઉપયોગ કરો.', paste: 'પેસ્ટ', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'પેસ્ટ કરવાની જગ્યા', pasteMsg: 'Ctrl/Cmd+V નો પ્રયોગ કરી પેસ્ટ કરો', title: 'પેસ્ટ' diff --git a/plugins/clipboard/lang/he.js b/plugins/clipboard/lang/he.js index f2f17fce689..2e8c2710927 100644 --- a/plugins/clipboard/lang/he.js +++ b/plugins/clipboard/lang/he.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'he', { cut: 'גזירה', cutError: 'הגדרות האבטחה בדפדפן שלך לא מאפשרות לעורך לבצע פעולות גזירה אוטומטיות. יש להשתמש במקלדת לשם כך (Ctrl/Cmd+X).', paste: 'הדבקה', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'איזור הדבקה', pasteMsg: 'נא להדביק בתוך הקופסה באמצעות (Ctrl/Cmd+V) וללחוץ על אישור.', title: 'הדבקה' diff --git a/plugins/clipboard/lang/hi.js b/plugins/clipboard/lang/hi.js index a4f0e7602d7..9142406ba4a 100644 --- a/plugins/clipboard/lang/hi.js +++ b/plugins/clipboard/lang/hi.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'hi', { cut: 'कट', cutError: 'आपके ब्राउज़र की सुरक्षा सॅटिन्ग्स ने कट करने की अनुमति नहीं प्रदान की है। (Ctrl/Cmd+X) का प्रयोग करें।', paste: 'पेस्ट', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: 'Ctrl/Cmd+V का प्रयोग करके पेस्ट करें और ठीक है करें.', title: 'पेस्ट' diff --git a/plugins/clipboard/lang/hr.js b/plugins/clipboard/lang/hr.js index b92710441f5..5b2ffab5229 100644 --- a/plugins/clipboard/lang/hr.js +++ b/plugins/clipboard/lang/hr.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'hr', { cut: 'Izreži', cutError: 'Sigurnosne postavke Vašeg pretraživača ne dozvoljavaju operacije automatskog izrezivanja. Molimo koristite kraticu na tipkovnici (Ctrl/Cmd+X).', paste: 'Zalijepi', - pasteNotification: 'Vaš preglednik Vam ne dozvoljava lijepljenje na ovaj način. Za lijepljenje, pritisnite %1.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Prostor za ljepljenje', pasteMsg: 'Molimo zaljepite unutar doljnjeg okvira koristeći tipkovnicu (Ctrl/Cmd+V) i kliknite OK.', title: 'Zalijepi' diff --git a/plugins/clipboard/lang/hu.js b/plugins/clipboard/lang/hu.js index cba7861f7d5..a07a131eb48 100644 --- a/plugins/clipboard/lang/hu.js +++ b/plugins/clipboard/lang/hu.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'hu', { cut: 'Kivágás', cutError: 'A böngésző biztonsági beállításai nem engedélyezik a szerkesztőnek, hogy végrehajtsa a kivágás műveletet. Használja az alábbi billentyűkombinációt (Ctrl/Cmd+X).', paste: 'Beillesztés', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Beszúrás mező', pasteMsg: 'Másolja be az alábbi mezőbe a Ctrl/Cmd+V billentyűk lenyomásával, majd nyomjon Rendben-t.', title: 'Beillesztés' diff --git a/plugins/clipboard/lang/id.js b/plugins/clipboard/lang/id.js index 28a71c0eee0..7e530d756ba 100644 --- a/plugins/clipboard/lang/id.js +++ b/plugins/clipboard/lang/id.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'id', { cut: 'Potong', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', // MISSING paste: 'Tempel', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Area Tempel', pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING title: 'Tempel' diff --git a/plugins/clipboard/lang/is.js b/plugins/clipboard/lang/is.js index fe14280e4c5..07bab0b8629 100644 --- a/plugins/clipboard/lang/is.js +++ b/plugins/clipboard/lang/is.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'is', { cut: 'Klippa', cutError: 'Öryggisstillingar vafrans þíns leyfa ekki klippingu texta með músaraðgerð. Notaðu lyklaborðið í klippa (Ctrl/Cmd+X).', paste: 'Líma', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: 'Límdu í svæðið hér að neðan og (Ctrl/Cmd+V) og smelltu á OK.', title: 'Líma' diff --git a/plugins/clipboard/lang/it.js b/plugins/clipboard/lang/it.js index 14264204557..993f2b5cf42 100644 --- a/plugins/clipboard/lang/it.js +++ b/plugins/clipboard/lang/it.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'it', { cut: 'Taglia', cutError: 'Le impostazioni di sicurezza del browser non permettono di tagliare automaticamente il testo. Usa la tastiera (Ctrl/Cmd+X).', paste: 'Incolla', - pasteNotification: 'Il browser non permette di incollare in questo modo. Premere %1 per incollare.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Incolla', pasteMsg: 'Incolla il testo all\'interno dell\'area sottostante usando la scorciatoia di tastiere (Ctrl/Cmd+V) e premi OK.', title: 'Incolla' diff --git a/plugins/clipboard/lang/ja.js b/plugins/clipboard/lang/ja.js index 03ecbb76e6f..d7b611cbc1c 100644 --- a/plugins/clipboard/lang/ja.js +++ b/plugins/clipboard/lang/ja.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ja', { cut: '切り取り', cutError: 'ブラウザーのセキュリティ設定によりエディタの切り取り操作を自動で実行することができません。実行するには手動でキーボードの(Ctrl/Cmd+X)を使用してください。', paste: '貼り付け', - pasteNotification: 'ブラウザの設定によりこの方法で貼り付けることはできません。手動で実行するにはキーボードの「%1」を押してください。', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: '貼り付け場所', pasteMsg: 'キーボード(Ctrl/Cmd+V)を使用して、次の入力エリア内で貼り付けて、OKを押してください。', title: '貼り付け' diff --git a/plugins/clipboard/lang/ka.js b/plugins/clipboard/lang/ka.js index a80267e0a0a..78512c11dd0 100644 --- a/plugins/clipboard/lang/ka.js +++ b/plugins/clipboard/lang/ka.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ka', { cut: 'ამოჭრა', cutError: 'თქვენი ბროუზერის უსაფრთხოების პარამეტრები არ იძლევა ამოჭრის ოპერაციის ავტომატურად განხორციელების საშუალებას. გამოიყენეთ კლავიატურა ამისთვის (Ctrl/Cmd+X).', paste: 'ჩასმა', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'ჩასმის არე', pasteMsg: 'ჩასვით ამ არის შიგნით კლავიატურის გამოყენებით (Ctrl/Cmd+V) და დააჭირეთ OK-ს', title: 'ჩასმა' diff --git a/plugins/clipboard/lang/km.js b/plugins/clipboard/lang/km.js index 5310072917c..125941d4bd5 100644 --- a/plugins/clipboard/lang/km.js +++ b/plugins/clipboard/lang/km.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'km', { cut: 'កាត់យក', cutError: 'ការកំណត់សុវត្ថភាពរបស់កម្មវិធីរុករករបស់លោកអ្នក នេះ​មិនអាចធ្វើកម្មវិធីតាក់តែងអត្ថបទ កាត់អត្ថបទយកដោយស្វ័យប្រវត្តបានឡើយ ។ សូមប្រើប្រាស់បន្សំ ឃីដូចនេះ (Ctrl/Cmd+X) ។', paste: 'បិទ​ភ្ជាប់', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'តំបន់​បិទ​ភ្ជាប់', pasteMsg: 'សូមចំលងអត្ថបទទៅដាក់ក្នុងប្រអប់ដូចខាងក្រោមដោយប្រើប្រាស់ ឃី ​(Ctrl/Cmd+V) ហើយចុច OK ។', title: 'បិទ​ភ្ជាប់' diff --git a/plugins/clipboard/lang/ko.js b/plugins/clipboard/lang/ko.js index d4bac6b6d7f..97160dc0568 100644 --- a/plugins/clipboard/lang/ko.js +++ b/plugins/clipboard/lang/ko.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ko', { cut: '잘라내기', cutError: '브라우저의 보안설정 때문에 잘라내기 기능을 실행할 수 없습니다. 키보드(Ctrl/Cmd+X)를 이용해서 잘라내기 하십시오', paste: '붙여넣기', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: '붙여넣기 범위', pasteMsg: '키보드(Ctrl/Cmd+V)를 이용해서 상자안에 붙여넣고 확인 를 누르세요.', title: '붙여넣기' diff --git a/plugins/clipboard/lang/ku.js b/plugins/clipboard/lang/ku.js index 84cccffa574..83cb0a77573 100644 --- a/plugins/clipboard/lang/ku.js +++ b/plugins/clipboard/lang/ku.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ku', { cut: 'بڕین', cutError: 'پارێزی وێبگەڕەکەت ڕێگەنادات بە سەرنووسەکە لەبڕینی خۆکارانە. تکایە لەبری ئەمە ئەم فەرمانە بەکاربهێنە بەداگرتنی کلیلی (Ctrl/Cmd+X).', paste: 'لکاندن', - pasteNotification: 'وێبگەڕەکەت ڕێگەت پێنادات بۆ لکاندنی تێکست بە ڕێگایە. کلیکی %1 بۆ لکاندن.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'ناوچەی لکاندن', pasteMsg: 'تکایە بیلکێنە لەناوەوەی ئەم سنوقە لەڕێی تەختەکلیلەکەت بە بەکارهێنانی کلیلی (Ctrl/Cmd+V) دووای کلیکی باشە بکە.', title: 'لکاندن' diff --git a/plugins/clipboard/lang/lt.js b/plugins/clipboard/lang/lt.js index 017b8d7cf4e..fed0d59598f 100644 --- a/plugins/clipboard/lang/lt.js +++ b/plugins/clipboard/lang/lt.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'lt', { cut: 'Iškirpti', cutError: 'Jūsų naršyklės saugumo nustatymai neleidžia redaktoriui automatiškai įvykdyti iškirpimo operacijų. Tam prašome naudoti klaviatūrą (Ctrl/Cmd+X).', paste: 'Įdėti', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Įkelti dalį', pasteMsg: 'Žemiau esančiame įvedimo lauke įdėkite tekstą, naudodami klaviatūrą (Ctrl/Cmd+V) ir paspauskite mygtuką OK.', title: 'Įdėti' diff --git a/plugins/clipboard/lang/lv.js b/plugins/clipboard/lang/lv.js index be3153b5bf7..a1ba9e555fd 100644 --- a/plugins/clipboard/lang/lv.js +++ b/plugins/clipboard/lang/lv.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'lv', { cut: 'Izgriezt', cutError: 'Jūsu pārlūkprogrammas drošības iestatījumi nepieļauj redaktoram automātiski veikt izgriezšanas darbību. Lūdzu, izmantojiet (Ctrl/Cmd+X), lai veiktu šo darbību.', paste: 'Ielīmēt', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Ielīmēšanas zona', pasteMsg: 'Lūdzu, ievietojiet tekstu šajā laukumā, izmantojot klaviatūru (Ctrl/Cmd+V) un apstipriniet ar Darīts!.', title: 'Ievietot' diff --git a/plugins/clipboard/lang/mk.js b/plugins/clipboard/lang/mk.js index e9850f13b55..207b7e0e2f7 100644 --- a/plugins/clipboard/lang/mk.js +++ b/plugins/clipboard/lang/mk.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'mk', { cut: 'Исечи (Cut)', cutError: 'Опциите за безбедност на вашиот прелистувач не дозволуваат уредувачот автоматски да изврши сечење. Ве молиме употребете ја тастатурата. (Ctrl/Cmd+C)', paste: 'Залепи (Paste)', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Простор за залепување', pasteMsg: 'Ве молиме да залепите во следниот квадрат користејќи ја тастатурата (Ctrl/Cmd+V) и да притиснете OK', title: 'Залепи (Paste)' diff --git a/plugins/clipboard/lang/mn.js b/plugins/clipboard/lang/mn.js index 54e49e17f88..3ef6278cec0 100644 --- a/plugins/clipboard/lang/mn.js +++ b/plugins/clipboard/lang/mn.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'mn', { cut: 'Хайчлах', cutError: 'Таны browser-ын хамгаалалтын тохиргоо editor-д автоматаар хайчлах үйлдэлийг зөвшөөрөхгүй байна. (Ctrl/Cmd+X) товчны хослолыг ашиглана уу.', paste: 'Буулгах', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: '(Ctrl/Cmd+V) товчийг ашиглан paste хийнэ үү. Мөн OK дар.', title: 'Буулгах' diff --git a/plugins/clipboard/lang/ms.js b/plugins/clipboard/lang/ms.js index 049f56750bc..7d37544881b 100644 --- a/plugins/clipboard/lang/ms.js +++ b/plugins/clipboard/lang/ms.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ms', { cut: 'Potong', cutError: 'Keselamatan perisian browser anda tidak membenarkan operasi suntingan text/imej. Sila gunakan papan kekunci (Ctrl/Cmd+X).', paste: 'Tampal', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING title: 'Tampal' diff --git a/plugins/clipboard/lang/nb.js b/plugins/clipboard/lang/nb.js index 34101d544d8..85330b563b2 100644 --- a/plugins/clipboard/lang/nb.js +++ b/plugins/clipboard/lang/nb.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'nb', { cut: 'Klipp ut', cutError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk utklipping av tekst. Vennligst bruk tastatursnarveien (Ctrl/Cmd+X).', paste: 'Lim inn', - pasteNotification: 'Nettleseren din lar deg ikke lime inn på denne måten. Trykk %1 for å lime inn.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Innlimingsområde', pasteMsg: 'Vennligst lim inn i følgende boks med tastaturet (Ctrl/Cmd+V) og trykk OK.', title: 'Lim inn' diff --git a/plugins/clipboard/lang/nl.js b/plugins/clipboard/lang/nl.js index d6c06d0de0a..1d4fc073309 100644 --- a/plugins/clipboard/lang/nl.js +++ b/plugins/clipboard/lang/nl.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'nl', { cut: 'Knippen', cutError: 'De beveiligingsinstelling van de browser verhinderen het automatisch knippen. Gebruik de sneltoets Ctrl/Cmd+X van het toetsenbord.', paste: 'Plakken', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Plakgebied', pasteMsg: 'Plak de tekst in het volgende vak gebruikmakend van uw toetsenbord (Ctrl/Cmd+V) en klik op OK.', title: 'Plakken' diff --git a/plugins/clipboard/lang/no.js b/plugins/clipboard/lang/no.js index 01e9da520f5..e94229fbd61 100644 --- a/plugins/clipboard/lang/no.js +++ b/plugins/clipboard/lang/no.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'no', { cut: 'Klipp ut', cutError: 'Din nettlesers sikkerhetsinstillinger tillater ikke automatisk utklipping av tekst. Vennligst bruk snarveien (Ctrl/Cmd+X).', paste: 'Lim inn', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Innlimingsområde', pasteMsg: 'Vennligst lim inn i følgende boks med tastaturet (Ctrl/Cmd+V) og trykk OK.', title: 'Lim inn' diff --git a/plugins/clipboard/lang/oc.js b/plugins/clipboard/lang/oc.js index 95613a6b014..22ebf08c02e 100644 --- a/plugins/clipboard/lang/oc.js +++ b/plugins/clipboard/lang/oc.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'oc', { cut: 'Talhar', cutError: 'Los paramètres de seguretat de vòstre navigador autorizan pas l\'editor a executar automaticament l\'operacion « Talhar ». Utilizatz l\'acorchi de clavièr a aqueste efièit (Ctrl/Cmd+X).', paste: 'Pegar', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING title: 'Paste' // MISSING diff --git a/plugins/clipboard/lang/pl.js b/plugins/clipboard/lang/pl.js index 8431c2a4d91..4331cf619f5 100644 --- a/plugins/clipboard/lang/pl.js +++ b/plugins/clipboard/lang/pl.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'pl', { cut: 'Wytnij', cutError: 'Ustawienia bezpieczeństwa Twojej przeglądarki nie pozwalają na automatyczne wycinanie tekstu. Użyj skrótu klawiszowego Ctrl/Cmd+X.', paste: 'Wklej', - pasteNotification: 'Twoja przeglądarka nie pozwala na wklejanie treści w ten sposób. Naciśnij %1 by wkleić tekst.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Obszar wklejania', pasteMsg: 'Wklej tekst w poniższym polu, używając skrótu klawiaturowego (Ctrl/Cmd+V), i kliknij OK.', title: 'Wklej' diff --git a/plugins/clipboard/lang/pt-br.js b/plugins/clipboard/lang/pt-br.js index 2df0b1ac882..44968b1a4dd 100644 --- a/plugins/clipboard/lang/pt-br.js +++ b/plugins/clipboard/lang/pt-br.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'pt-br', { cut: 'Recortar', cutError: 'As configurações de segurança do seu navegador não permitem que o editor execute operações de recortar automaticamente. Por favor, utilize o teclado para recortar (Ctrl/Cmd+X).', paste: 'Colar', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Área para Colar', pasteMsg: 'Transfira o link usado na caixa usando o teclado com (Ctrl/Cmd+V) e OK.', title: 'Colar' diff --git a/plugins/clipboard/lang/pt.js b/plugins/clipboard/lang/pt.js index ebbff92f5a5..f20f9ab8558 100644 --- a/plugins/clipboard/lang/pt.js +++ b/plugins/clipboard/lang/pt.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'pt', { cut: 'Cortar', cutError: 'A configuração de segurança do navegador não permite a execução automática de operações de cortar. Por favor use o teclado (Ctrl/Cmd+X).', paste: 'Colar', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Colar área', pasteMsg: 'Por favor, cole dentro da seguinte caixa usando o teclado (Ctrl/Cmd+V) e carregue em OK.', title: 'Colar' diff --git a/plugins/clipboard/lang/ro.js b/plugins/clipboard/lang/ro.js index 62bc304f650..f81ed6ff0b9 100644 --- a/plugins/clipboard/lang/ro.js +++ b/plugins/clipboard/lang/ro.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ro', { cut: 'Decupează', cutError: 'Setările de securitate ale navigatorului (browser) pe care îl folosiţi nu permit editorului să execute automat operaţiunea de tăiere. Vă rugăm folosiţi tastatura (Ctrl/Cmd+X).', paste: 'Adaugă din clipboard', - pasteNotification: 'Permiteți accesul la clipboard pentru a adăuga conținut?', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Suprafața de adăugare', pasteMsg: 'Vă rugăm adăugaţi în căsuţa următoare folosind tastatura (Ctrl/Cmd+V) şi apăsaţi OK', title: 'Adaugă' diff --git a/plugins/clipboard/lang/ru.js b/plugins/clipboard/lang/ru.js index 3c03636fd67..e9baaeddd11 100644 --- a/plugins/clipboard/lang/ru.js +++ b/plugins/clipboard/lang/ru.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ru', { cut: 'Вырезать', cutError: 'Настройки безопасности вашего браузера не разрешают редактору выполнять операции по вырезке текста. Пожалуйста, используйте для этого клавиатуру (Ctrl/Cmd+X).', paste: 'Вставить', - pasteNotification: 'Ваш браузер не поддерживает данный метод вставки. Для вставки нажмите %1', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Зона для вставки', pasteMsg: 'Пожалуйста, вставьте текст в зону ниже, используя клавиатуру (Ctrl/Cmd+V) и нажмите кнопку "OK".', title: 'Вставить' diff --git a/plugins/clipboard/lang/si.js b/plugins/clipboard/lang/si.js index 4c03cf8873f..0524374510d 100644 --- a/plugins/clipboard/lang/si.js +++ b/plugins/clipboard/lang/si.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'si', { cut: 'කපාගන්න', cutError: 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).', // MISSING paste: 'අලවන්න', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'අලවන ප්‍රදේශ', pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING title: 'අලවන්න' diff --git a/plugins/clipboard/lang/sk.js b/plugins/clipboard/lang/sk.js index e53ce92f84f..5216aadd201 100644 --- a/plugins/clipboard/lang/sk.js +++ b/plugins/clipboard/lang/sk.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sk', { cut: 'Vystrihnúť', cutError: 'Bezpečnostné nastavenia vášho prehliadača nedovoľujú editoru automaticky spustiť operáciu vystrihnutia. Použite na to klávesnicu (Ctrl/Cmd+X).', paste: 'Vložiť', - pasteNotification: 'Váš prehliadač nepovoľuje prilepiť text takýmto spôsobom. Pre prilepenie stlačte %1.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Miesto na vloženie', pasteMsg: 'Použitím klávesnice (Ctrl/Cmd+V) vložte text do rámčeka a stlačte OK.', title: 'Vložiť' diff --git a/plugins/clipboard/lang/sl.js b/plugins/clipboard/lang/sl.js index d992c9242c1..8d457759936 100644 --- a/plugins/clipboard/lang/sl.js +++ b/plugins/clipboard/lang/sl.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sl', { cut: 'Izreži', cutError: 'Varnostne nastavitve brskalnika ne dopuščajo samodejnega izrezovanja. Uporabite kombinacijo tipk na tipkovnici (Ctrl/Cmd+X).', paste: 'Prilepi', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Prilepi območje', pasteMsg: 'Prosimo, prilepite v sleči okvir s pomočjo tipkovnice (Ctrl/Cmd+V) in pritisnite V redu.', title: 'Prilepi' diff --git a/plugins/clipboard/lang/sq.js b/plugins/clipboard/lang/sq.js index f47a1e15e55..5a4c132f20a 100644 --- a/plugins/clipboard/lang/sq.js +++ b/plugins/clipboard/lang/sq.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sq', { cut: 'Preje', cutError: 'Të dhënat e sigurisë së shfletuesit tuaj nuk lejojnë që redaktuesi automatikisht të kryej veprimin e prerjes. Ju lutemi shfrytëzoni tastierën për këtë veprim (Ctrl/Cmd+X).', paste: 'Hidhe', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Hapësira Hedhëse', pasteMsg: 'Ju lutemi hidhni brenda kutizës në vijim duke shfrytëzuar tastierën (Ctrl/Cmd+V) dhe shtypni Mirë.', title: 'Hidhe' diff --git a/plugins/clipboard/lang/sr-latn.js b/plugins/clipboard/lang/sr-latn.js index bde1d4efb13..44d79501c85 100644 --- a/plugins/clipboard/lang/sr-latn.js +++ b/plugins/clipboard/lang/sr-latn.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sr-latn', { cut: 'Iseci', cutError: 'Sigurnosna podešavanja Vašeg pretraživača ne dozvoljavaju operacije automatskog isecanja teksta. Molimo Vas da koristite prečicu sa tastature (Ctrl/Cmd+X).', paste: 'Zalepi', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Prostor za lepljenje', pasteMsg: 'Molimo Vas da zalepite unutar donje povrine koristeći tastaturnu prečicu (Ctrl/Cmd+V) i da pritisnete OK.', title: 'Zalepi' diff --git a/plugins/clipboard/lang/sr.js b/plugins/clipboard/lang/sr.js index 8003cf48dd4..ca98d16acce 100644 --- a/plugins/clipboard/lang/sr.js +++ b/plugins/clipboard/lang/sr.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sr', { cut: 'Исеци', cutError: 'Сигурносна подешавања Вашег претраживача не дозвољавају операције аутоматског исецања текста. Молимо Вас да користите пречицу са тастатуре (Ctrl/Cmd+X).', paste: 'Залепи', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Залепи зону', pasteMsg: 'Молимо Вас да залепите унутар доње површине користећи тастатурну пречицу (Ctrl/Cmd+V) и да притиснете OK.', title: 'Залепи' diff --git a/plugins/clipboard/lang/sv.js b/plugins/clipboard/lang/sv.js index e34a9b7f0a1..d25c006060f 100644 --- a/plugins/clipboard/lang/sv.js +++ b/plugins/clipboard/lang/sv.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'sv', { cut: 'Klipp ut', cutError: 'Säkerhetsinställningar i din webbläsare tillåter inte åtgärden klipp ut. Använd (Ctrl/Cmd+X) istället.', paste: 'Klistra in', - pasteNotification: 'Din webbläsare tillåter dig inte att klistra in på detta vis. Tryck på %1 för att klistra in.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', pasteMsg: 'Var god och klistra in Er text i rutan nedan genom att använda (Ctrl/Cmd+V) klicka sen på OK.', title: 'Klistra in' diff --git a/plugins/clipboard/lang/th.js b/plugins/clipboard/lang/th.js index dbf1de7bfab..e3a1f0f3dad 100644 --- a/plugins/clipboard/lang/th.js +++ b/plugins/clipboard/lang/th.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'th', { cut: 'ตัด', cutError: 'ไม่สามารถตัดข้อความที่เลือกไว้ได้เนื่องจากการกำหนดค่าระดับความปลอดภัย. กรุณาใช้ปุ่มลัดเพื่อวางข้อความแทน (กดปุ่ม Ctrl/Cmd และตัว X พร้อมกัน).', paste: 'วาง', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Paste Area', // MISSING pasteMsg: 'กรุณาใช้คีย์บอร์ดเท่านั้น โดยกดปุ๋ม (Ctrl/Cmd และ V)พร้อมๆกัน และกด OK.', title: 'วาง' diff --git a/plugins/clipboard/lang/tr.js b/plugins/clipboard/lang/tr.js index 40c4c25cbc2..5fe6adbac29 100644 --- a/plugins/clipboard/lang/tr.js +++ b/plugins/clipboard/lang/tr.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'tr', { cut: 'Kes', cutError: 'Gezgin yazılımınızın güvenlik ayarları düzenleyicinin otomatik kesme işlemine izin vermiyor. İşlem için (Ctrl/Cmd+X) tuşlarını kullanın.', paste: 'Yapıştır', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Yapıştırma Alanı', pasteMsg: 'Lütfen aşağıdaki kutunun içine yapıştırın. (Ctrl/Cmd+V) ve Tamam butonunu tıklayın.', title: 'Yapıştır' diff --git a/plugins/clipboard/lang/tt.js b/plugins/clipboard/lang/tt.js index 386202e1283..66c91f05228 100644 --- a/plugins/clipboard/lang/tt.js +++ b/plugins/clipboard/lang/tt.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'tt', { cut: 'Кисеп алу', cutError: 'Браузерыгызның иминлек үзлекләре автоматик рәвештә күчермәләү үтәүне тыя. Тиз төймәләрне (Ctrl/Cmd+C) кулланыгыз.', paste: 'Өстәү', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Өстәү мәйданы', pasteMsg: 'Please paste inside the following box using the keyboard (Ctrl/Cmd+V) and hit OK', // MISSING title: 'Өстәү' diff --git a/plugins/clipboard/lang/ug.js b/plugins/clipboard/lang/ug.js index b8a5ada69f0..d554efa941e 100644 --- a/plugins/clipboard/lang/ug.js +++ b/plugins/clipboard/lang/ug.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'ug', { cut: 'كەس', cutError: 'تور كۆرگۈڭىزنىڭ بىخەتەرلىك تەڭشىكى تەھرىرلىگۈچنىڭ كەس مەشغۇلاتىنى ئۆزلۈكىدىن ئىجرا قىلىشىغا يول قويمايدۇ، ھەرپتاختا تېز كۇنۇپكا (Ctrl/Cmd+X) ئارقىلىق تاماملاڭ', paste: 'چاپلا', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'چاپلاش دائىرىسى', pasteMsg: 'ھەرپتاختا تېز كۇنۇپكا (Ctrl/Cmd+V) نى ئىشلىتىپ مەزمۇننى تۆۋەندىكى رامكىغا كۆچۈرۈڭ، ئاندىن جەزملەنى بېسىڭ', title: 'چاپلا' diff --git a/plugins/clipboard/lang/uk.js b/plugins/clipboard/lang/uk.js index f41ab5ed23e..1fed32cf493 100644 --- a/plugins/clipboard/lang/uk.js +++ b/plugins/clipboard/lang/uk.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'uk', { cut: 'Вирізати', cutError: 'Налаштування безпеки Вашого браузера не дозволяють редактору автоматично виконувати операції вирізування. Будь ласка, використовуйте клавіатуру для цього (Ctrl/Cmd+X)', paste: 'Вставити', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Область вставки', pasteMsg: 'Будь ласка, вставте інформацію з буфера обміну в цю область, користуючись комбінацією клавіш (Ctrl/Cmd+V), та натисніть OK.', title: 'Вставити' diff --git a/plugins/clipboard/lang/vi.js b/plugins/clipboard/lang/vi.js index 5c7f061d48d..02d3a5bc068 100644 --- a/plugins/clipboard/lang/vi.js +++ b/plugins/clipboard/lang/vi.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'vi', { cut: 'Cắt', cutError: 'Các thiết lập bảo mật của trình duyệt không cho phép trình biên tập tự động thực thi lệnh cắt. Hãy sử dụng bàn phím cho lệnh này (Ctrl/Cmd+X).', paste: 'Dán', - pasteNotification: 'Trình duyệt của bạn không cho phép bạn dán theo cách này. Nhấn %1 để dán', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: 'Khu vực dán', pasteMsg: 'Hãy dán nội dung vào trong khung bên dưới, sử dụng tổ hợp phím (Ctrl/Cmd+V) và nhấn vào nút Đồng ý.', title: 'Dán' diff --git a/plugins/clipboard/lang/zh-cn.js b/plugins/clipboard/lang/zh-cn.js index 9a62a6d68aa..d1750514a57 100644 --- a/plugins/clipboard/lang/zh-cn.js +++ b/plugins/clipboard/lang/zh-cn.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'zh-cn', { cut: '剪切', cutError: '您的浏览器安全设置不允许编辑器自动执行剪切操作,请使用键盘快捷键(Ctrl/Cmd+X)来完成。', paste: '粘贴', - pasteNotification: '您的浏览器不允许用此方式粘贴,要粘贴请按 %1。', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: '粘贴区域', pasteMsg: '请使用键盘快捷键(Ctrl/Cmd+V)把内容粘贴到下面的方框里,再按 确定', title: '粘贴' diff --git a/plugins/clipboard/lang/zh.js b/plugins/clipboard/lang/zh.js index 734c8b1c702..2439243689e 100644 --- a/plugins/clipboard/lang/zh.js +++ b/plugins/clipboard/lang/zh.js @@ -8,7 +8,7 @@ CKEDITOR.plugins.setLang( 'clipboard', 'zh', { cut: '剪下', cutError: '瀏覽器的安全性設定不允許編輯器自動執行剪下動作。請使用鏐盤快捷鍵 (Ctrl/Cmd+X) 剪下。', paste: '貼上', - pasteNotification: 'Your browser doesn\'t allow you to paste this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING pasteArea: '貼上區', pasteMsg: '請使用鍵盤快捷鍵 (Ctrl/Cmd+V) 貼到下方區域中並按下「確定」。', title: '貼上' diff --git a/plugins/pastetext/lang/af.js b/plugins/pastetext/lang/af.js index 108c30ee55e..2d0a7114b4f 100644 --- a/plugins/pastetext/lang/af.js +++ b/plugins/pastetext/lang/af.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'af', { button: 'Plak as eenvoudige teks', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Plak as eenvoudige teks' } ); diff --git a/plugins/pastetext/lang/ar.js b/plugins/pastetext/lang/ar.js index 2e2a0c43d09..328e95e610b 100644 --- a/plugins/pastetext/lang/ar.js +++ b/plugins/pastetext/lang/ar.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ar', { button: 'لصق كنص بسيط', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'لصق كنص بسيط' } ); diff --git a/plugins/pastetext/lang/az.js b/plugins/pastetext/lang/az.js index 81bf63f4bed..20e0ad8d207 100644 --- a/plugins/pastetext/lang/az.js +++ b/plugins/pastetext/lang/az.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'az', { button: 'Yalnız mətni saxla', - pasteNotification: 'Sizin İnternet bələdçiniz bu cür mətnin köçürməsini dəstəklənmir. Əlavə etmək üçün %1 basın.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Paste as Plain Text' // MISSING } ); diff --git a/plugins/pastetext/lang/bg.js b/plugins/pastetext/lang/bg.js index 977d8190cfe..ce53c9d5836 100644 --- a/plugins/pastetext/lang/bg.js +++ b/plugins/pastetext/lang/bg.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'bg', { button: 'Вмъкни като чист текст', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Вмъкни като чист текст' } ); diff --git a/plugins/pastetext/lang/bn.js b/plugins/pastetext/lang/bn.js index 9bb6518dd50..a9048beeccd 100644 --- a/plugins/pastetext/lang/bn.js +++ b/plugins/pastetext/lang/bn.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'bn', { button: 'সাধারণ টেক্সট হিসেবে পেইস্ট করি', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'সাদা টেক্সট হিসেবে পেস্ট কর' } ); diff --git a/plugins/pastetext/lang/bs.js b/plugins/pastetext/lang/bs.js index 1e4edb2f84c..ad7a0ff9ee9 100644 --- a/plugins/pastetext/lang/bs.js +++ b/plugins/pastetext/lang/bs.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'bs', { button: 'Zalijepi kao obièan tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Zalijepi kao obièan tekst' } ); diff --git a/plugins/pastetext/lang/ca.js b/plugins/pastetext/lang/ca.js index ece87869837..f07930fa905 100644 --- a/plugins/pastetext/lang/ca.js +++ b/plugins/pastetext/lang/ca.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ca', { button: 'Enganxa com a text no formatat', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Enganxa com a text no formatat' } ); diff --git a/plugins/pastetext/lang/cs.js b/plugins/pastetext/lang/cs.js index 22b594164e7..78cca1bc249 100644 --- a/plugins/pastetext/lang/cs.js +++ b/plugins/pastetext/lang/cs.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'cs', { button: 'Vložit jako čistý text', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Vložit jako čistý text' } ); diff --git a/plugins/pastetext/lang/cy.js b/plugins/pastetext/lang/cy.js index 72a563b21f9..5be8298eff2 100644 --- a/plugins/pastetext/lang/cy.js +++ b/plugins/pastetext/lang/cy.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'cy', { button: 'Gludo fel testun plaen', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Gludo fel Testun Plaen' } ); diff --git a/plugins/pastetext/lang/da.js b/plugins/pastetext/lang/da.js index 25ff7ba1e27..861671126be 100644 --- a/plugins/pastetext/lang/da.js +++ b/plugins/pastetext/lang/da.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'da', { button: 'Indsæt som ikke-formateret tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Indsæt som ikke-formateret tekst' } ); diff --git a/plugins/pastetext/lang/de-ch.js b/plugins/pastetext/lang/de-ch.js index e7d72ae46b2..0becbd1803f 100644 --- a/plugins/pastetext/lang/de-ch.js +++ b/plugins/pastetext/lang/de-ch.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'de-ch', { button: 'Als Klartext einfügen', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Als Klartext einfügen' } ); diff --git a/plugins/pastetext/lang/de.js b/plugins/pastetext/lang/de.js index 97659ecdd85..96fd660c0b4 100644 --- a/plugins/pastetext/lang/de.js +++ b/plugins/pastetext/lang/de.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'de', { button: 'Als Klartext einfügen', - pasteNotification: 'Ihr Browser verhindert das Einfügen von Text über diesen Weg. Zum einfügen drücken Sie %1.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Als Klartext einfügen' } ); diff --git a/plugins/pastetext/lang/el.js b/plugins/pastetext/lang/el.js index 007d732dafd..ef024919a3a 100644 --- a/plugins/pastetext/lang/el.js +++ b/plugins/pastetext/lang/el.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'el', { button: 'Επικόλληση ως απλό κείμενο', - pasteNotification: 'Ο φυλλομετρητής σας δεν επιτρέπει την επικόλληση απλού κειμένου με αυτόν τον τρόπο. Πατήστε 1% για να επικολλήστε.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Επικόλληση ως απλό κείμενο' } ); diff --git a/plugins/pastetext/lang/en-au.js b/plugins/pastetext/lang/en-au.js index 47f527a0727..f5e97f65090 100644 --- a/plugins/pastetext/lang/en-au.js +++ b/plugins/pastetext/lang/en-au.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'en-au', { button: 'Paste as plain text', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Paste as Plain Text' } ); diff --git a/plugins/pastetext/lang/en-ca.js b/plugins/pastetext/lang/en-ca.js index 83306dba8af..4d844aa8667 100644 --- a/plugins/pastetext/lang/en-ca.js +++ b/plugins/pastetext/lang/en-ca.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'en-ca', { button: 'Paste as plain text', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Paste as Plain Text' } ); diff --git a/plugins/pastetext/lang/en-gb.js b/plugins/pastetext/lang/en-gb.js index dd89d7deaeb..3a786e7af8b 100644 --- a/plugins/pastetext/lang/en-gb.js +++ b/plugins/pastetext/lang/en-gb.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'en-gb', { button: 'Paste as plain text', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Paste as Plain Text' } ); diff --git a/plugins/pastetext/lang/en.js b/plugins/pastetext/lang/en.js index b90800d8c63..ae6e46a26bc 100644 --- a/plugins/pastetext/lang/en.js +++ b/plugins/pastetext/lang/en.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'en', { button: 'Paste as plain text', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', title: 'Paste as Plain Text' } ); diff --git a/plugins/pastetext/lang/eo.js b/plugins/pastetext/lang/eo.js index 242091947a3..7dd0dd6389d 100644 --- a/plugins/pastetext/lang/eo.js +++ b/plugins/pastetext/lang/eo.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'eo', { button: 'Interglui kiel platan tekston', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Interglui kiel platan tekston' } ); diff --git a/plugins/pastetext/lang/es-mx.js b/plugins/pastetext/lang/es-mx.js index 5400f6ea474..50a0cb57b12 100644 --- a/plugins/pastetext/lang/es-mx.js +++ b/plugins/pastetext/lang/es-mx.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'es-mx', { button: 'Pegar como texto plano', - pasteNotification: 'Su navegador no permite esta forma de pegar texto plano. Presiona %1 para pegar.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Paste as Plain Text' // MISSING } ); diff --git a/plugins/pastetext/lang/es.js b/plugins/pastetext/lang/es.js index 22efecbfe40..bfb08fc9d20 100644 --- a/plugins/pastetext/lang/es.js +++ b/plugins/pastetext/lang/es.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'es', { button: 'Pegar como Texto Plano', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Pegar como Texto Plano' } ); diff --git a/plugins/pastetext/lang/et.js b/plugins/pastetext/lang/et.js index 4a6acd2c132..82ee9527803 100644 --- a/plugins/pastetext/lang/et.js +++ b/plugins/pastetext/lang/et.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'et', { button: 'Asetamine tavalise tekstina', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Asetamine tavalise tekstina' } ); diff --git a/plugins/pastetext/lang/eu.js b/plugins/pastetext/lang/eu.js index d18377c8703..54a594fcccc 100644 --- a/plugins/pastetext/lang/eu.js +++ b/plugins/pastetext/lang/eu.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'eu', { button: 'Itsatsi testu arrunta bezala', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Itsatsi testu arrunta bezala' } ); diff --git a/plugins/pastetext/lang/fa.js b/plugins/pastetext/lang/fa.js index 19794a9d2e0..13eb262a2d2 100644 --- a/plugins/pastetext/lang/fa.js +++ b/plugins/pastetext/lang/fa.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'fa', { button: 'چسباندن به عنوان متن ساده', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'چسباندن به عنوان متن ساده' } ); diff --git a/plugins/pastetext/lang/fi.js b/plugins/pastetext/lang/fi.js index 9edee11450f..77a32f01b08 100644 --- a/plugins/pastetext/lang/fi.js +++ b/plugins/pastetext/lang/fi.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'fi', { button: 'Liitä tekstinä', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Liitä tekstinä' } ); diff --git a/plugins/pastetext/lang/fo.js b/plugins/pastetext/lang/fo.js index 1b1b524721a..4b7d9ed4ac6 100644 --- a/plugins/pastetext/lang/fo.js +++ b/plugins/pastetext/lang/fo.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'fo', { button: 'Innrita som reinan tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Innrita som reinan tekst' } ); diff --git a/plugins/pastetext/lang/fr-ca.js b/plugins/pastetext/lang/fr-ca.js index 3a8d44bc892..aa4be1375ca 100644 --- a/plugins/pastetext/lang/fr-ca.js +++ b/plugins/pastetext/lang/fr-ca.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'fr-ca', { button: 'Coller comme texte', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Coller comme texte' } ); diff --git a/plugins/pastetext/lang/fr.js b/plugins/pastetext/lang/fr.js index ef95676bd0c..0bd819324ad 100644 --- a/plugins/pastetext/lang/fr.js +++ b/plugins/pastetext/lang/fr.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'fr', { button: 'Coller comme texte brut', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Coller comme texte brut' } ); diff --git a/plugins/pastetext/lang/gl.js b/plugins/pastetext/lang/gl.js index 9ffe347398e..1c9664f6850 100644 --- a/plugins/pastetext/lang/gl.js +++ b/plugins/pastetext/lang/gl.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'gl', { button: 'Pegar como texto simple', - pasteNotification: 'O seu navegador non permite pegar texto simple deste xeito. Prema %1 para pegar.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Pegar como texto simple' } ); diff --git a/plugins/pastetext/lang/gu.js b/plugins/pastetext/lang/gu.js index 32b3e72aa4f..b07b24327d4 100644 --- a/plugins/pastetext/lang/gu.js +++ b/plugins/pastetext/lang/gu.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'gu', { button: 'પેસ્ટ (ટેક્સ્ટ)', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'પેસ્ટ (ટેક્સ્ટ)' } ); diff --git a/plugins/pastetext/lang/he.js b/plugins/pastetext/lang/he.js index 23e698c3c72..cab46b9c7fe 100644 --- a/plugins/pastetext/lang/he.js +++ b/plugins/pastetext/lang/he.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'he', { button: 'הדבקה כטקסט פשוט', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'הדבקה כטקסט פשוט' } ); diff --git a/plugins/pastetext/lang/hi.js b/plugins/pastetext/lang/hi.js index 55a7124fa8c..06418201753 100644 --- a/plugins/pastetext/lang/hi.js +++ b/plugins/pastetext/lang/hi.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'hi', { button: 'पेस्ट (सादा टॅक्स्ट)', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'पेस्ट (सादा टॅक्स्ट)' } ); diff --git a/plugins/pastetext/lang/hr.js b/plugins/pastetext/lang/hr.js index 72630a93403..56269710bcc 100644 --- a/plugins/pastetext/lang/hr.js +++ b/plugins/pastetext/lang/hr.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'hr', { button: 'Zalijepi kao čisti tekst', - pasteNotification: 'Vaš preglednik Vam ne dozvoljava lijepljenje običnog teksta na ovaj način. Za lijepljenje, pritisnite %1.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Zalijepi kao čisti tekst' } ); diff --git a/plugins/pastetext/lang/hu.js b/plugins/pastetext/lang/hu.js index 65a9c808123..ae8a5658289 100644 --- a/plugins/pastetext/lang/hu.js +++ b/plugins/pastetext/lang/hu.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'hu', { button: 'Beillesztés formázatlan szövegként', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Beillesztés formázatlan szövegként' } ); diff --git a/plugins/pastetext/lang/id.js b/plugins/pastetext/lang/id.js index 0f49162f69a..a00f592634e 100644 --- a/plugins/pastetext/lang/id.js +++ b/plugins/pastetext/lang/id.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'id', { button: 'Tempel sebagai teks polos', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Tempel sebagai Teks Polos' } ); diff --git a/plugins/pastetext/lang/is.js b/plugins/pastetext/lang/is.js index b4360287026..d9f1074ca39 100644 --- a/plugins/pastetext/lang/is.js +++ b/plugins/pastetext/lang/is.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'is', { button: 'Líma sem ósniðinn texta', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Líma sem ósniðinn texta' } ); diff --git a/plugins/pastetext/lang/it.js b/plugins/pastetext/lang/it.js index dd65bc27d49..76130ddf985 100644 --- a/plugins/pastetext/lang/it.js +++ b/plugins/pastetext/lang/it.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'it', { button: 'Incolla come testo semplice', - pasteNotification: 'Il browser non permette di incollare il testo semplice in questo modo. Premere %1 per incollare.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Incolla come testo semplice' } ); diff --git a/plugins/pastetext/lang/ja.js b/plugins/pastetext/lang/ja.js index 9ac178298de..5e0e116d87e 100644 --- a/plugins/pastetext/lang/ja.js +++ b/plugins/pastetext/lang/ja.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ja', { button: 'プレーンテキストとして貼り付け', - pasteNotification: 'ブラウザの設定によりこの方法でプレーンテキストを貼り付けることはできません。手動で実行するにはキーボードの「%1」を押してくださ\r\nい。', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'プレーンテキストとして貼り付け' } ); diff --git a/plugins/pastetext/lang/ka.js b/plugins/pastetext/lang/ka.js index da92d23c7db..ea905ad189b 100644 --- a/plugins/pastetext/lang/ka.js +++ b/plugins/pastetext/lang/ka.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ka', { button: 'მხოლოდ ტექსტის ჩასმა', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'მხოლოდ ტექსტის ჩასმა' } ); diff --git a/plugins/pastetext/lang/km.js b/plugins/pastetext/lang/km.js index b95a1f9f582..31f7fb54b9f 100644 --- a/plugins/pastetext/lang/km.js +++ b/plugins/pastetext/lang/km.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'km', { button: 'បិទ​ភ្ជាប់​ជា​អត្ថបទ​ធម្មតា', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'បិទ​ភ្ជាប់​ជា​អត្ថបទ​ធម្មតា' } ); diff --git a/plugins/pastetext/lang/ko.js b/plugins/pastetext/lang/ko.js index 45c6ac8d634..86fdfcc3eac 100644 --- a/plugins/pastetext/lang/ko.js +++ b/plugins/pastetext/lang/ko.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ko', { button: '텍스트로 붙여넣기', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: '텍스트로 붙여넣기' } ); diff --git a/plugins/pastetext/lang/ku.js b/plugins/pastetext/lang/ku.js index df61333c1e4..4aea8280e2a 100644 --- a/plugins/pastetext/lang/ku.js +++ b/plugins/pastetext/lang/ku.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ku', { button: 'لکاندنی وەك دەقی ڕوون', - pasteNotification: 'وێبگەڕەکەت ڕێگەت پێنادات بۆ لکاندنی تێکست بە ڕێگایە. کلیکی %1 بۆ لکاندن.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'لکاندنی وەك دەقی ڕوون' } ); diff --git a/plugins/pastetext/lang/lt.js b/plugins/pastetext/lang/lt.js index d335af60e18..3b0b426fb49 100644 --- a/plugins/pastetext/lang/lt.js +++ b/plugins/pastetext/lang/lt.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'lt', { button: 'Įdėti kaip gryną tekstą', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Įdėti kaip gryną tekstą' } ); diff --git a/plugins/pastetext/lang/lv.js b/plugins/pastetext/lang/lv.js index ab53b49fe59..d4e08ff14dc 100644 --- a/plugins/pastetext/lang/lv.js +++ b/plugins/pastetext/lang/lv.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'lv', { button: 'Ievietot kā vienkāršu tekstu', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Ievietot kā vienkāršu tekstu' } ); diff --git a/plugins/pastetext/lang/mk.js b/plugins/pastetext/lang/mk.js index bcc82c2ccc7..e317e77ad3f 100644 --- a/plugins/pastetext/lang/mk.js +++ b/plugins/pastetext/lang/mk.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'mk', { button: 'Paste as plain text', // MISSING - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Paste as Plain Text' // MISSING } ); diff --git a/plugins/pastetext/lang/mn.js b/plugins/pastetext/lang/mn.js index 5b46b354888..033df4f8236 100644 --- a/plugins/pastetext/lang/mn.js +++ b/plugins/pastetext/lang/mn.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'mn', { button: 'Энгийн бичвэрээр буулгах', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Энгийн бичвэрээр буулгах' } ); diff --git a/plugins/pastetext/lang/ms.js b/plugins/pastetext/lang/ms.js index 7b65c9a7919..e7b37fb3597 100644 --- a/plugins/pastetext/lang/ms.js +++ b/plugins/pastetext/lang/ms.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ms', { button: 'Tampal sebagai text biasa', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Tampal sebagai text biasa' } ); diff --git a/plugins/pastetext/lang/nb.js b/plugins/pastetext/lang/nb.js index ee79db07a91..b8debcad8f5 100644 --- a/plugins/pastetext/lang/nb.js +++ b/plugins/pastetext/lang/nb.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'nb', { button: 'Lim inn som ren tekst', - pasteNotification: 'Nettleseren din lar deg ikke lime inn ren tekst på denne måten. Trykk %1 for å lime inn.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Lim inn som ren tekst' } ); diff --git a/plugins/pastetext/lang/nl.js b/plugins/pastetext/lang/nl.js index e1603c28520..64ae848aba8 100644 --- a/plugins/pastetext/lang/nl.js +++ b/plugins/pastetext/lang/nl.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'nl', { button: 'Plakken als platte tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Plakken als platte tekst' } ); diff --git a/plugins/pastetext/lang/no.js b/plugins/pastetext/lang/no.js index 05c2829b04a..dc42725e559 100644 --- a/plugins/pastetext/lang/no.js +++ b/plugins/pastetext/lang/no.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'no', { button: 'Lim inn som ren tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Lim inn som ren tekst' } ); diff --git a/plugins/pastetext/lang/oc.js b/plugins/pastetext/lang/oc.js index 4c66b7a6029..53c5745ecd0 100644 --- a/plugins/pastetext/lang/oc.js +++ b/plugins/pastetext/lang/oc.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'oc', { button: 'Pegar coma tèxte brut', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Paste as Plain Text' // MISSING } ); diff --git a/plugins/pastetext/lang/pl.js b/plugins/pastetext/lang/pl.js index 44546f0df05..5f13a512588 100644 --- a/plugins/pastetext/lang/pl.js +++ b/plugins/pastetext/lang/pl.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'pl', { button: 'Wklej jako czysty tekst', - pasteNotification: 'Twoja przeglądarka nie pozwala na wklejanie treści w ten sposób. Naciśnij %1 by wkleić tekst.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Wklej jako czysty tekst' } ); diff --git a/plugins/pastetext/lang/pt-br.js b/plugins/pastetext/lang/pt-br.js index f239aca8a21..d7a86cef9da 100644 --- a/plugins/pastetext/lang/pt-br.js +++ b/plugins/pastetext/lang/pt-br.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'pt-br', { button: 'Colar como Texto sem Formatação', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Colar como Texto sem Formatação' } ); diff --git a/plugins/pastetext/lang/pt.js b/plugins/pastetext/lang/pt.js index d2d1ecf47f4..49f2eeb292f 100644 --- a/plugins/pastetext/lang/pt.js +++ b/plugins/pastetext/lang/pt.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'pt', { button: 'Colar como texto simples', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Colar como texto simples' } ); diff --git a/plugins/pastetext/lang/ro.js b/plugins/pastetext/lang/ro.js index aaa964d9e3e..1863cd19e78 100644 --- a/plugins/pastetext/lang/ro.js +++ b/plugins/pastetext/lang/ro.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ro', { button: 'Adaugă ca text simplu (Plain Text)', - pasteNotification: 'Se lipește conținut din clipboard. Confirmați?', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Adaugă ca text simplu (Plain Text)' } ); diff --git a/plugins/pastetext/lang/ru.js b/plugins/pastetext/lang/ru.js index ed1ef26717d..8b59b04ac61 100644 --- a/plugins/pastetext/lang/ru.js +++ b/plugins/pastetext/lang/ru.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ru', { button: 'Вставить только текст', - pasteNotification: 'Ваш браузер не поддерживает данный метод вставки. Для вставки нажмите %1', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Вставить только текст' } ); diff --git a/plugins/pastetext/lang/si.js b/plugins/pastetext/lang/si.js index 80d004fe1f6..fc05d2e078d 100644 --- a/plugins/pastetext/lang/si.js +++ b/plugins/pastetext/lang/si.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'si', { button: 'සාමාන්‍ය අක්ෂර ලෙස අලවන්න', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'සාමාන්‍ය අක්ෂර ලෙස අලවන්න' } ); diff --git a/plugins/pastetext/lang/sk.js b/plugins/pastetext/lang/sk.js index 79bd02c43e8..eecb9b08819 100644 --- a/plugins/pastetext/lang/sk.js +++ b/plugins/pastetext/lang/sk.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sk', { button: 'Vložiť ako čistý text', - pasteNotification: 'Váš prehliadač neumožňuje vložiť text týmto spôsobom. Na vloženie textu stlačte %1.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Vložiť ako čistý text' } ); diff --git a/plugins/pastetext/lang/sl.js b/plugins/pastetext/lang/sl.js index ee0197478f4..8ea413cf9b9 100644 --- a/plugins/pastetext/lang/sl.js +++ b/plugins/pastetext/lang/sl.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sl', { button: 'Prilepi kot golo besedilo', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Prilepi kot golo besedilo' } ); diff --git a/plugins/pastetext/lang/sq.js b/plugins/pastetext/lang/sq.js index 18e248400e0..6b58b7dbbd4 100644 --- a/plugins/pastetext/lang/sq.js +++ b/plugins/pastetext/lang/sq.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sq', { button: 'Hidhe si tekst të thjeshtë', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Hidhe si Tekst të Thjeshtë' } ); diff --git a/plugins/pastetext/lang/sr-latn.js b/plugins/pastetext/lang/sr-latn.js index 001b385394d..72253c83a27 100644 --- a/plugins/pastetext/lang/sr-latn.js +++ b/plugins/pastetext/lang/sr-latn.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sr-latn', { button: 'Zalepi kao čist tekst', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Zalepi kao čist tekst' } ); diff --git a/plugins/pastetext/lang/sr.js b/plugins/pastetext/lang/sr.js index 6534ebe0f5e..03eea850c8d 100644 --- a/plugins/pastetext/lang/sr.js +++ b/plugins/pastetext/lang/sr.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sr', { button: 'Залепи као чист текст', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Залепи као чист текст' } ); diff --git a/plugins/pastetext/lang/sv.js b/plugins/pastetext/lang/sv.js index d2321ef6368..dbd11c697a6 100644 --- a/plugins/pastetext/lang/sv.js +++ b/plugins/pastetext/lang/sv.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'sv', { button: 'Klistra in som vanlig text', - pasteNotification: 'Din webbläsare tillåter dig inte att klistra in vanlig text på detta vis. Tryck på %1 för att klistra in.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Klistra in som vanlig text' } ); diff --git a/plugins/pastetext/lang/th.js b/plugins/pastetext/lang/th.js index 47e55aba89f..12a219eb5a8 100644 --- a/plugins/pastetext/lang/th.js +++ b/plugins/pastetext/lang/th.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'th', { button: 'วางแบบตัวอักษรธรรมดา', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'วางแบบตัวอักษรธรรมดา' } ); diff --git a/plugins/pastetext/lang/tr.js b/plugins/pastetext/lang/tr.js index af26d37d5c7..cc3afb174d1 100644 --- a/plugins/pastetext/lang/tr.js +++ b/plugins/pastetext/lang/tr.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'tr', { button: 'Düz Metin Olarak Yapıştır', - pasteNotification: 'Web tarayıcınız bu şekilde düz metni yapıştırmanıza izin vermiyor. Yapıştırmak için %1 basınız.', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Düz Metin Olarak Yapıştır' } ); diff --git a/plugins/pastetext/lang/tt.js b/plugins/pastetext/lang/tt.js index 4d2502cb779..1189460c8a8 100644 --- a/plugins/pastetext/lang/tt.js +++ b/plugins/pastetext/lang/tt.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'tt', { button: 'Форматлаусыз текст өстәү', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Форматлаусыз текст өстәү' } ); diff --git a/plugins/pastetext/lang/ug.js b/plugins/pastetext/lang/ug.js index 6a6a10860c1..2b4d3483a30 100644 --- a/plugins/pastetext/lang/ug.js +++ b/plugins/pastetext/lang/ug.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'ug', { button: 'پىچىمى يوق تېكىست سۈپىتىدە چاپلا', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'پىچىمى يوق تېكىست سۈپىتىدە چاپلا' } ); diff --git a/plugins/pastetext/lang/uk.js b/plugins/pastetext/lang/uk.js index 3d958eccab9..7e70cefd780 100644 --- a/plugins/pastetext/lang/uk.js +++ b/plugins/pastetext/lang/uk.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'uk', { button: 'Вставити тільки текст', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Вставити тільки текст' } ); diff --git a/plugins/pastetext/lang/vi.js b/plugins/pastetext/lang/vi.js index 138914d0c98..d09a543213a 100644 --- a/plugins/pastetext/lang/vi.js +++ b/plugins/pastetext/lang/vi.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'vi', { button: 'Dán theo định dạng văn bản thuần', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: 'Dán theo định dạng văn bản thuần' } ); diff --git a/plugins/pastetext/lang/zh-cn.js b/plugins/pastetext/lang/zh-cn.js index 0a8d5efd6c6..c74196009a0 100644 --- a/plugins/pastetext/lang/zh-cn.js +++ b/plugins/pastetext/lang/zh-cn.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'zh-cn', { button: '粘贴为无格式文本', - pasteNotification: '您的浏览器不允许用此方式粘贴成纯文本,要粘贴请按 %1。', + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: '粘贴为无格式文本' } ); diff --git a/plugins/pastetext/lang/zh.js b/plugins/pastetext/lang/zh.js index f07cc0fc978..7a4db48cd0c 100644 --- a/plugins/pastetext/lang/zh.js +++ b/plugins/pastetext/lang/zh.js @@ -4,6 +4,6 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ CKEDITOR.plugins.setLang( 'pastetext', 'zh', { button: '貼成純文字', - pasteNotification: 'Your browser does not allow you to paste plain text this way. Press %1 to paste.', // MISSING + pasteNotification: 'Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.', // MISSING title: '貼成純文字' } ); From be6d2fc8105c6adc3eb7a04d9c545eb28e84abae Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Wed, 7 Feb 2018 19:58:51 +0100 Subject: [PATCH 601/642] Updated target release for cloudservices plugin. --- plugins/cloudservices/plugin.js | 6 +++--- tests/plugins/cloudservices/manual/errors.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/cloudservices/plugin.js b/plugins/cloudservices/plugin.js index 1e99def5f6e..b83aedb8975 100644 --- a/plugins/cloudservices/plugin.js +++ b/plugins/cloudservices/plugin.js @@ -18,7 +18,7 @@ * guaranteed to be available in dependent plugin's {@link CKEDITOR.pluginDefinition#beforeInit beforeInit}, * {@link CKEDITOR.pluginDefinition#init init} and {@link CKEDITOR.pluginDefinition#afterInit} methods. * - * @since 4.8.0 + * @since 4.9.0 * @class CKEDITOR.plugins.cloudservices.cloudServicesLoader * @extends CKEDITOR.fileTools.fileLoader * @constructor @@ -122,7 +122,7 @@ /** * Endpoint URL for [Cloud Services](https://ckeditor.com/ckeditor-cloud-services) uploads. * - * @since 4.8.0 + * @since 4.9.0 * @cfg {String} [cloudServices_url=''] * @member CKEDITOR.config */ @@ -130,7 +130,7 @@ /** * Token used for [Cloud Services](https://ckeditor.com/ckeditor-cloud-services) authentication. * - * @since 4.8.0 + * @since 4.9.0 * @cfg {String} [cloudServices_token=''] * @member CKEDITOR.config */ diff --git a/tests/plugins/cloudservices/manual/errors.md b/tests/plugins/cloudservices/manual/errors.md index 8e393fcf8d2..07d27630fcf 100644 --- a/tests/plugins/cloudservices/manual/errors.md +++ b/tests/plugins/cloudservices/manual/errors.md @@ -1,4 +1,4 @@ -@bender-tags: 4.8.0, feature, 932 +@bender-tags: 4.9.0, feature, 932 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, toolbar, cloudservices From 0c780c2872d8f7f7e05d4360c93027b3916a7b91 Mon Sep 17 00:00:00 2001 From: Kajetan Litwinowicz Date: Thu, 8 Feb 2018 11:38:01 +0100 Subject: [PATCH 602/642] Removed leftover assert that tests for removed propety --- tests/plugins/contextmenu/integration.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/plugins/contextmenu/integration.js b/tests/plugins/contextmenu/integration.js index fa9128a23cb..a7f43795880 100644 --- a/tests/plugins/contextmenu/integration.js +++ b/tests/plugins/contextmenu/integration.js @@ -100,7 +100,6 @@ bot.editor.on( 'menuShow', function( evt ) { resume( function() { assert.isTrue( evt.data[ 0 ] instanceof CKEDITOR.ui.floatPanel, 'CKEDITOR.ui.panel available' ); - assert.isTrue( evt.data.menu instanceof CKEDITOR.menu, 'CKEDITOR.menu available' ); } ); } ); From f2c3e45037f64f1e0951d09945b65e010b81ec90 Mon Sep 17 00:00:00 2001 From: Kajetan Litwinowicz Date: Fri, 2 Feb 2018 14:50:03 +0100 Subject: [PATCH 603/642] Fixed: Upload tests for Easy Image are unstable on Firefox --- tests/plugins/imagebase/features/_helpers/tools.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/plugins/imagebase/features/_helpers/tools.js b/tests/plugins/imagebase/features/_helpers/tools.js index dd27cc831b9..9821fc886ee 100644 --- a/tests/plugins/imagebase/features/_helpers/tools.js +++ b/tests/plugins/imagebase/features/_helpers/tools.js @@ -52,7 +52,14 @@ } resume( function() { - callback( objToArray( editor.widgets.instances ), evt, uploadEvt ); + // Some tests occasionally fail in Firefox. After making them asynchronous tests passes. + if ( CKEDITOR.env.gecko ) { + wait( function() { + callback( objToArray( editor.widgets.instances ), evt, uploadEvt ); + }, 0 ); + } else { + callback( objToArray( editor.widgets.instances ), evt, uploadEvt ); + } } ); } From 260c8d82308fc24895efd7c452619ab6c5cd85fa Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 8 Feb 2018 12:43:18 +0100 Subject: [PATCH 604/642] Tests: helpers simplification, if possible all browsers should use same code path. That way code is easier to maintain. Also added a reference to the ticket. --- .../plugins/imagebase/features/_helpers/tools.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/tests/plugins/imagebase/features/_helpers/tools.js b/tests/plugins/imagebase/features/_helpers/tools.js index 9821fc886ee..5ff9a9153ef 100644 --- a/tests/plugins/imagebase/features/_helpers/tools.js +++ b/tests/plugins/imagebase/features/_helpers/tools.js @@ -51,16 +51,13 @@ } ); } - resume( function() { - // Some tests occasionally fail in Firefox. After making them asynchronous tests passes. - if ( CKEDITOR.env.gecko ) { - wait( function() { - callback( objToArray( editor.widgets.instances ), evt, uploadEvt ); - }, 0 ); - } else { + // Some tests occasionally fail in Firefox. After making them asynchronous tests passes (#1571). + // Unfortunately we weren't able to figure out a better way than adding a timeout. + setTimeout( function() { + resume( function() { callback( objToArray( editor.widgets.instances ), evt, uploadEvt ); - } - } ); + } ); + }, 0 ); } if ( options.fullLoad && widgets.length ) { From b1f1ff9e099caf0d3b48ae046089f440553e826b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Thu, 8 Feb 2018 10:57:53 +0100 Subject: [PATCH 605/642] Updated leftovers 4.8.0 tags to 4.9.0. --- plugins/easyimage/plugin.js | 6 +++--- plugins/imagebase/plugin.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/easyimage/plugin.js b/plugins/easyimage/plugin.js index 4eb1fc810fe..82b6b049037 100644 --- a/plugins/easyimage/plugin.js +++ b/plugins/easyimage/plugin.js @@ -471,7 +471,7 @@ /** * Namespace providing a set of helper functions for Easy Image plugin. * - * @since 4.8.0 + * @since 4.9.0 * @singleton * @class CKEDITOR.plugins.easyimage */ @@ -479,7 +479,7 @@ /** * Converts response from the server into proper `[srcset]` attribute. * - * @since 4.8.0 + * @since 4.9.0 * @private * @param {Object} srcs Sources list to be parsed. * @returns {String} `img[srcset]` attribute. @@ -547,7 +547,7 @@ * // This will cause plugin to convert any figure into a widget. * config.easyimage_class = null; * - * @since 4.8.0 + * @since 4.9.0 * @cfg {String/null} [easyimage_class='easyimage'] * @member CKEDITOR.config */ diff --git a/plugins/imagebase/plugin.js b/plugins/imagebase/plugin.js index 75970727b00..848dc34c9d1 100644 --- a/plugins/imagebase/plugin.js +++ b/plugins/imagebase/plugin.js @@ -627,7 +627,7 @@ * {@link CKEDITOR.plugins.widget.definition#upcast} callback. * * @abstract - * @since 4.8.0 + * @since 4.9.0 * @class CKEDITOR.plugins.imagebase.imageWidgetDefinition * @mixins CKEDITOR.plugins.widget.definition */ @@ -844,7 +844,7 @@ /** * Namespace providing a set of helper functions for working with image widgets. * - * @since 4.8.0 + * @since 4.9.0 * @singleton * @class CKEDITOR.plugins.imagebase */ From d46d5b317dfbb2f76fdf18e55e25cff6cf203003 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 8 Feb 2018 12:23:24 +0100 Subject: [PATCH 606/642] Explicitly remove additional clipboard plugins and move assertion into callback. --- tests/plugins/clipboard/mobilefix.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plugins/clipboard/mobilefix.js b/tests/plugins/clipboard/mobilefix.js index addfa4710ac..42d5c36af54 100644 --- a/tests/plugins/clipboard/mobilefix.js +++ b/tests/plugins/clipboard/mobilefix.js @@ -116,6 +116,7 @@ name: 'custom_button', config: { language: 'en', + removePlugins: 'pastetext,pastefromword', on: { pluginsLoaded: function( evt ) { var editor = evt.editor; @@ -125,12 +126,11 @@ command: 'paste', toolbar: 'clipboard,40' } ); - - arrayAssert.itemsAreEqual( [ 'Paste', 'CustomPaste' ], editor._.pasteButtons ); } } } }, function( bot ) { + arrayAssert.itemsAreEqual( [ 'Paste', 'CustomPaste' ], bot.editor._.pasteButtons ); assertTouchEnd( bot.editor, 'CustomPaste' ); } ); }; From 4df4823312fe7d470052e3559bfcc10e4423cbe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Thu, 8 Feb 2018 13:37:47 +0100 Subject: [PATCH 607/642] Tests: mock target when firing 'mouseup' event. --- tests/plugins/balloontoolbar/context/widgetdnd.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/plugins/balloontoolbar/context/widgetdnd.js b/tests/plugins/balloontoolbar/context/widgetdnd.js index 2f0cf82ec08..83b47b99c71 100644 --- a/tests/plugins/balloontoolbar/context/widgetdnd.js +++ b/tests/plugins/balloontoolbar/context/widgetdnd.js @@ -148,9 +148,6 @@ editor.focus(); try { - // Testing if widget is selected is meaningful only if it is not selected at the beginning. (https://dev.ckeditor.com/ticket/13129) - // assert.isNull( editor.widgets.focused, 'widget not focused before mousedown' ); - img.fire( 'mousedown', { $: { button: 0 @@ -161,7 +158,9 @@ // making if feel that there's a place for the widget to be dropped. editor.widgets.liner.showLine( editor.widgets.liner.addLine() ); - editor.document.fire( 'mouseup' ); + // Mouseup needs target so tableselection `evt.data.getTarget().getName` check inside + // its `fakeSelectionMouseHandler` method does not throw an error (#1614). + editor.document.fire( 'mouseup', new CKEDITOR.dom.event( { target: img } ) ); assert.areSame( widget, editor.widgets.focused, 'widget focused after mouseup' ); From 50e6ff9573139cb6311bdcc31dde80278b8011e0 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 8 Feb 2018 13:54:16 +0100 Subject: [PATCH 608/642] Add quote to the list of allowed characters. --- tests/plugins/button/buttonicon.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plugins/button/buttonicon.js b/tests/plugins/button/buttonicon.js index addd240d495..300e3bb6722 100644 --- a/tests/plugins/button/buttonicon.js +++ b/tests/plugins/button/buttonicon.js @@ -228,7 +228,7 @@ }, { name: 'test custom button icon with different basepath trailing slash', button: 'custom_btn8', - iconPath: /['|(]\/assets\/icons\.sample\.png/gi, + iconPath: /['|"|(]\/assets\/icons\.sample\.png/gi, config: { toolbar: [ [ 'custom_btn8' ] ], on: { @@ -244,7 +244,7 @@ }, { name: 'test custom button icon with different basepath trailing slash (hidpi)', button: 'custom_btn9', - iconPath: /['|(]\/assets\/hidpi\/icons\.sample\.png/gi, + iconPath: /['|"|(]\/assets\/hidpi\/icons\.sample\.png/gi, config: { toolbar: [ [ 'custom_btn9' ] ], on: { From 34578648e5af8144f43c2e0a98824b09358a0872 Mon Sep 17 00:00:00 2001 From: Kajetan Litwinowicz Date: Thu, 8 Feb 2018 13:45:09 +0100 Subject: [PATCH 609/642] Fixed: Failing test on builded version: tests/core/selection/fake --- tests/core/selection/fake.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/core/selection/fake.js b/tests/core/selection/fake.js index 581c4d8d11a..22fa29008ab 100644 --- a/tests/core/selection/fake.js +++ b/tests/core/selection/fake.js @@ -1074,12 +1074,16 @@ bender.test( { editor.setReadOnly( true ); bot.setData( '

[[placeholder]]

', function() { - var widget = editor.widgets.instances[ 0 ]; - + var widget = editor.widgets.instances[ 0 ], + domEvent = { + getKey: function() { + return false; + } + }; widget.focus(); - editor.fire( 'key', { keyCode: 8 } ); // backspace - editor.fire( 'key', { keyCode: 46 } ); // delete + editor.fire( 'key', { keyCode: 8, domEvent: domEvent } ); // backspace + editor.fire( 'key', { keyCode: 46, domEvent: domEvent } ); // delete assert.areEqual( '

[[placeholder]]

', editor.getData() ); } ); From d154e0b0e06d46f8ffa850afe7880dbf1ade6ce4 Mon Sep 17 00:00:00 2001 From: Tomasz Jakut Date: Thu, 8 Feb 2018 16:09:22 +0100 Subject: [PATCH 610/642] Add changelog entry about Easy Image. [ci skip] --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index d81f980019d..ef0a799f9a6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ New Features: +* [#932](https://github.com/ckeditor/ckeditor-dev/issues/932): Introduced [Easy Image](https://ckeditor.com/cke4/addon/easyimage) plugin. * [#1338](https://github.com/ckeditor/ckeditor-dev/issues/1338): Keystroke labels are displayed for function keys (like F7, F8). * [#933](https://github.com/ckeditor/ckeditor-dev/issues/933): [File Browser](https://ckeditor.com/cke4/addon/filebrowser) plugin can now upload files using XHR requests. This allows for setting custom HTTP headers using [`config.fileTools_requestHeaders`](http://docs.ckeditor.test/#!/api/CKEDITOR.config-cfg-fileTools_requestHeaders) configuration option. * [#1365](https://github.com/ckeditor/ckeditor-dev/issues/1365): [File Browser](https://ckeditor.com/cke4/addon/filebrowser) plugin uses XHR requests by default. From a424566a387ae019826f30200806ea951e7c19a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Thu, 8 Feb 2018 17:19:16 +0100 Subject: [PATCH 611/642] SCAYT/WSC changelog entry. [skip ci] --- CHANGES.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index ef0a799f9a6..b0ed5f01c96 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -40,6 +40,16 @@ API Changes: Other Changes: +* Updated [SCAYT](https://ckeditor.com/cke4/addon/scayt) (Spell Check As You Type) and [WebSpellChecker](https://ckeditor.com/cke4/addon/wsc) plugins: + * SCAYT [`scayt_minWordLength`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#scayt_minWordLength) configuration option now defaults to 3 instead of 4. + * SCAYT default number of suggested words on context menu changed to 3. + * [#90](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/90): Fixed: Selection is lost on link creation if SCAYT highlights the word. + * Fixed: SCAYT crashes when browser `localStorage` is disabled. + * [IE11] Fixed: `Unable to get property type of undefined or null reference` error in the browser console when SCAYT is disabled/enabled. + * [#46](https://github.com/WebSpellChecker/ckeditor-plugin-wsc/issues/46): Fixed: Editing is blocked when remote spell checker server is offline. + * Fixed: User Dictionary can't be created in WSC due to `You already have the dictionary` error. + * Fixed: Words with apostrophe `'` on the replacement make the WSC dialog inaccessible. + * Fixed: SCAYT/WSC causes `Uncaught TypeError` error in the browser console. * [#1337](https://github.com/ckeditor/ckeditor-dev/issues/1337): Update `samples` layout with new CKEditor 4 logo and color scheme. * [#1591](https://github.com/ckeditor/ckeditor-dev/issues/1591): CKBuilder and lang tools are now downloaded over HTTPS. Thanks to [August Detlefsen](https://github.com/augustd)! From 554254efd7cc04259919f015017da3e20f07a5a9 Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Mon, 29 Jan 2018 13:23:01 +0100 Subject: [PATCH 612/642] Ignore easyimage manual and unit test on unsupported environments. --- tests/plugins/easyimage/commands.js | 8 ++++++-- tests/plugins/easyimage/config.js | 10 ++++++++-- tests/plugins/easyimage/manual/_helpers/tools.js | 6 +++++- .../manual/balloontoolbar/balloontoolbar.html | 4 ++++ .../easyimage/manual/balloontoolbar/balloontoolbar.md | 1 + tests/plugins/easyimage/manual/captionflickering.html | 3 +++ tests/plugins/easyimage/manual/captionflickering.md | 1 + tests/plugins/easyimage/manual/dndimagetype.html | 3 +++ tests/plugins/easyimage/manual/dndimagetype.md | 1 + tests/plugins/easyimage/manual/easyimage.html | 3 +++ tests/plugins/easyimage/manual/easyimage.md | 1 + tests/plugins/easyimage/manual/figuresnoclass.html | 3 +++ tests/plugins/easyimage/manual/figuresnoclass.md | 1 + tests/plugins/easyimage/manual/imageoutline.html | 5 ++++- tests/plugins/easyimage/manual/imageoutline.md | 3 ++- tests/plugins/easyimage/manual/imagestretch.html | 2 +- tests/plugins/easyimage/manual/imagestretch.md | 1 + tests/plugins/easyimage/manual/pasteimagetype.html | 3 +++ tests/plugins/easyimage/manual/pasteimagetype.md | 1 + tests/plugins/easyimage/manual/progressbar.html | 2 +- tests/plugins/easyimage/manual/progressbar.md | 1 + tests/plugins/easyimage/manual/styles.html | 3 +++ tests/plugins/easyimage/manual/styles.md | 1 + tests/plugins/easyimage/manual/undo.html | 2 +- tests/plugins/easyimage/manual/undo.md | 1 + tests/plugins/easyimage/manual/upload.html | 2 +- tests/plugins/easyimage/manual/upload.md | 1 + tests/plugins/easyimage/tools.js | 5 +++++ tests/plugins/easyimage/widget.js | 10 ++++++++-- 29 files changed, 75 insertions(+), 13 deletions(-) diff --git a/tests/plugins/easyimage/commands.js b/tests/plugins/easyimage/commands.js index 9ce85d89ee2..8fed53468cb 100644 --- a/tests/plugins/easyimage/commands.js +++ b/tests/plugins/easyimage/commands.js @@ -1,7 +1,7 @@ /* bender-tags: editor,widget */ /* bender-ckeditor-plugins: easyimage,toolbar,contextmenu,undo */ -/* bender-include: _helpers/tools.js */ -/* global easyImageTools */ +/* bender-include: _helpers/tools.js,manual/_helpers/tools.js */ +/* global easyImageTools, isUnsupportedEnvironment */ ( function() { 'use strict'; @@ -24,6 +24,10 @@ widgetHtml = '
foo
Test image
', tests = { setUp: function() { + if ( isUnsupportedEnvironment() ) { + assert.ignore(); + } + if ( CKEDITOR.env.ie ) { CKEDITOR.dom.element.prototype.getClientRect = function() { return { diff --git a/tests/plugins/easyimage/config.js b/tests/plugins/easyimage/config.js index 09d2f375daa..be3dbe9a0a8 100644 --- a/tests/plugins/easyimage/config.js +++ b/tests/plugins/easyimage/config.js @@ -1,7 +1,7 @@ /* bender-tags: editor,widget */ /* bender-ckeditor-plugins: easyimage,toolbar,contextmenu */ -/* bender-include: ../widget/_helpers/tools.js */ -/* global widgetTestsTools */ +/* bender-include: ../widget/_helpers/tools.js,./manual/_helpers/tools.js */ +/* global widgetTestsTools, isUnsupportedEnvironment */ ( function() { 'use strict'; @@ -112,6 +112,12 @@ } bender.test( { + setUp: function() { + if ( isUnsupportedEnvironment() ) { + assert.ignore(); + } + }, + 'test easyimage_class - changed': function() { widgetTestsTools.assertWidget( { count: 1, diff --git a/tests/plugins/easyimage/manual/_helpers/tools.js b/tests/plugins/easyimage/manual/_helpers/tools.js index c77d2461863..851c9892a5c 100644 --- a/tests/plugins/easyimage/manual/_helpers/tools.js +++ b/tests/plugins/easyimage/manual/_helpers/tools.js @@ -1,4 +1,4 @@ -/* exported getToken, easyImageTools */ +/* exported getToken, easyImageTools, isUnsupportedEnvironment */ /* global console */ // WARNING: The URL below should not be used for any other purpose than Easy Image plugin development. @@ -44,3 +44,7 @@ function getToken( callback ) { var easyImageTools = { CLOUD_SERVICES_UPLOAD_GATEWAY: 'https://files.cke-cs.com/upload/' }; + +function isUnsupportedEnvironment() { + return CKEDITOR.env.ie && CKEDITOR.env.version < 11; +} diff --git a/tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.html b/tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.html index 97d1169d037..33d32756083 100644 --- a/tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.html +++ b/tests/plugins/easyimage/manual/balloontoolbar/balloontoolbar.html @@ -29,6 +29,10 @@

Inline editor

diff --git a/tests/plugins/easyimage/manual/dndimagetype.md b/tests/plugins/easyimage/manual/dndimagetype.md index 3f4a06f9c7f..bbc3546c14e 100644 --- a/tests/plugins/easyimage/manual/dndimagetype.md +++ b/tests/plugins/easyimage/manual/dndimagetype.md @@ -1,6 +1,7 @@ @bender-tags: 4.9.0, bug, easyimage, 932, tp3163 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, htmlwriter, elementspath +@bender-include: ./_helpers/tools.js 1. Focus widget. 2. Switch it to full size. diff --git a/tests/plugins/easyimage/manual/easyimage.html b/tests/plugins/easyimage/manual/easyimage.html index d880e0da1eb..a1a5bead26a 100644 --- a/tests/plugins/easyimage/manual/easyimage.html +++ b/tests/plugins/easyimage/manual/easyimage.html @@ -29,6 +29,9 @@

Inline editor

\ No newline at end of file + diff --git a/tests/plugins/easyimage/manual/imageoutline.md b/tests/plugins/easyimage/manual/imageoutline.md index 67bfa4e3e8e..ff7f4bc7094 100644 --- a/tests/plugins/easyimage/manual/imageoutline.md +++ b/tests/plugins/easyimage/manual/imageoutline.md @@ -1,6 +1,7 @@ @bender-tags: 4.9.0, bug, 932, tp3302 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, link +@bender-include: ./_helpers/tools.js Check if linked images have correct outlines. @@ -10,4 +11,4 @@ Linked image should have correct outline aligned nicely with the rest of a widge ## Unexpected -The outline link is overflowing the widget, thus not aligning perfectly with the caption. \ No newline at end of file +The outline link is overflowing the widget, thus not aligning perfectly with the caption. diff --git a/tests/plugins/easyimage/manual/imagestretch.html b/tests/plugins/easyimage/manual/imagestretch.html index e1e93894435..8516586afc1 100644 --- a/tests/plugins/easyimage/manual/imagestretch.html +++ b/tests/plugins/easyimage/manual/imagestretch.html @@ -23,7 +23,7 @@

Sample editor

diff --git a/tests/plugins/easyimage/manual/pasteimagetype.md b/tests/plugins/easyimage/manual/pasteimagetype.md index 4d298ad42fe..f54e5ae5098 100644 --- a/tests/plugins/easyimage/manual/pasteimagetype.md +++ b/tests/plugins/easyimage/manual/pasteimagetype.md @@ -1,6 +1,7 @@ @bender-tags: 4.9.0, bug, easyimage, 932, tp3162 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, floatingspace, toolbar, easyimage, htmlwriter, elementspath +@bender-include: ./_helpers/tools.js 1. Focus widget. 2. Switch it to full size. diff --git a/tests/plugins/easyimage/manual/progressbar.html b/tests/plugins/easyimage/manual/progressbar.html index 15494d28e34..c937d6acedd 100644 --- a/tests/plugins/easyimage/manual/progressbar.html +++ b/tests/plugins/easyimage/manual/progressbar.html @@ -24,7 +24,7 @@

Sample editor

\ No newline at end of file + diff --git a/tests/plugins/cloudservices/manual/errors.md b/tests/plugins/cloudservices/manual/errors.md index 07d27630fcf..16de15c0c1f 100644 --- a/tests/plugins/cloudservices/manual/errors.md +++ b/tests/plugins/cloudservices/manual/errors.md @@ -1,6 +1,7 @@ @bender-tags: 4.9.0, feature, 932 @bender-ui: collapsed @bender-ckeditor-plugins: sourcearea, wysiwygarea, toolbar, cloudservices +@bender-include: ../../easyimage/manual/_helpers/tools.js 1. Open browser console. 1. Click `Test undefinded URL` button. @@ -9,4 +10,4 @@ In console we should have information about error with code `cloudservices-no-ur 1. Click `Test undefinded TOKEN` button. -In console we should have information about error with code `cloudservices-no-token`. \ No newline at end of file +In console we should have information about error with code `cloudservices-no-token`. From 45891fe75b17493d6497eca20029b16dbf83afd8 Mon Sep 17 00:00:00 2001 From: Mateusz Samsel Date: Mon, 29 Jan 2018 13:51:55 +0100 Subject: [PATCH 614/642] Fix one manual test which wasn't ignored. --- tests/plugins/easyimage/manual/progressbar.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/plugins/easyimage/manual/progressbar.html b/tests/plugins/easyimage/manual/progressbar.html index c937d6acedd..edc7dc025e6 100644 --- a/tests/plugins/easyimage/manual/progressbar.html +++ b/tests/plugins/easyimage/manual/progressbar.html @@ -1,4 +1,9 @@ +

Classic editor

@@ -24,10 +29,6 @@

Sample editor

+ +

Go on, drop some files below:

@@ -5,10 +11,6 @@ -

Go on, drop some files below:

- diff --git a/tests/plugins/imagebase/features/manual/uploadsimple.html b/tests/plugins/imagebase/features/manual/uploadsimple.html index cca9243e70a..48d256061e4 100644 --- a/tests/plugins/imagebase/features/manual/uploadsimple.html +++ b/tests/plugins/imagebase/features/manual/uploadsimple.html @@ -3,7 +3,6 @@

- \ No newline at end of file + diff --git a/tests/plugins/easyimage/manual/customprogressbar.md b/tests/plugins/easyimage/manual/customprogressbar.md index 5b0872d8d33..3e49677ee0d 100644 --- a/tests/plugins/easyimage/manual/customprogressbar.md +++ b/tests/plugins/easyimage/manual/customprogressbar.md @@ -1,7 +1,7 @@ @bender-tags: 4.9.0, feature, 932 @bender-ui: collapsed @bender-ckeditor-plugins: wysiwygarea, easyimage, autogrow -@bender-include: ./_helpers/tools.js,../_helpers/tools.js +@bender-include: ../_helpers/tools.js # Custom Progress diff --git a/tests/plugins/easyimage/manual/customstyleicons.html b/tests/plugins/easyimage/manual/customstyleicons.html index 1cba3a22166..e830629d95b 100644 --- a/tests/plugins/easyimage/manual/customstyleicons.html +++ b/tests/plugins/easyimage/manual/customstyleicons.html @@ -29,7 +29,7 @@

Inline editor

Classic editor

@@ -29,6 +23,9 @@

Sample editor

diff --git a/tests/plugins/imagebase/features/manual/upload.md b/tests/plugins/imagebase/features/manual/upload.md index 9c1638fde4a..64e9584f23b 100644 --- a/tests/plugins/imagebase/features/manual/upload.md +++ b/tests/plugins/imagebase/features/manual/upload.md @@ -1,7 +1,7 @@ @bender-tags: 4.9.0, feature, 932 @bender-ui: collapsed @bender-ckeditor-plugins: wysiwygarea, toolbar, imagebase, elementspath, placeholder, cloudservices -@bender-include: %BASE_PATH%/plugins/easyimage/manual/_helpers/tools.js +@bender-include: %BASE_PATH%/plugins/easyimage/_helpers/tools.js ## Upload Feature diff --git a/tests/plugins/imagebase/features/manual/uploadsimple.html b/tests/plugins/imagebase/features/manual/uploadsimple.html index 48d256061e4..14f9f4ec3eb 100644 --- a/tests/plugins/imagebase/features/manual/uploadsimple.html +++ b/tests/plugins/imagebase/features/manual/uploadsimple.html @@ -4,11 +4,11 @@ diff --git a/tests/plugins/image2/manual/aspectratio.md b/tests/plugins/image2/manual/aspectratio.md new file mode 100644 index 00000000000..7405c529f6d --- /dev/null +++ b/tests/plugins/image2/manual/aspectratio.md @@ -0,0 +1,17 @@ +@bender-tags: 4.9.0, bug, 1348 +@bender-ui: collapsed +@bender-ckeditor-plugins: wysiwygarea, sourcearea, toolbar, image2, link, undo + +1. Double click on the image to popup dialog. +2. Change url of the image to `/tests//_assets/lena.jpg`. +3. Ensure that the image is locked. +4. Change `width` to `400`. +5. Click `OK` button. + +## Expected + +The image has preserved aspect ratio. + +## Unexpected + +The image is streched, aspect ratio is not preserved. From 13d72a57e33ccafbae19b2c6925fe45099829de7 Mon Sep 17 00:00:00 2001 From: Jacek Bogdanski Date: Fri, 2 Feb 2018 11:51:50 +0100 Subject: [PATCH 639/642] Fixed image2 dialog width/height refresh. --- plugins/image2/dialogs/image2.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/image2/dialogs/image2.js b/plugins/image2/dialogs/image2.js index 4bddff0b77f..a9d6270c03e 100644 --- a/plugins/image2/dialogs/image2.js +++ b/plugins/image2/dialogs/image2.js @@ -153,10 +153,10 @@ CKEDITOR.dialog.add( 'image2', function( editor ) { heightField.setValue( editor.config.image2_prefillDimensions === false ? 0 : height ); // Cache the new width. - preLoadedWidth = width; + preLoadedWidth = domWidth = width; // Cache the new height. - preLoadedHeight = height; + preLoadedHeight = domHeight = height; // Check for new lock value if image exist. toggleLockRatio( helpers.checkHasNaturalRatio( image ) ); From 39f55f7fb3fd59314e9f280a8f3667a626ab7964 Mon Sep 17 00:00:00 2001 From: Jacek Bogdanski Date: Mon, 5 Feb 2018 16:06:02 +0100 Subject: [PATCH 640/642] Added tests. --- plugins/image2/dialogs/image2.js | 4 ++-- tests/plugins/image2/editing.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/plugins/image2/dialogs/image2.js b/plugins/image2/dialogs/image2.js index a9d6270c03e..216fbda5651 100644 --- a/plugins/image2/dialogs/image2.js +++ b/plugins/image2/dialogs/image2.js @@ -152,10 +152,10 @@ CKEDITOR.dialog.add( 'image2', function( editor ) { // Fill height field with the height of the new image. heightField.setValue( editor.config.image2_prefillDimensions === false ? 0 : height ); - // Cache the new width. + // Cache the new width and update initial cache (#1348). preLoadedWidth = domWidth = width; - // Cache the new height. + // Cache the new height and update initial cache (#1348). preLoadedHeight = domHeight = height; // Check for new lock value if image exist. diff --git a/tests/plugins/image2/editing.js b/tests/plugins/image2/editing.js index 2e9cd357a46..34e855e8bd9 100644 --- a/tests/plugins/image2/editing.js +++ b/tests/plugins/image2/editing.js @@ -74,6 +74,37 @@ wait(); }, + // #1348 + 'test image dialog has correct aspect ratio after src change': function() { + var bot = this.editorBot, + editor = bot.editor; + + editor.once( 'dialogShow', function( evt ) { + var dialog = evt.data, + widthInput = CKEDITOR.document.findOne( '#' + dialog.getContentElement( 'info', 'width' )._.inputId ); + + dialog.setValueOf( 'info', 'src', '_assets/foo.png' ); + downloadImage( '_assets/foo.png', assertImage ); + + function assertImage() { + widthInput.fire( 'keyup', new CKEDITOR.dom.event( {} ) ); // It will force image dialog to recalculate width and height. + + assert.areEqual( 50, dialog.getContentElement( 'info', 'width' ).getValue(), 'invalid width' ); + assert.areEqual( 120, dialog.getContentElement( 'info', 'height' ).getValue(), 'invalid height' ); + + dialog.hide(); + + resume(); + } + } ); + + bot.setData( widgetsHtml, function() { + getWidgetById( editor, 'y' ).focus(); + editor.execCommand( 'image' ); + wait(); + } ); + }, + 'test create inline widget with a global command': function() { var editorBot = this.editorBot, onResume = function( dialog ) { From 757600f7f3b0ae23cfcfc446fdfdcf27fe1377cf Mon Sep 17 00:00:00 2001 From: Jacek Bogdanski Date: Mon, 5 Feb 2018 16:12:02 +0100 Subject: [PATCH 641/642] Changelog entry. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 1f4cd8c4454..568e0c36823 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -35,6 +35,7 @@ Fixed Issues: * [#1516](https://github.com/ckeditor/ckeditor-dev/issues/1516): Fixed: Fake selection allows removing content in read-only mode using the Backspace and Delete keys. * [#1570](https://github.com/ckeditor/ckeditor-dev/issues/1570): Fixed: Fake selection allows cutting content in read-only mode using the Ctrl/Cmd + X keys. * [#1363](https://github.com/ckeditor/ckeditor-dev/issues/1363): Fixed: Paste notification is unclear and it might confuse users. +* [#1348](https://github.com/ckeditor/ckeditor-dev/issues/1348): Fixed: [Enhanced Image](https://ckeditor.com/cke4/addon/image2) aspect ratio locking uses old width and height on `src` change. API Changes: From f8fbeb910e40955d714159b24598f6c0f9dc6606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Fri, 16 Feb 2018 11:52:52 +0100 Subject: [PATCH 642/642] Changelog correction. [skip ci] --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 568e0c36823..b40470172ba 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -35,7 +35,7 @@ Fixed Issues: * [#1516](https://github.com/ckeditor/ckeditor-dev/issues/1516): Fixed: Fake selection allows removing content in read-only mode using the Backspace and Delete keys. * [#1570](https://github.com/ckeditor/ckeditor-dev/issues/1570): Fixed: Fake selection allows cutting content in read-only mode using the Ctrl/Cmd + X keys. * [#1363](https://github.com/ckeditor/ckeditor-dev/issues/1363): Fixed: Paste notification is unclear and it might confuse users. -* [#1348](https://github.com/ckeditor/ckeditor-dev/issues/1348): Fixed: [Enhanced Image](https://ckeditor.com/cke4/addon/image2) aspect ratio locking uses old width and height on `src` change. +* [#1348](https://github.com/ckeditor/ckeditor-dev/issues/1348): Fixed: [Enhanced Image](https://ckeditor.com/cke4/addon/image2) plugin aspect ratio locking uses old width and height on image URL change. API Changes: