diff --git a/composer.json b/composer.json index c51de557a4df5b3aa30daaec11190323db9ce849..49a331bab93e69afe4ca5b24e0835f188a6e6352 100644 --- a/composer.json +++ b/composer.json @@ -135,7 +135,8 @@ "drupal/entity_browser_enhanced": "1.0-beta5", "drupal/vmi": "1.0-beta2", "drupal/varbase_bootstrap_paragraphs": "4.x-dev#acd6df8043ffa883aed7913427a98f6845eb23ce", - "drupal/varbase_editor": "4.15", + "drupal/ckeditor_media_embed": "1.1", + "drupal/varbase_editor": "4.x-dev", "drupal/varbase_heroslider_media": "4.0-beta8", "drupal/varbase_carousels": "4.0-beta2", "drupal/varbase_total_control": "1.0-beta4", @@ -280,6 +281,10 @@ "drupal/responsive_preview": { "Issue #2899640: Responsive Preview shows 'Page not found' when multilingual site is enabled with Path-prefix setting": "https://www.drupal.org/files/issues/responsive_preview_with_path_prefix-2899640-2_0.patch" + }, + "drupal/ckeditor_media_embed": { + "Issue #2900313: Add ability to embed tweets and other rich content in WYSIWYG": + "https://www.drupal.org/files/issues/embed_rich_content_in_WYSIWYG-2900313-2.patch" } } } diff --git a/css/admin-toolbar-tools.css b/css/admin-toolbar-tools.css index 720028aafa1f02bf631b01c7f7fe77a2511fc6e8..f8b6a6c10b7fc403499054e050fc9c3a3ef0ab34 100644 --- a/css/admin-toolbar-tools.css +++ b/css/admin-toolbar-tools.css @@ -8,3 +8,7 @@ .adminimal-admin-toolbar .toolbar-icon-admin-toolbar-tools-help:hover:before { background-image: url(../files/images/varbase-x-small-emblem-white.png); } + +span .cke_button__embed_icon { + background-image:url('../images/embed.png') !important; +} diff --git a/drupal-org.make b/drupal-org.make index 25c989a761d084585b6028ccacdf28a761e62db3..03ed59e694b4ff94a427b10478433ad028101c2b 100644 --- a/drupal-org.make +++ b/drupal-org.make @@ -256,6 +256,11 @@ projects[login_destination][download][url] = https://git.drupal.org/project/logi projects[login_destination][download][revision] = 98892eb84eba6fe69d4fc48dc5b1fdaccb21c8a7 projects[login_destination][download][branch] = 8.x-1.x +projects[ckeditor_media_embed][type] = module +projects[ckeditor_media_embed][version] = 1.1 +;; Issue #2900313: Add ability to embed tweets and other rich content in WYSIWYG +projects[ckeditor_media_embed][patch][] = https://www.drupal.org/files/issues/embed_rich_content_in_WYSIWYG-2900313-2.patch + ;;;;;;;;;;;;;;;;;;;;; ;; Contrib modules for Varbase SEO. ;;;;;;;;;;;;;;;;;;;;; @@ -430,7 +435,7 @@ projects[total_control][version] = 2.0-alpha2 ;;;;;;;;;;;;;;;;;;;;; projects[varbase_editor][type] = module -projects[varbase_editor][version] = 4.15 +projects[varbase_editor][version] = 4.x-dev projects[varbase_heroslider_media][type] = module projects[varbase_heroslider_media][version] = 4.0-beta8 diff --git a/images/embed.png b/images/embed.png new file mode 100644 index 0000000000000000000000000000000000000000..a2f8f853ac6d4efed31e0b6a3d70f104d48423ee Binary files /dev/null and b/images/embed.png differ diff --git a/libraries/ckeditor/plugins/autoembed/lang/az.js b/libraries/ckeditor/plugins/autoembed/lang/az.js new file mode 100644 index 0000000000000000000000000000000000000000..e6da287ac70feda72d499f4c3f632df2ce6277b5 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/az.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'az', { + embeddingInProgress: 'Dahil etdiyiniz link yerləşdirilir...', + embeddingFailed: 'Bu cür linki avtomatik yerləşdirmÉ™k mövcud deyil.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/ca.js b/libraries/ckeditor/plugins/autoembed/lang/ca.js new file mode 100644 index 0000000000000000000000000000000000000000..8b700d96edcdd62028985d8d37cf73f0dce6296a --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/ca.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'ca', { + embeddingInProgress: 'Provant d\'incrustar URL copiada...', + embeddingFailed: 'Aquesta URL no es pot incrustar automà ticament.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/cs.js b/libraries/ckeditor/plugins/autoembed/lang/cs.js new file mode 100644 index 0000000000000000000000000000000000000000..9f0a4fffc21182dbfc7d4c702e473946aa980054 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/cs.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'cs', { + embeddingInProgress: 'Pokus o vnoÅ™enà vložené URL', + embeddingFailed: 'Tato URL nemůže být automaticky vnoÅ™ena.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/de-ch.js b/libraries/ckeditor/plugins/autoembed/lang/de-ch.js new file mode 100644 index 0000000000000000000000000000000000000000..3c69faa971f6d35df3c2d5ef9566297c056f073c --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/de-ch.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'de-ch', { + embeddingInProgress: 'Einbetten der eingefügten URL wird versucht...', + embeddingFailed: 'Diese URL konnte nicht automatisch eingebettet werden.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/de.js b/libraries/ckeditor/plugins/autoembed/lang/de.js new file mode 100644 index 0000000000000000000000000000000000000000..c229c1d9f38858bda848125470d779311df2b226 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/de.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'de', { + embeddingInProgress: 'Einbetten der eingefügten URL wird versucht...', + embeddingFailed: 'Diese URL konnte nicht automatisch eingebettet werden.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/en.js b/libraries/ckeditor/plugins/autoembed/lang/en.js new file mode 100644 index 0000000000000000000000000000000000000000..c7123838e859dc6baccdd6e159d96e0cfd76b38d --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/en.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'en', { + embeddingInProgress: 'Trying to embed pasted URL...', + embeddingFailed: 'This URL could not be automatically embedded.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/eo.js b/libraries/ckeditor/plugins/autoembed/lang/eo.js new file mode 100644 index 0000000000000000000000000000000000000000..5afc0440db33fa9eeda2ff416076509dffbab8d3 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/eo.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'eo', { + embeddingInProgress: 'Provas enkorpigi la algluitan URL ...', + embeddingFailed: 'Ne eblis enkorpigi aÅtomate tiun URL.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/es-mx.js b/libraries/ckeditor/plugins/autoembed/lang/es-mx.js new file mode 100644 index 0000000000000000000000000000000000000000..6dc8558c3506ddb5a854f96dd93582d67232f66e --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/es-mx.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'es-mx', { + embeddingInProgress: 'Tratando de empotrar la URL pegada...', + embeddingFailed: 'Esta URL no puede ser empotrada automáticamente.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/es.js b/libraries/ckeditor/plugins/autoembed/lang/es.js new file mode 100644 index 0000000000000000000000000000000000000000..e9cf8c90bb7d89d027f678c1ebfc7ac9c9a491df --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/es.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'es', { + embeddingInProgress: 'Intentando incrustar URL pegada...', + embeddingFailed: 'Está URL no pudo ser automáticamente incrustada.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/eu.js b/libraries/ckeditor/plugins/autoembed/lang/eu.js new file mode 100644 index 0000000000000000000000000000000000000000..b6291d809beeec1f2e97d25953f7d30d4bb9a8ac --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/eu.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'eu', { + embeddingInProgress: 'Itsatsitako URLa txertatzen saiatzen...', + embeddingFailed: 'URL hau ezin izan da automatikoki txertatu.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/fr.js b/libraries/ckeditor/plugins/autoembed/lang/fr.js new file mode 100644 index 0000000000000000000000000000000000000000..77c20434f66061e22067d0ae3bbc8738c0775c33 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/fr.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'fr', { + embeddingInProgress: 'Incorporation de l\'URL collée...', + embeddingFailed: 'Cette URL n\'a pas pu être incorporée automatiquement.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/gl.js b/libraries/ckeditor/plugins/autoembed/lang/gl.js new file mode 100644 index 0000000000000000000000000000000000000000..844a7c580d1a1e599df77b66a1309bfa076a6488 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/gl.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'gl', { + embeddingInProgress: 'Tentando incrustar URL pegado...', + embeddingFailed: 'Non foi posÃbel incrustar automaticamente este URL.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/hr.js b/libraries/ckeditor/plugins/autoembed/lang/hr.js new file mode 100644 index 0000000000000000000000000000000000000000..1f5335f6d1a035c725ad0e59ce7a5884bfbcdc61 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/hr.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'hr', { + embeddingInProgress: 'PokuÅ¡avam umetnuti URL...', + embeddingFailed: 'URL nije moguće umetnuti automatski.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/hu.js b/libraries/ckeditor/plugins/autoembed/lang/hu.js new file mode 100644 index 0000000000000000000000000000000000000000..8d54463bf3b0ccee56b0228e7930f53baab3f8d0 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/hu.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'hu', { + embeddingInProgress: 'A beillesztett URL beágyazásának megkÃsérlése...', + embeddingFailed: 'Ezt az URL-t nem lehet automatikusan beágyazni.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/it.js b/libraries/ckeditor/plugins/autoembed/lang/it.js new file mode 100644 index 0000000000000000000000000000000000000000..9f037431cedf60e545427c9dfe754aca3c7dd46f --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/it.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'it', { + embeddingInProgress: 'Prova a incorporare l\'URL incollato...', + embeddingFailed: 'Non è stato possibile incorporare automaticamente questo URL.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/ja.js b/libraries/ckeditor/plugins/autoembed/lang/ja.js new file mode 100644 index 0000000000000000000000000000000000000000..0650e71ed05486dbc2a3bc713593e0643d4848a1 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/ja.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'ja', { + embeddingInProgress: '貼り付ã‘られãŸURLを埋ã‚è¾¼ã¿ä¸...', + embeddingFailed: 'ã“ã®URLã¯è‡ªå‹•çš„ã«åŸ‹ã‚込むã“ã¨ãŒå‡ºæ¥ã¾ã›ã‚“。' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/km.js b/libraries/ckeditor/plugins/autoembed/lang/km.js new file mode 100644 index 0000000000000000000000000000000000000000..ca390fd7bf365077215e7af317d4cb9675813b8b --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/km.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'km', { + embeddingInProgress: 'កំពុង​ព្យាយាម​បង្កប់ URL ដែល​បាន​បិទភ្ជាប់...', + embeddingFailed: 'មិន​អាច​បង្កប់ URL áž“áŸáŸ‡â€‹ážŠáŸ„យ​ស្វáŸáž™áž”្រវážáŸ’ážáž·â€‹áž‘áŸáŸ”' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/ko.js b/libraries/ckeditor/plugins/autoembed/lang/ko.js new file mode 100644 index 0000000000000000000000000000000000000000..d6ddeb55dc39a2049c12e8790cda5ca778fd0581 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/ko.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'ko', { + embeddingInProgress: 'ë¶™ì—¬ë„£ì€ URL 첨부 ì‹œë„ ì¤‘...', + embeddingFailed: 'ì´ URLì€ ìžë™ìœ¼ë¡œ ì²¨ë¶€í• ìˆ˜ 없습니다.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/ku.js b/libraries/ckeditor/plugins/autoembed/lang/ku.js new file mode 100644 index 0000000000000000000000000000000000000000..d2a2a5080d7f3043f34690d4de6e7924542ba3f7 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/ku.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'ku', { + embeddingInProgress: 'Ù„Û•Ù‡Û•ÙˆÚµÛŒ لکاندنی بەستەری ناونیشانە...', + embeddingFailed: 'ئەم بەستەرە خۆکارانە ناتواندرێت بخرێتە ناوێ.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/mk.js b/libraries/ckeditor/plugins/autoembed/lang/mk.js new file mode 100644 index 0000000000000000000000000000000000000000..0e7da04355d976958eecf20c0a9d257ffbf6a5ce --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/mk.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'mk', { + embeddingInProgress: 'Обид за вметнување копирано URL...', + embeddingFailed: 'Ова URL не може да биде вметнато автоматÑки.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/nb.js b/libraries/ckeditor/plugins/autoembed/lang/nb.js new file mode 100644 index 0000000000000000000000000000000000000000..73ec63a173a5985d2fc4d2f5485b9377db7b1baa --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/nb.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'nb', { + embeddingInProgress: 'Prøver Ã¥ bygge inn innlimt URL...', + embeddingFailed: 'URL-en kunne ikke bli automatisk bygget inn.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/nl.js b/libraries/ckeditor/plugins/autoembed/lang/nl.js new file mode 100644 index 0000000000000000000000000000000000000000..b77eb1e7d6581acdb5fd8546bb8f2b619cb7cc10 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/nl.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'nl', { + embeddingInProgress: 'De geplakte URL wordt ingesloten...', + embeddingFailed: 'Deze URL kon niet automatisch ingesloten worden.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/oc.js b/libraries/ckeditor/plugins/autoembed/lang/oc.js new file mode 100644 index 0000000000000000000000000000000000000000..275a4ca4330afee387ddbd8a12f34eb65c34e358 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/oc.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'oc', { + embeddingInProgress: 'Incorporacion de l\'URL pegada...', + embeddingFailed: 'Aquesta URL a pas pogut èsser incorporada automaticament.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/pl.js b/libraries/ckeditor/plugins/autoembed/lang/pl.js new file mode 100644 index 0000000000000000000000000000000000000000..aea0e518d97084ed9fae9d6206024b3dea17efc5 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/pl.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'pl', { + embeddingInProgress: 'Osadzanie wklejonego adresu URL...', + embeddingFailed: 'Ten adres URL multimediów nie może być automatycznie osadzony.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/pt-br.js b/libraries/ckeditor/plugins/autoembed/lang/pt-br.js new file mode 100644 index 0000000000000000000000000000000000000000..90342530a093861d6e00b6f5b5fcb8f663131bd1 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/pt-br.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'pt-br', { + embeddingInProgress: 'Tentando embutir a URL colada...', + embeddingFailed: 'Esta URL não pode ser embutida automaticamente.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/pt.js b/libraries/ckeditor/plugins/autoembed/lang/pt.js new file mode 100644 index 0000000000000000000000000000000000000000..b3be44b28d358c266a72a43cfc19c38b2d8bfd45 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/pt.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'pt', { + embeddingInProgress: 'Trying to embed pasted URL...', // MISSING + embeddingFailed: 'Não foi possÃvel embeber diretamente este URL.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/ru.js b/libraries/ckeditor/plugins/autoembed/lang/ru.js new file mode 100644 index 0000000000000000000000000000000000000000..ec8aba88c117315f162d0f04fbf4b6947d79df43 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/ru.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'ru', { + embeddingInProgress: 'ПытаемÑÑ Ð²Ñтроить вÑтавленный URL...', + embeddingFailed: 'Данный URL не может быть вÑтроен автоматичеÑки.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/sk.js b/libraries/ckeditor/plugins/autoembed/lang/sk.js new file mode 100644 index 0000000000000000000000000000000000000000..39632450c0b37ce3fdd8e120753fb4b8b1d91a5c --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/sk.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'sk', { + embeddingInProgress: 'SnažÃm sa vložiÅ¥ skopÃrovanú URL...', + embeddingFailed: 'Túto URL nebolo možné automaticky vložiÅ¥.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/sv.js b/libraries/ckeditor/plugins/autoembed/lang/sv.js new file mode 100644 index 0000000000000000000000000000000000000000..e35b960f2d0b641bab537ea5354caa7df892d1e7 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/sv.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'sv', { + embeddingInProgress: 'Försöker bädda in inklistrad URL...', + embeddingFailed: 'Denna URL kunde inte automatiskt bäddas in.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/tr.js b/libraries/ckeditor/plugins/autoembed/lang/tr.js new file mode 100644 index 0000000000000000000000000000000000000000..51346e8e312dfbd6b6ad4b224e445ebfee04559b --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/tr.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'tr', { + embeddingInProgress: 'Yapıştırdığınız URL gömülmeye çalışılıyor...', + embeddingFailed: 'Bu URL otomatik olarak gömülemedi.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/ug.js b/libraries/ckeditor/plugins/autoembed/lang/ug.js new file mode 100644 index 0000000000000000000000000000000000000000..5cf73a79b79264f90461e85f3187a043742a2a75 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/ug.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'ug', { + embeddingInProgress: 'سىÚدۈرۈلگەن چاپلانغان URL نى سىناۋاتىدۇ…', + embeddingFailed: 'بۇ URL نى ئۆزلۈكىدىن سىÚدۈرەلمەيدۇ.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/uk.js b/libraries/ckeditor/plugins/autoembed/lang/uk.js new file mode 100644 index 0000000000000000000000000000000000000000..5fea30b71dd3caa2c84b14fedeaa8500f21bd7f6 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/uk.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'uk', { + embeddingInProgress: 'ÐамагаюÑÑŒ вбудувати вÑтавлене URL поÑиланнÑ...', + embeddingFailed: 'Це URl поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ðµ може бути автоматично вбудовано.' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/zh-cn.js b/libraries/ckeditor/plugins/autoembed/lang/zh-cn.js new file mode 100644 index 0000000000000000000000000000000000000000..ae6c67b732654b5974cbeee3e9005dd0b528e72e --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/zh-cn.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'zh-cn', { + embeddingInProgress: 'æ£åœ¨å°è¯•åµŒå…¥ç²˜è´´çš„ URL 里的媒体内容...', + embeddingFailed: 'æ¤ URL æ— æ³•è‡ªåŠ¨åµŒå…¥åª’ä½“å†…å®¹' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/lang/zh.js b/libraries/ckeditor/plugins/autoembed/lang/zh.js new file mode 100644 index 0000000000000000000000000000000000000000..dfad65dfafaeb806a460482fe284b8d814f4b96b --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/lang/zh.js @@ -0,0 +1,8 @@ +/* + Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + For licensing, see LICENSE.md or http://ckeditor.com/license + */ +CKEDITOR.plugins.setLang( 'autoembed', 'zh', { + embeddingInProgress: 'æ£åœ¨å˜—試嵌入已貼上的 URL...', + embeddingFailed: '這個 URL 無法被自動嵌入。' +} ); diff --git a/libraries/ckeditor/plugins/autoembed/plugin.js b/libraries/ckeditor/plugins/autoembed/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..54dd77abe1ecb5fa3cb627edcb9b7910c7df0866 --- /dev/null +++ b/libraries/ckeditor/plugins/autoembed/plugin.js @@ -0,0 +1,214 @@ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +'use strict'; + +( function() { + var validLinkRegExp = /^<a[^>]+href="([^"]+)"[^>]*>([^<]+)<\/a>$/i; + + CKEDITOR.plugins.add( 'autoembed', { + requires: 'autolink,undo', + lang: 'az,ca,cs,de,de-ch,en,eo,es,es-mx,eu,fr,gl,hr,hu,it,ja,km,ko,ku,mk,nb,nl,oc,pl,pt,pt-br,ru,sk,sv,tr,ug,uk,zh,zh-cn', // %REMOVE_LINE_CORE% + init: function( editor ) { + var currentId = 1, + embedCandidatePasted; + + editor.on( 'paste', function( evt ) { + if ( evt.data.dataTransfer.getTransferType( editor ) == CKEDITOR.DATA_TRANSFER_INTERNAL ) { + embedCandidatePasted = 0; + return; + } + + var match = evt.data.dataValue.match( validLinkRegExp ); + + embedCandidatePasted = match != null && decodeURI( match[ 1 ] ) == decodeURI( match[ 2 ] ); + + // Expecting exactly one <a> tag spanning the whole pasted content. + // The tag has to have same href as content. + if ( embedCandidatePasted ) { + evt.data.dataValue = '<a data-cke-autoembed="' + ( ++currentId ) + '"' + evt.data.dataValue.substr( 2 ); + } + }, null, null, 20 ); // Execute after autolink. + + editor.on( 'afterPaste', function() { + // If one pasted an embeddable link and then undone the action, the link in the content holds the + // data-cke-autoembed attribute and may be embedded on *any* successive paste. + // This check ensures that autoEmbedLink is called only if afterPaste is fired *right after* + // embeddable link got into the content. (http://dev.ckeditor.com/ticket/13532) + if ( embedCandidatePasted ) { + autoEmbedLink( editor, currentId ); + } + } ); + } + } ); + + function autoEmbedLink( editor, id ) { + var anchor = editor.editable().findOne( 'a[data-cke-autoembed="' + id + '"]' ), + lang = editor.lang.autoembed, + notification; + + if ( !anchor || !anchor.data( 'cke-saved-href' ) ) { + return; + } + + var href = anchor.data( 'cke-saved-href' ), + widgetDef = CKEDITOR.plugins.autoEmbed.getWidgetDefinition( editor, href ); + + if ( !widgetDef ) { + CKEDITOR.warn( 'autoembed-no-widget-def' ); + return; + } + + // TODO Move this to a method in the widget plugin. http://dev.ckeditor.com/ticket/13408 + var defaults = typeof widgetDef.defaults == 'function' ? widgetDef.defaults() : widgetDef.defaults, + element = CKEDITOR.dom.element.createFromHtml( widgetDef.template.output( defaults ) ), + instance, + wrapper = editor.widgets.wrapElement( element, widgetDef.name ), + temp = new CKEDITOR.dom.documentFragment( wrapper.getDocument() ); + + temp.append( wrapper ); + instance = editor.widgets.initOn( element, widgetDef ); + + if ( !instance ) { + finalizeCreation(); + return; + } + + notification = editor.showNotification( lang.embeddingInProgress, 'info' ); + instance.loadContent( href, { + noNotifications: true, + callback: function() { + // DOM might be invalidated in the meantime, so find the anchor again. + var anchor = editor.editable().findOne( 'a[data-cke-autoembed="' + id + '"]' ); + + // Anchor might be removed in the meantime. + if ( anchor ) { + var selection = editor.getSelection(), + insertRange = editor.createRange(), + editable = editor.editable(); + + // Save the changes in editor contents that happened *after* the link was pasted + // but before it gets embedded (i.e. user pasted and typed). + editor.fire( 'saveSnapshot' ); + + // Lock snapshot so we don't make unnecessary undo steps in + // editable.insertElement() below, which would include bookmarks. (http://dev.ckeditor.com/ticket/13429) + editor.fire( 'lockSnapshot', { dontUpdate: true } ); + + // Bookmark current selection. (http://dev.ckeditor.com/ticket/13429) + var bookmark = selection.createBookmarks( false )[ 0 ], + startNode = bookmark.startNode, + endNode = bookmark.endNode || startNode; + + // When url is pasted, IE8 sets the caret after <a> element instead of inside it. + // So, if user hasn't changed selection, bookmark is inserted right after <a>. + // Then, after pasting embedded content, bookmark is still in DOM but it is + // inside the original element. After selection recreation it would end up before widget: + // <p>A <a /><bm /></p><p>B</p> --> <p>A <bm /></p><widget /><p>B</p> --> <p>A ^</p><widget /><p>B</p> + // We have to fix this IE8 behavior so it is the same as on other browsers. + if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 && !bookmark.endNode && startNode.equals( anchor.getNext() ) ) { + anchor.append( startNode ); + } + + insertRange.setStartBefore( anchor ); + insertRange.setEndAfter( anchor ); + + editable.insertElement( wrapper, insertRange ); + + // If both bookmarks are still in DOM, it means that selection was not inside + // an anchor that got substituted. We can safely recreate that selection. (http://dev.ckeditor.com/ticket/13429) + if ( editable.contains( startNode ) && editable.contains( endNode ) ) { + selection.selectBookmarks( [ bookmark ] ); + } else { + // If one of bookmarks is not in DOM, clean up leftovers. + startNode.remove(); + endNode.remove(); + } + + editor.fire( 'unlockSnapshot' ); + } + + notification.hide(); + finalizeCreation(); + }, + + errorCallback: function() { + notification.hide(); + editor.widgets.destroy( instance, true ); + editor.showNotification( lang.embeddingFailed, 'info' ); + } + } ); + + function finalizeCreation() { + editor.widgets.finalizeCreation( temp ); + } + } + + CKEDITOR.plugins.autoEmbed = { + /** + * Gets the definition of the widget that should be used to automatically embed the specified link. + * + * This method uses the value of the {@link CKEDITOR.config#autoEmbed_widget} option. + * + * @since 4.5 + * @member CKEDITOR.plugins.autoEmbed + * @param {CKEDITOR.editor} editor + * @param {String} url The URL to be embedded. + * @returns {CKEDITOR.plugins.widget.definition/null} The definition of the widget to be used to embed the link. + */ + getWidgetDefinition: function( editor, url ) { + var opt = editor.config.autoEmbed_widget || 'embed,embedSemantic', + name, + widgets = editor.widgets.registered; + + if ( typeof opt == 'string' ) { + opt = opt.split( ',' ); + + while ( ( name = opt.shift() ) ) { + if ( widgets[ name ] ) { + return widgets[ name ]; + } + } + } else if ( typeof opt == 'function' ) { + return widgets[ opt( url ) ]; + } + + return null; + } + }; + + /** + * Specifies the widget to use to automatically embed a link. The default value + * of this option defines that either the [Media Embed](ckeditor.com/addon/embed) or + * [Semantic Media Embed](ckeditor.com/addon/embedsemantic) widgets will be used, depending on which is enabled. + * + * The general behavior: + * + * * If a string (widget names separated by commas) is provided, then the first of the listed widgets which is registered + * will be used. For example, if `'foo,bar,bom'` is set and widgets `'bar'` and `'bom'` are registered, then `'bar'` + * will be used. + * * If a callback is specified, then it will be executed with the URL to be embedded and it should return the + * name of the widget to be used. It allows to use different embed widgets for different URLs. + * + * Example: + * + * // Defines that embedSemantic should be used (regardless of whether embed is defined). + * config.autoEmbed_widget = 'embedSemantic'; + * + * Using with custom embed widgets: + * + * config.autoEmbed_widget = 'customEmbed'; + * + * **Note:** Plugin names are always lower case, while widget names are not, so widget names do not have to equal plugin names. + * For example, there is the `embedsemantic` plugin and the `embedSemantic` widget. + * + * Read more in the [documentation](#!/guide/dev_media_embed-section-automatic-embedding-on-paste) + * and see the [SDK sample](http://sdk.ckeditor.com/samples/mediaembed.html). + * + * @since 4.5 + * @cfg {String/Function} [autoEmbed_widget='embed,embedSemantic'] + * @member CKEDITOR.config + */ +} )(); diff --git a/libraries/ckeditor/plugins/autolink/plugin.js b/libraries/ckeditor/plugins/autolink/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..831922ae77ca66403180174c349aeafaa412d807 --- /dev/null +++ b/libraries/ckeditor/plugins/autolink/plugin.js @@ -0,0 +1,42 @@ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +( function() { + 'use strict'; + + // Regex by Imme Emosol. + var validUrlRegex = /^(https?|ftp):\/\/(-\.)?([^\s\/?\.#]+\.?)+(\/[^\s]*)?[^\s\.,]$/ig, + doubleQuoteRegex = /"/g; + + CKEDITOR.plugins.add( 'autolink', { + requires: 'clipboard', + + init: function( editor ) { + editor.on( 'paste', function( evt ) { + var data = evt.data.dataValue; + + if ( evt.data.dataTransfer.getTransferType( editor ) == CKEDITOR.DATA_TRANSFER_INTERNAL ) { + return; + } + + // If we found "<" it means that most likely there's some tag and we don't want to touch it. + if ( data.indexOf( '<' ) > -1 ) { + return; + } + + // http://dev.ckeditor.com/ticket/13419 + data = data.replace( validUrlRegex , '<a href="' + data.replace( doubleQuoteRegex, '%22' ) + '">$&</a>' ); + + // If link was discovered, change the type to 'html'. This is important e.g. when pasting plain text in Chrome + // where real type is correctly recognized. + if ( data != evt.data.dataValue ) { + evt.data.type = 'html'; + } + + evt.data.dataValue = data; + } ); + } + } ); +} )(); diff --git a/libraries/ckeditor/plugins/embed/icons/embed.png b/libraries/ckeditor/plugins/embed/icons/embed.png new file mode 100644 index 0000000000000000000000000000000000000000..9a9a73568eff8443f69985e68bc1f8039940b498 Binary files /dev/null and b/libraries/ckeditor/plugins/embed/icons/embed.png differ diff --git a/libraries/ckeditor/plugins/embed/icons/hidpi/embed.png b/libraries/ckeditor/plugins/embed/icons/hidpi/embed.png new file mode 100644 index 0000000000000000000000000000000000000000..97dc75475839dece3638850cd2d1628e1af4ed6b Binary files /dev/null and b/libraries/ckeditor/plugins/embed/icons/hidpi/embed.png differ diff --git a/libraries/ckeditor/plugins/embed/plugin.js b/libraries/ckeditor/plugins/embed/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..2ecbccb2b8109a71a4820f7bb5571229d48c9cb7 --- /dev/null +++ b/libraries/ckeditor/plugins/embed/plugin.js @@ -0,0 +1,105 @@ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +( function() { + 'use strict'; + + CKEDITOR.plugins.add( 'embed', { + icons: 'embed', // %REMOVE_LINE_CORE% + hidpi: true, // %REMOVE_LINE_CORE% + requires: 'embedbase', + + init: function( editor ) { + var widgetDefinition = CKEDITOR.plugins.embedBase.createWidgetBaseDefinition( editor ); + + if ( !editor.config.embed_provider ) { + CKEDITOR.error( 'embed-no-provider-url' ); + } + + // Extend the base definition with additional properties. + CKEDITOR.tools.extend( widgetDefinition, { + // Use a dialog exposed by the embedbase plugin. + dialog: 'embedBase', + button: editor.lang.embedbase.button, + allowedContent: 'div[!data-oembed-url]', + requiredContent: 'div[data-oembed-url]', + providerUrl: new CKEDITOR.template( editor.config.embed_provider || '' ), + + // The filter element callback actually allows all divs with data-oembed-url, + // so registering styles to the filter is virtually unnecessary because + // classes won't be filtered out. However, registering them will make filter.check() work + // which may be important in some cases. + styleToAllowedContentRules: function( style ) { + // Retrieve classes defined in the style. + var classes = style.getClassesArray(); + + return { + div: { + propertiesOnly: true, + classes: classes, + attributes: '!data-oembed-url' + } + }; + }, + + upcast: function( el, data ) { + if ( el.name == 'div' && el.attributes[ 'data-oembed-url' ] ) { + data.url = el.attributes[ 'data-oembed-url' ]; + + return true; + } + }, + + downcast: function( el ) { + el.attributes[ 'data-oembed-url' ] = this.data.url; + } + }, true ); + + // Register the definition as 'embed' widget. + editor.widgets.add( 'embed', widgetDefinition ); + + // Do not filter contents of the div[data-oembed-url] at all. + editor.filter.addElementCallback( function( el ) { + if ( 'data-oembed-url' in el.attributes ) { + return CKEDITOR.FILTER_SKIP_TREE; + } + } ); + } + } ); + +} )(); + +/** + * A template for the URL of the provider endpoint. This URL will be queried for each resource to be embedded. + * + * It uses the following parameters: + * + * * `url` – The URL of the requested media, e.g. `https://twitter.com/ckeditor/status/401373919157821441`. + * * `callback` – The name of the globally available callback used for JSONP requests. + * + * For example: + * + * config.embed_provider = '//example.com/api/oembed-proxy?resource-url={url}&callback={callback}'; + * + * By default CKEditor does not use any provider, although there is a ready-to-use URL available via Iframely: + * + * config.embed_provider = '//ckeditor.iframe.ly/api/oembed?url={url}&callback={callback}' + * + * However, this endpoint contains certain limitations, e.g. it cannot embed Google Maps content. + * It is recommended to set up an account on the [Iframely](https://iframely.com/) service for + * better control over embedded content. + * + * Read more in the [documentation](#!/guide/dev_media_embed) + * and see the [SDK sample](http://sdk.ckeditor.com/samples/mediaembed.html). + * + * Refer to {@link CKEDITOR.plugins.embedBase.baseDefinition#providerUrl} for more information about content providers. + * + * **Important note:** Prior to version 4.7 this configuration option defaulted to the + * `//ckeditor.iframe.ly/api/oembed?url={url}&callback={callback}` string. + * + * @since 4.5 + * @cfg {String} [embed_provider=''] + * @member CKEDITOR.config + */ diff --git a/libraries/ckeditor/plugins/embedbase/dialogs/embedbase.js b/libraries/ckeditor/plugins/embedbase/dialogs/embedbase.js new file mode 100644 index 0000000000000000000000000000000000000000..014282f31fea21f98cc111da5b4627f0a919d0bd --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/dialogs/embedbase.js @@ -0,0 +1,99 @@ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +/* global alert */ + +CKEDITOR.dialog.add( 'embedBase', function( editor ) { + 'use strict'; + + var lang = editor.lang.embedbase; + + return { + title: lang.title, + minWidth: 350, + minHeight: 50, + + onLoad: function() { + var that = this, + loadContentRequest = null; + + this.on( 'ok', function( evt ) { + // We're going to hide it manually, after remote response is fetched. + evt.data.hide = false; + + // We don't want the widget system to finalize widget insertion (it happens with priority 20). + evt.stop(); + + // Indicate visually that waiting for the response (http://dev.ckeditor.com/ticket/13213). + that.setState( CKEDITOR.DIALOG_STATE_BUSY ); + + var url = that.getValueOf( 'info', 'url' ); + + loadContentRequest = that.widget.loadContent( url, { + noNotifications: true, + + callback: function() { + if ( !that.widget.isReady() ) { + editor.widgets.finalizeCreation( that.widget.wrapper.getParent( true ) ); + } + + editor.fire( 'saveSnapshot' ); + + that.hide(); + unlock(); + }, + + errorCallback: function( messageTypeOrMessage ) { + that.getContentElement( 'info', 'url' ).select(); + + alert( that.widget.getErrorMessage( messageTypeOrMessage, url, 'Given' ) ); + + unlock(); + } + } ); + }, null, null, 15 ); + + this.on( 'cancel', function( evt ) { + if ( evt.data.hide && loadContentRequest ) { + loadContentRequest.cancel(); + unlock(); + } + } ); + + function unlock() { + // Visual waiting indicator is no longer needed (http://dev.ckeditor.com/ticket/13213). + that.setState( CKEDITOR.DIALOG_STATE_IDLE ); + loadContentRequest = null; + } + }, + + contents: [ + { + id: 'info', + + elements: [ + { + type: 'text', + id: 'url', + label: editor.lang.common.url, + required: true, + + setup: function( widget ) { + this.setValue( widget.data.url ); + }, + + validate: function() { + if ( !this.getDialog().widget.isUrlValid( this.getValue() ) ) { + return lang.unsupportedUrlGiven; + } + + return true; + } + } + ] + } + ] + }; +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/az.js b/libraries/ckeditor/plugins/embedbase/lang/az.js new file mode 100644 index 0000000000000000000000000000000000000000..d2a09bed3f4f920c37ac97dc0903cea62202082e --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/az.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'az', { + pathName: 'Multimedia obyektlÉ™ri', + title: 'Multimedia obyektlÉ™rin quraÅŸdırılması', + button: 'Multimedia obyekti quraÅŸdır', + unsupportedUrlGiven: 'Daxil etdiyiniz linki dÉ™stÉ™klÉ™nmir', + unsupportedUrl: '{url} linki quraÅŸdırıla bilmÉ™z', + fetchingFailedGiven: 'Daxil etdiyiniz linkdÉ™n gÉ™lÉ™n mÉ™lumat yanlışdır', + fetchingFailed: '{url} linkdÉ™n gÉ™lÉ™n mÉ™lumat yanlışdır', + fetchingOne: 'oEmbed tÉ™rÉ™findÉ™n cavabın yoxlanması...', + fetchingMany: 'oEmbed tÉ™rÉ™findÉ™n cavabların yoxlanması, {max}-dan {current} yerinÉ™ yetirilib...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/ca.js b/libraries/ckeditor/plugins/embedbase/lang/ca.js new file mode 100644 index 0000000000000000000000000000000000000000..236d52553deb34ea5f7b395ab7cc57e0f291f7fb --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/ca.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'ca', { + pathName: 'objecte multimèdia', + title: 'Objecte multimèdia incrustat', + button: 'Inserir objecte multimèdia incrustat', + unsupportedUrlGiven: 'La URL especificada no és compatible.', + unsupportedUrl: 'La URL {url} no és compatible pels objectes multimèdia incrustats.', + fetchingFailedGiven: 'No s\'ha pogut obtenir el contingut de la URL especificada.', + fetchingFailed: 'No s\'ha pogut obtenir el contingut de {url}.', + fetchingOne: 'Recuperant resposta de oEmbed...', + fetchingMany: 'Recuperant respostes dels oEmbed, {current} de {max} finalitzats...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/cs.js b/libraries/ckeditor/plugins/embedbase/lang/cs.js new file mode 100644 index 0000000000000000000000000000000000000000..6949e047dc354bb1c50e61253355ea321a24cd2c --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/cs.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'cs', { + pathName: 'objekt média', + title: 'Vloženà médiÃ', + button: 'Vložit médium', + unsupportedUrlGiven: 'Zadaná URL nenà podporována.', + unsupportedUrl: 'URL {url} nenà podporována ', + fetchingFailedGiven: 'Pro zadanou adresu URL nelze zÃskat obsah.', + fetchingFailed: 'Nelze zÃskat obsah na {url}.', + fetchingOne: 'ZÃskávánà odpovÄ›dà oEmbed...', + fetchingMany: 'ZÃskávánà odpovÄ›dà oEmbed. {current} z {max} hotovo...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/da.js b/libraries/ckeditor/plugins/embedbase/lang/da.js new file mode 100644 index 0000000000000000000000000000000000000000..214ec6211e668dbb4ced89bcd86f969e376f6b84 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/da.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'da', { + pathName: 'media objekt', + title: 'Media Embed', + button: 'Indsæt Media Embed', + unsupportedUrlGiven: 'Den angivende URL er ikke undersøttet.', + unsupportedUrl: 'URLen {url} er ikke undersøttet af Media Embed.', + fetchingFailedGiven: 'Kunne ikke hente indholdet fra den angivende URL.', + fetchingFailed: 'Kunne ikke hente indholdet fra {url}.', + fetchingOne: 'Henter oEmbed-svar', + fetchingMany: 'Henter oEmbed-svar, {current} af {max} færdige...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/de-ch.js b/libraries/ckeditor/plugins/embedbase/lang/de-ch.js new file mode 100644 index 0000000000000000000000000000000000000000..47ee89c87fc675dddb0e7da160c4973c567ffc7f --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/de-ch.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'de-ch', { + pathName: 'Medienobjekt', + title: 'Media Embed (Medieninhalte)', + button: 'Medieninhalte einfügen', + unsupportedUrlGiven: 'Die angegebene URL wird nicht unterstützt.', + unsupportedUrl: 'Die URL {url} wird von Media Embed nicht unterstützt.', + fetchingFailedGiven: 'Abrufen des Inhalts für die angegebene URL ist fehlgeschlagen.', + fetchingFailed: 'Abrufen des Inhalts für {url} ist fehlgeschlagen.', + fetchingOne: 'Empfangen der Medieninhalte...', + fetchingMany: 'Medieninhalte werden abgerufen, {current} von {max} empfangen...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/de.js b/libraries/ckeditor/plugins/embedbase/lang/de.js new file mode 100644 index 0000000000000000000000000000000000000000..5dd47e619a91f290d9c00a67bb3f62799be174c3 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/de.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'de', { + pathName: 'Medienobjekt', + title: 'Media Embed (Medieninhalte)', + button: 'Medieninhalte einfügen', + unsupportedUrlGiven: 'Die angegebene URL wird nicht unterstützt.', + unsupportedUrl: 'Die URL {url} wird von Media Embed nicht unterstützt.', + fetchingFailedGiven: 'Abrufen des Inhalts für die angegebene URL ist fehlgeschlagen.', + fetchingFailed: 'Abrufen des Inhalts für {url} ist fehlgeschlagen.', + fetchingOne: 'Empfangen der Medieninhalte...', + fetchingMany: 'Medieninhalte werden abgerufen, {current} von {max} empfangen...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/en.js b/libraries/ckeditor/plugins/embedbase/lang/en.js new file mode 100644 index 0000000000000000000000000000000000000000..70a785ea623d01480dd87fb155dc79b70aad2217 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/en.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'en', { + pathName: 'media object', + title: 'Media Embed', + button: 'Insert Media Embed', + unsupportedUrlGiven: 'The specified URL is not supported.', + unsupportedUrl: 'The URL {url} is not supported by Media Embed.', + fetchingFailedGiven: 'Failed to fetch content for the given URL.', + fetchingFailed: 'Failed to fetch content for {url}.', + fetchingOne: 'Fetching oEmbed response...', + fetchingMany: 'Fetching oEmbed responses, {current} of {max} done...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/eo.js b/libraries/ckeditor/plugins/embedbase/lang/eo.js new file mode 100644 index 0000000000000000000000000000000000000000..e9d0782dfc35235e2e724796e964d97932d67395 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/eo.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'eo', { + pathName: 'Datumportila objekto', + title: 'Enkorpigo de datumportilo', + button: 'Enmetu enkorpigitan datumportilon.', + unsupportedUrlGiven: 'la indikita URL ne estas subtenata.', + unsupportedUrl: 'La URL {url} ne estas subtenata de enkorpigo de datumportilo.', + fetchingFailedGiven: 'Rekuperi enhavon por la indikitan URL malsukcesis.', + fetchingFailed: 'Rekuperi enhavon por {url} malsukcesis.', + fetchingOne: 'La respondo de la enkorpigita objekto estas serĉata ...', + fetchingMany: 'La respondoj de la enkorpigita objekto estas serĉataj, {current} el {max} faritaj...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/es-mx.js b/libraries/ckeditor/plugins/embedbase/lang/es-mx.js new file mode 100644 index 0000000000000000000000000000000000000000..a0c7f8f73c206350464be9f8177578bd8e3c493b --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/es-mx.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'es-mx', { + pathName: 'objeto multimedia', + title: 'Empotrar multimedia', + button: 'Insertar multimedia empotrado', + unsupportedUrlGiven: 'La URL especificada no es soportada.', + unsupportedUrl: 'La URL {url} no es soportada para empotrar multimedia', + fetchingFailedGiven: 'No se pudo obtener el contenido de la URL dada.', + fetchingFailed: 'No se pudo obtener el contenido de {url}.', + fetchingOne: 'Recuperar o Incrustar respuesta ...', + fetchingMany: 'Recuperar o Incrustar respuestas, {current} de {max} listo...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/es.js b/libraries/ckeditor/plugins/embedbase/lang/es.js new file mode 100644 index 0000000000000000000000000000000000000000..8e1bf9246ad60fad10e10bb0a3183456126a771f --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/es.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'es', { + pathName: 'objeto media', + title: 'Media incrustado', + button: 'Insertar Media incrustado', + unsupportedUrlGiven: 'La URL especificada no está soportada.', + unsupportedUrl: 'La URL {url} no está soportada por Medio Inscrustado.', + fetchingFailedGiven: 'Fallo al recuperar el contenido de la URL dada.', + fetchingFailed: 'Fallo al recuperar contenido de {url}.', + fetchingOne: 'Recuperando respuesta oEmbed...', + fetchingMany: 'Recuperando respuestas oEmbed, {current} de {max} hecho...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/eu.js b/libraries/ckeditor/plugins/embedbase/lang/eu.js new file mode 100644 index 0000000000000000000000000000000000000000..c8c41e4b27324c392a4bb9249ac1d5058b994108 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/eu.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'eu', { + pathName: 'multimedia objektua', + title: 'Media Embed', + button: 'Txertatu edukia', + unsupportedUrlGiven: 'Ez dago zehazturiko URLarentzako euskarririk', + unsupportedUrl: 'Media Embed-ek ez dauka {url} URLarentzako euskarririk.', + fetchingFailedGiven: 'Huts egin du emandako URLetik edukia eskuratzean.', + fetchingFailed: 'Huts egin du {url}(e)tik edukia eskuratzean.', + fetchingOne: 'oEmbed erantzuna eskuratzen...', + fetchingMany: 'oEmbed erantzunak eskuratzen, {current} / {max}' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/fr.js b/libraries/ckeditor/plugins/embedbase/lang/fr.js new file mode 100644 index 0000000000000000000000000000000000000000..24096c6ab288a3840473d8a1d378804b132bbb9f --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/fr.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'fr', { + pathName: 'objet média', + title: 'Incorporation de média', + button: 'Incorporer un média', + unsupportedUrlGiven: 'L\'URL spécifiée n\'est pas supportée.', + unsupportedUrl: 'L\'URL {url} n\'est pas supportée par l\'incorporation de média.', + fetchingFailedGiven: 'Échec de la récupération du contenu de l\'URL donnée.', + fetchingFailed: 'Échec de la récupération du contenu pour {url}.', + fetchingOne: 'Récupération de la réponse oEmbed...', + fetchingMany: 'Récupération des réponses oEmbed, {current} sur {max} effectué...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/gl.js b/libraries/ckeditor/plugins/embedbase/lang/gl.js new file mode 100644 index 0000000000000000000000000000000000000000..8666047ad7e44d6a95e2b08752a6384d80d8af81 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/gl.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'gl', { + pathName: 'obxecto multimedia', + title: 'Multimedia integrado', + button: 'Inserir un multimedia integrado', + unsupportedUrlGiven: 'O URL especificado non está admitido.', + unsupportedUrl: 'O URL {url} non está admitido polo multimedia integrado.', + fetchingFailedGiven: 'Non foi posÃbel obter o contido do URL indicado.', + fetchingFailed: 'Non foi posÃbel obter o contido der {url}.', + fetchingOne: 'Obtendo a resposta oEmbed...', + fetchingMany: 'Obtendo as respostas oEmbed, feito {current} de {max}...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/hr.js b/libraries/ckeditor/plugins/embedbase/lang/hr.js new file mode 100644 index 0000000000000000000000000000000000000000..4acfe6e2d223c973837506b99963bfe8a6b3ea42 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/hr.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'hr', { + pathName: 'objekt medija', + title: 'Media Embed', + button: 'Umetanje Media Embed', + unsupportedUrlGiven: 'Navedeni URL nije podržan', + unsupportedUrl: 'URL {url} nije podržan od strane Media Embed-a.', + fetchingFailedGiven: 'Nije moguće dohvatiti sadržaj danog URL-a.', + fetchingFailed: 'Nije moguće dohvatiti sadržaj za {url}.', + fetchingOne: 'Dohvaćanje oEmbed odgovora...', + fetchingMany: 'Dohvaćanje oEmbed odgovora, {current} od {max} gotovo...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/hu.js b/libraries/ckeditor/plugins/embedbase/lang/hu.js new file mode 100644 index 0000000000000000000000000000000000000000..805c4d2e12f75fb3e4dd35126fa6619414d3f24d --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/hu.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'hu', { + pathName: 'média objektum', + title: 'Média beágyazása', + button: 'Beágyazott média beszúrása', + unsupportedUrlGiven: 'A megadott URL nem támogatott.', + unsupportedUrl: 'Az URL-t {url} a média beágyazása nem támogatja.', + fetchingFailedGiven: 'Nem sikerült a megadott URL-hez tartalmat kinyerni.', + fetchingFailed: 'Nem sikerült az {url}-nek a tartalmát kinyerni.', + fetchingOne: 'oEmbed válasz kinyerése...', + fetchingMany: 'oEmbed válasz kinyerése folyamatban, {current} a {max}-ból kész...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/id.js b/libraries/ckeditor/plugins/embedbase/lang/id.js new file mode 100644 index 0000000000000000000000000000000000000000..a8f4cbaa6dcad1da4dd18801f3222bb26fd17589 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/id.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'id', { + pathName: 'media object', // MISSING + title: 'Sisipkan Media', + button: 'Insert Media Embed', // MISSING + unsupportedUrlGiven: 'The specified URL is not supported.', // MISSING + unsupportedUrl: 'The URL {url} is not supported by Media Embed.', // MISSING + fetchingFailedGiven: 'Failed to fetch content for the given URL.', // MISSING + fetchingFailed: 'Gagal mengambil konten untuk {url}', + fetchingOne: 'Fetching oEmbed response...', // MISSING + fetchingMany: 'Fetching oEmbed responses, {current} of {max} done...' // MISSING +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/it.js b/libraries/ckeditor/plugins/embedbase/lang/it.js new file mode 100644 index 0000000000000000000000000000000000000000..72cf3a5b46eb064a8f0ed4c749be9f6f65b2601f --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/it.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'it', { + pathName: 'oggetto multimediale', + title: 'Media incorporato', + button: 'Inserisci media incorporato', + unsupportedUrlGiven: 'L\'URL specificato non è supportato.', + unsupportedUrl: 'L\'URL {url} non è supportato da Media incorporato.', + fetchingFailedGiven: 'Non è stato possibile recuperareil contenuto per l\'URL specificato.', + fetchingFailed: 'Non è stato possibile recuperare il contenuto per {url}.', + fetchingOne: 'Recupero della risposta oEmbed...', + fetchingMany: 'Recupero delle risposta oEmbed, {current} di {max} completati...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/ja.js b/libraries/ckeditor/plugins/embedbase/lang/ja.js new file mode 100644 index 0000000000000000000000000000000000000000..a1fb0e4d6c91ef557d4779e5aa5788e53e3dd6f0 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/ja.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'ja', { + pathName: 'media object', // MISSING + title: 'Media Embed', // MISSING + button: 'Insert Media Embed', // MISSING + unsupportedUrlGiven: '指定ã•ã‚ŒãŸURLã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。', + unsupportedUrl: 'The URL {url} is not supported by Media Embed.', // MISSING + fetchingFailedGiven: 'Failed to fetch content for the given URL.', // MISSING + fetchingFailed: 'Failed to fetch content for {url}.', // MISSING + fetchingOne: 'Fetching oEmbed response...', // MISSING + fetchingMany: 'Fetching oEmbed responses, {current} of {max} done...' // MISSING +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/ko.js b/libraries/ckeditor/plugins/embedbase/lang/ko.js new file mode 100644 index 0000000000000000000000000000000000000000..c5db672b22c9d1ebdee1efc103bd3abf44c7beb8 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/ko.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'ko', { + pathName: '미디어 오브ì 트', + title: '미디어 ìž„ë² ë“œ', + button: '미디어 ìž„ë² ë“œ 삽입', + unsupportedUrlGiven: '지ì›í•˜ì§€ 않는 주소 형ì‹ìž…니다.', + unsupportedUrl: 'ìž…ë ¥í•˜ì‹ ì£¼ì†Œ {url}ì€ ì§€ì›ë˜ì§€ 않는 형ì‹ìž…니다.', + fetchingFailedGiven: 'ìž…ë ¥í•˜ì‹ ì£¼ì†Œì—ì„œ ë‚´ìš©ì„ ë¶ˆëŸ¬ì˜¬ 수 없습니다.', + fetchingFailed: 'ìž…ë ¥í•˜ì‹ ì£¼ì†Œ {url}ì—ì„œ ë‚´ìš©ì„ ë¶ˆëŸ¬ì˜¬ 수 없습니다.', + fetchingOne: 'oEmbed ì‘ë‹µì„ ê°€ì ¸ì˜¤ëŠ” 중...', + fetchingMany: 'ì´ {max} ê°œ 중{current} 번째 oEmbed ì‘ë‹µì„ ê°€ì ¸ì˜¤ëŠ” 중...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/ku.js b/libraries/ckeditor/plugins/embedbase/lang/ku.js new file mode 100644 index 0000000000000000000000000000000000000000..4667de06f9e1e7add3e13618c67f2da6640906da --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/ku.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'ku', { + pathName: 'ڕاگەیاندنی بەرکار', + title: 'خستنەناوی ڕاگەیاندن', + button: 'خستنەناوی ڕاگەیاندن', + unsupportedUrlGiven: 'بەستەری نیشانکراو پشتیوان نەکراوە.', + unsupportedUrl: 'بەستەری {url} پشتیواننەککراوە لەلایەن خستنەناوی ڕاگەیاندن.', + fetchingFailedGiven: 'سەرکەوتوونەبوو Ù„Û• هێنانی ناوەڕۆکی بەستەری دراو', + fetchingFailed: 'سەرکەوتوونەبوو Ù„Û• هێنانەی ناوەڕۆکی ئەم بەستەرە {url}.', + fetchingOne: 'Ù„Û• Ù‡Û•ÙˆÚµÛŒ وەڵامی خستنەناوە', + fetchingMany: 'Ù„Û• Ù‡Û•ÙˆÚµÛŒ هێنانی خستنەناوە, {current} Ù„Û• {max} کۆتایهاتووە...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/nb.js b/libraries/ckeditor/plugins/embedbase/lang/nb.js new file mode 100644 index 0000000000000000000000000000000000000000..1779a83a3149c16f20e76a97be1061305ac803c5 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/nb.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'nb', { + pathName: 'mediaobjekt', + title: 'Media-innbygging', + button: 'Sett inn mediaobjekt', + unsupportedUrlGiven: 'Den oppgitte URL-en er ikke støttet.', + unsupportedUrl: 'URL-en {url} er ikke støttet av Media-innbygging.', + fetchingFailedGiven: 'Kunne ikke hente innhold for den oppgitte URL-en.', + fetchingFailed: 'Kunne ikke hente innhold for {url}.', + fetchingOne: 'Henter oEmbed-svar...', + fetchingMany: 'Henter oEmbed-svar, {current} av {max} fullført...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/nl.js b/libraries/ckeditor/plugins/embedbase/lang/nl.js new file mode 100644 index 0000000000000000000000000000000000000000..613487ec2f40233051882c18701ec4fcf88ab9cb --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/nl.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'nl', { + pathName: 'media object', + title: 'Mediareferentie', + button: 'Mediareferentie invoegen', + unsupportedUrlGiven: 'De opgegeven URL wordt niet ondersteund.', + unsupportedUrl: 'De URL {url} wordt niet ondersteund door Mediareferentie.', + fetchingFailedGiven: 'Kon de inhoud van de opgegeven URL niet ophalen', + fetchingFailed: 'Kon de inhoud van {url} niet ophalen.', + fetchingOne: 'Ophalen van oEmbed antwoord…', + fetchingMany: 'Ophalen van oEmbed antwoorden, {current} van {max} klaar…' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/oc.js b/libraries/ckeditor/plugins/embedbase/lang/oc.js new file mode 100644 index 0000000000000000000000000000000000000000..559f8ce10c3c8e4bc8ebea676b1dd9ae4da185a7 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/oc.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'oc', { + pathName: 'objècte mèdia', + title: 'Incorporacion de mèdia', + button: 'Incorporar un mèdia', + unsupportedUrlGiven: 'L\'URL especificada es pas suportada.', + unsupportedUrl: 'L\'URL {url} es pas suportada per l\'incorporacion de mèdia.', + fetchingFailedGiven: 'Fracà s de la recuperacion del contengut de l\'URL donada.', + fetchingFailed: 'Fracà s de la recuperacion del contengut per {url}.', + fetchingOne: 'Recuperacion de la responsa oEmbed...', + fetchingMany: 'Recuperacion de las responsas oEmbed, {current} sus {max} efectuat...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/pl.js b/libraries/ckeditor/plugins/embedbase/lang/pl.js new file mode 100644 index 0000000000000000000000000000000000000000..d5d2d9673b867f17e35970a42abc6ff6af33020f --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/pl.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'pl', { + pathName: 'obiekt multimediów', + title: 'Osadzenie multimediów (oEmbed)', + button: 'Osadź obiekt multimediów (oEmbed)', + unsupportedUrlGiven: 'Podany adres URL nie jest obsÅ‚ugiwany.', + unsupportedUrl: 'Adres URL {url} nie jest obsÅ‚ugiwany przez funkcjonalność osadzania multimediów.', + fetchingFailedGiven: 'Nie udaÅ‚o siÄ™ pobrać zawartoÅ›ci dla podanego adresu URL.', + fetchingFailed: 'Nie udaÅ‚o siÄ™ pobrać zawartoÅ›ci dla {url}.', + fetchingOne: 'Pobieranie odpowiedzi oEmbed...', + fetchingMany: 'Pobieranie odpowiedzi oEmbed, gotowe {current} z {max}...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/pt-br.js b/libraries/ckeditor/plugins/embedbase/lang/pt-br.js new file mode 100644 index 0000000000000000000000000000000000000000..46e89fc8b8be368e2fb8409411f77c3e98719b7b --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/pt-br.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'pt-br', { + pathName: 'objeto de mÃdia', + title: 'Incorporação de MÃdia', + button: 'Inserir Incorporação de MÃdia', + unsupportedUrlGiven: 'A URL especificada não é suportada.', + unsupportedUrl: 'A UTL {url} não é suportada pela Incorporação de MÃdia.', + fetchingFailedGiven: 'Falha ao obter conteúdo para a URL informada.', + fetchingFailed: 'Falha ao obter conteúdo para {url}.', + fetchingOne: 'Obtendo resposta oEmbed...', + fetchingMany: 'Obtendo respostas oEmbed, {current} de {max} completos...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/pt.js b/libraries/ckeditor/plugins/embedbase/lang/pt.js new file mode 100644 index 0000000000000000000000000000000000000000..d048caa2024fe30171b0ec7a9acec38956ec2e9a --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/pt.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'pt', { + pathName: 'objeto de media', + title: 'Embeber media', + button: 'Insert Media Embed', // MISSING + unsupportedUrlGiven: 'O URL especificado não é suportado.', + unsupportedUrl: 'The URL {url} is not supported by Media Embed.', // MISSING + fetchingFailedGiven: 'Failed to fetch content for the given URL.', // MISSING + fetchingFailed: 'Failed to fetch content for {url}.', // MISSING + fetchingOne: 'Fetching oEmbed response...', // MISSING + fetchingMany: 'Fetching oEmbed responses, {current} of {max} done...' // MISSING +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/ru.js b/libraries/ckeditor/plugins/embedbase/lang/ru.js new file mode 100644 index 0000000000000000000000000000000000000000..17ab98101aa08a2be7c30e866d4fac5c94818819 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/ru.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'ru', { + pathName: 'Медиа объект', + title: 'Медиаконтент', + button: 'Ð’Ñтавить Медиаконтент', + unsupportedUrlGiven: 'Данный URL не поддерживаетÑÑ.', + unsupportedUrl: 'URL {url} не поддерживаетÑÑ Media Embed.', + fetchingFailedGiven: 'Ðе удалоÑÑŒ подгрузить Ñодержимое Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ URL', + fetchingFailed: 'Ðе удалоÑÑŒ подгрузить Ñодержимое Ð´Ð»Ñ {url}', + fetchingOne: 'Подгружаем oEmbed ответ...', + fetchingMany: 'Подгружаем oEmbed ответы, {current} из {max} подгружено...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/sk.js b/libraries/ckeditor/plugins/embedbase/lang/sk.js new file mode 100644 index 0000000000000000000000000000000000000000..069f363b5adf7cb4c60d431e7411896fc245e73d --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/sk.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'sk', { + pathName: 'media objekt', + title: 'Media Embed', + button: 'Vložte Media Embed', + unsupportedUrlGiven: 'Zadaná URL nie je podporovaná.', + unsupportedUrl: 'URL {url} nie je podporovaná Media Embedom.', + fetchingFailedGiven: 'Nepodarilo sa zÃskaÅ¥ obsah zo zadanej URL.', + fetchingFailed: 'Nepodarilo sa zÃskaÅ¥ obsah z {url}.', + fetchingOne: 'ZÃskavanie oEmbed odpovede...', + fetchingMany: 'ZÃskavanie oEmbed odpovede, {current} z {max} hotových...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/sv.js b/libraries/ckeditor/plugins/embedbase/lang/sv.js new file mode 100644 index 0000000000000000000000000000000000000000..944df0dfb4d60d040d1016a09855007fc517136f --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/sv.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'sv', { + pathName: 'mediaobjekt', + title: 'Mediainbäddning', + button: 'Lägg in mediainbäddning', + unsupportedUrlGiven: 'Den angivna URL:en stöds inte.', + unsupportedUrl: 'URL:en {url} stöds inte av mediainbäddningen.', + fetchingFailedGiven: 'Lyckades inte hämta innehÃ¥llet frÃ¥n den angivna URL:en.', + fetchingFailed: 'Lyckades inte hämta innehÃ¥ll frÃ¥n {url}.', + fetchingOne: 'Hämtar oEmbed-svar...', + fetchingMany: 'Hämtar oEmbed-svar, {current} av {max} färdiga...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/tr.js b/libraries/ckeditor/plugins/embedbase/lang/tr.js new file mode 100644 index 0000000000000000000000000000000000000000..ab314e894e87bbe0eaffa087c4cefbb4a9c3d6f5 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/tr.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'tr', { + pathName: 'medya nesnesi', + title: 'Gömülmüş Medya', + button: 'Gömülü Medya Ekle', + unsupportedUrlGiven: 'BelirtmiÅŸ olduÄŸunuz URL desteklenmiyor.', + unsupportedUrl: 'BelirttiÄŸiniz URL {url} gömülü medya tarafından desteklenmiyor.', + fetchingFailedGiven: 'VermiÅŸ olduÄŸunuz URL\'nin içeriÄŸi alınamadı.', + fetchingFailed: '{url} içeriÄŸi alınamadı.', + fetchingOne: 'oEmbed cevabı alınıyor...', + fetchingMany: 'oEmbed cevabı alınıyor, {current} / {max} tamamlandı...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/ug.js b/libraries/ckeditor/plugins/embedbase/lang/ug.js new file mode 100644 index 0000000000000000000000000000000000000000..d7c6eeb302a1f1e2791107cebb8b3caa55e75871 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/ug.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'ug', { + pathName: 'ۋاسىتە ئوبيÛكتى', + title: 'سىÚدۈرمە ۋاسىتە', + button: 'سىÚدۈرمە ۋاسىتە قىستۇر', + unsupportedUrlGiven: 'The specified URL is not supported.', // MISSING + unsupportedUrl: 'The URL {url} is not supported by Media Embed.', // MISSING + fetchingFailedGiven: 'Failed to fetch content for the given URL.', // MISSING + fetchingFailed: 'Failed to fetch content for {url}.', // MISSING + fetchingOne: 'Fetching oEmbed response...', // MISSING + fetchingMany: 'Fetching oEmbed responses, {current} of {max} done...' // MISSING +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/uk.js b/libraries/ckeditor/plugins/embedbase/lang/uk.js new file mode 100644 index 0000000000000000000000000000000000000000..9556f8292d27fe1a54ca15bbd9ce47263cc8108f --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/uk.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'uk', { + pathName: 'Медіаоб’єкт', + title: 'Медіаконтент', + button: 'Ð’Ñтавити медіаконтент', + unsupportedUrlGiven: 'Вказане URL поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ðµ підтримуєтьÑÑ.', + unsupportedUrl: 'URL поÑÐ¸Ð»Ð°Ð½Ð½Ñ {url} не підтримуєтьÑÑ Ð¼ÐµÐ´Ñ–Ð°ÐºÐ¾Ð½Ñ‚ÐµÐ½Ñ‚Ð¾Ð¼.', + fetchingFailedGiven: 'Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ контент Ð´Ð»Ñ Ð´Ð°Ð½Ð¾Ð³Ð¾ URL поÑиланнÑ.', + fetchingFailed: 'Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ контент Ð´Ð»Ñ {url}.', + fetchingOne: 'ÐžÑ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ oEmbed відповіді...', + fetchingMany: 'ÐžÑ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ {current} із {max} oEmbed відповідей завершено....' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/zh-cn.js b/libraries/ckeditor/plugins/embedbase/lang/zh-cn.js new file mode 100644 index 0000000000000000000000000000000000000000..a25640d9e9225675ef284f3eef0a7aa11d1074ad --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/zh-cn.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'zh-cn', { + pathName: '媒体对象', + title: '嵌入媒体', + button: 'æ’入媒体', + unsupportedUrlGiven: 'ä¸æ”¯æŒæŒ‡å®šçš„ URL', + unsupportedUrl: '嵌入媒体ä¸æ”¯æŒæ¤ URL {url}', + fetchingFailedGiven: 'æ— æ³•æŠ“å–æ¤ URL 的内容', + fetchingFailed: 'æ— æ³•æŠ“å– {url} 的内容', + fetchingOne: 'æ£åœ¨æŠ“å–...', + fetchingMany: 'æ£åœ¨æŠ“å–,{max} ä¸çš„ {current} ...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/lang/zh.js b/libraries/ckeditor/plugins/embedbase/lang/zh.js new file mode 100644 index 0000000000000000000000000000000000000000..aa8f7300e5ff472dcec1436020010fffb7e67290 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/lang/zh.js @@ -0,0 +1,15 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'embedbase', 'zh', { + pathName: '媒體元件', + title: '內嵌媒體', + button: 'æ’入內嵌媒體', + unsupportedUrlGiven: 'ä¸æ”¯æ´æŒ‡å®šçš„ URL。', + unsupportedUrl: '內嵌媒體ä¸æ”¯æ´ URL {url} 。', + fetchingFailedGiven: '抓å–指定 URL 的內容失敗。', + fetchingFailed: 'æŠ“å– {url} 的內容失敗。', + fetchingOne: 'æ£åœ¨æŠ“å– oEmbed 回應...', + fetchingMany: 'æ£åœ¨æŠ“å– oEmbed 回應,{max} ä¸çš„ {current} 已完æˆ...' +} ); diff --git a/libraries/ckeditor/plugins/embedbase/plugin.js b/libraries/ckeditor/plugins/embedbase/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..7161f973c3eab8332cbd636e55dfefc5d661dfc6 --- /dev/null +++ b/libraries/ckeditor/plugins/embedbase/plugin.js @@ -0,0 +1,652 @@ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +( function() { + 'use strict'; + + /** + * JSONP communication. + * + * @private + * @singleton + * @class CKEDITOR.plugins.embedBase._jsonp + */ + var Jsonp = { + /** + * Creates a `<script>` element and attaches it to the document `<body>`. + * + * @private + */ + _attachScript: function( url, errorCallback ) { + // ATM we cannot use CKE scriptloader here, because it will make sure that script + // with given URL is added only once. + var script = new CKEDITOR.dom.element( 'script' ); + script.setAttribute( 'src', url ); + script.on( 'error', errorCallback ); + + CKEDITOR.document.getBody().append( script ); + + return script; + }, + + /** + * Sends a request using the JSONP technique. + * + * @param {CKEDITOR.template} urlTemplate The template of the URL to be requested. All properties + * passed in `urlParams` can be used, plus a `{callback}`, which represents a JSONP callback, must be defined. + * @param {Object} urlParams Parameters to be passed to the `urlTemplate`. + * @param {Function} callback + * @param {Function} [errorCallback] + * @returns {Object} The request object with a `cancel()` method. + */ + sendRequest: function( urlTemplate, urlParams, callback, errorCallback ) { + var request = {}; + urlParams = urlParams || {}; + + var callbackKey = CKEDITOR.tools.getNextNumber(), + scriptElement; + + urlParams.callback = 'CKEDITOR._.jsonpCallbacks[' + callbackKey + ']'; + + CKEDITOR._.jsonpCallbacks[ callbackKey ] = function( response ) { + // On IEs scripts are sometimes loaded synchronously. It is bad for two reasons: + // * nature of sendRequest() is unstable, + // * scriptElement does not exist yet. + setTimeout( function() { + cleanUp(); + callback( response ); + } ); + }; + + scriptElement = this._attachScript( urlTemplate.output( urlParams ), function() { + cleanUp(); + errorCallback && errorCallback(); + } ); + + request.cancel = cleanUp; + + function cleanUp() { + if ( scriptElement ) { + scriptElement.remove(); + delete CKEDITOR._.jsonpCallbacks[ callbackKey ]; + scriptElement = null; + } + } + + return request; + } + }; + + CKEDITOR.plugins.add( 'embedbase', { + lang: 'az,ca,cs,da,de,de-ch,en,eo,es,es-mx,eu,fr,gl,hr,hu,id,it,ja,ko,ku,nb,nl,oc,pl,pt,pt-br,ru,sk,sv,tr,ug,uk,zh,zh-cn', // %REMOVE_LINE_CORE% + requires: 'dialog,widget,notificationaggregator', + + onLoad: function() { + CKEDITOR._.jsonpCallbacks = {}; + }, + + init: function() { + CKEDITOR.dialog.add( 'embedBase', this.path + 'dialogs/embedbase.js' ); + } + } ); + + /** + * Creates a new embed widget base definition. After other necessary properties are filled this definition + * may be {@link CKEDITOR.plugins.widget.repository#add registered} as a new, independent widget for + * embedding content. + * + * By default an embed widget is set up to work with [oEmbed providers](http://www.oembed.com/) using JSONP + * requests, such as [Iframely](https://iframely.com/) or [Noembed](https://noembed.com/). It can be, + * however, easily configured to use other providers and communication methods, including custom systems + * or local embed databases. + * + * See example usage of this method in: + * + * * [/plugins/embed/plugin.js](https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/embed/plugin.js) + * * [/plugins/embedsemantic/plugin.js](https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/embedsemantic/plugin.js) + * + * Note that both these plugins reuse the [dialog](https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/embedbase/dialogs/embedbase.js) + * defined by the `embedbase` plugin. Integration of the asynchronous way of loading content with a dialog requires additional + * effort. Check the dialog's code for more details. + * + * @static + * @param {CKEDITOR.editor} editor + * @returns {CKEDITOR.plugins.embedBase.baseDefinition} + * @member CKEDITOR.plugins.embedBase + */ + function createWidgetBaseDefinition( editor ) { + var aggregator, + lang = editor.lang.embedbase; + + /** + * An embed widget base definition. It predefines a few {@link CKEDITOR.plugins.widget.definition widget definition} + * properties such as {@link #mask}, {@link #template} and {@link #pathName} and adds methods related to + * content embedding. + * + * To create a base definition use the {@link CKEDITOR.plugins.embedBase#createWidgetBaseDefinition} method. + * + * Note: For easier browsing of this class's API you can hide inherited method using the "Show" drop-down + * on the right-hand side. + * + * @abstract + * @class CKEDITOR.plugins.embedBase.baseDefinition + * @extends CKEDITOR.plugins.widget.definition + */ + return { + mask: true, + template: '<div></div>', + pathName: lang.pathName, + + /** + * Response cache. This cache object will be shared between all instances of this widget. + * + * @private + */ + _cache: {}, + + /** + * A regular expression to pre-validate URLs. + * + * See: + * + * * [https://iframely.com/docs/providers], + * * {@link #isUrlValid}. + */ + urlRegExp: /^((https?:)?\/\/|www\.)/i, + + /** + * The template used to generate the URL of the content provider. Content provider is a service + * which the embed widget will request in order to get an [oEmbed](http://www.oembed.com/) response that + * can be transformed into content which can be embedded in the editor. + * + * Example content providers are: + * + * * [Iframely](https://iframely.com/), + * * [Noembed](https://noembed.com/). + * + * Both Iframely and Noembed are **proxy** services which support **JSONP requests**, hence they are not limited by the + * same-origin policy. Unfortunately, usually oEmbed services exposed by real content providers + * like YouTube or Twitter do not support XHR with CORS or do not support oEmbed at all which makes it + * impossible or hard to get such content to be embedded in the editor. This problem is solved by proxy content providers + * like Iframely and Noembed. + * + * This property must be defined after creating an embed widget base definition. + * + * By default two values are passed to the template: + * + * * `{url}` – The URL of the resource to be embedded. + * * `{callback}` – The JSONP callback to be executed. + * + * Example value: + * + * widgetDefinition.providerUrl = new CKEDITOR.template( + * '//ckeditor.iframe.ly/api/oembed?url={url}&callback={callback}' + * ); + * + * @property {CKEDITOR.template} providerUrl + */ + + init: function() { + this.on( 'sendRequest', function( evt ) { + this._sendRequest( evt.data ); + }, this, null, 999 ); + + // Expose the widget in the dialog - needed to trigger loadContent() and do error handling. + this.on( 'dialog', function( evt ) { + evt.data.widget = this; + }, this ); + + this.on( 'handleResponse', function( evt ) { + if ( evt.data.html ) { + return; + } + + var retHtml = this._responseToHtml( evt.data.url, evt.data.response ); + + if ( retHtml !== null ) { + evt.data.html = retHtml; + } else { + evt.data.errorMessage = 'unsupportedUrl'; + evt.cancel(); + } + }, this, null, 999 ); + }, + + /** + * Loads content for a given resource URL by requesting the {@link #providerUrl provider}. + * + * Usually widgets are controlled by the {@link CKEDITOR.plugins.widget#setData} method. However, + * loading content is an asynchronous operation due to client-server communication, and it would not + * be possible to pass callbacks to the {@link CKEDITOR.plugins.widget#setData} method so this new method + * is defined for embed widgets. + * + * This method fires two events that allow to customize widget behavior without changing its code: + * + * * {@link #sendRequest}, + * * {@link #handleResponse} (if the request was successful). + * + * Note: This method is always asynchronous, even if the cache was hit. + * + * Example usage: + * + * var url = 'https://twitter.com/reinmarpl/status/573118615274315776'; + * widget.loadContent( url, { + * callback: function() { + * // Success. It is a good time to save a snapshot. + * editor.fire( 'saveSnapshot' ); + * console.log( widget.data.url ); // The above URL. It is only changed + * // once the content is successfully loaded. + * }, + * + * errorCallback: function( message ) { + * editor.showNotification( widget.getErrorMessage( message, url ), 'warning' ); + * } + * } ); + * + * @param {String} url Resource URL to be embedded. + * @param {Object} opts + * @param {Function} [opts.callback] Callback called when content was successfully loaded into the editor. + * @param {Function} [opts.errorCallback] Callback called when an error occurred. + * @param {String} opts.errorCallback.messageTypeOrMessage See {@link #getErrorMessage}. + * @param {Boolean} [opts.noNotifications] Do not show notifications (useful when the dialog is open). + * @returns {CKEDITOR.plugins.embedBase.request} + */ + loadContent: function( url, opts ) { + opts = opts || {}; + + var that = this, + cachedResponse = this._getCachedResponse( url ), + request = { + noNotifications: opts.noNotifications, + url: url, + callback: finishLoading, + errorCallback: function( msg ) { + that._handleError( request, msg ); + if ( opts.errorCallback ) { + opts.errorCallback( msg ); + } + } + }; + + if ( cachedResponse ) { + // Keep the async nature (it caused a bug the very first day when the loadContent() + // was synchronous when cache was hit :D). + setTimeout( function() { + finishLoading( cachedResponse ); + } ); + return; + } + + if ( !opts.noNotifications ) { + request.task = this._createTask(); + } + + // The execution will be followed by #sendRequest's listener. + this.fire( 'sendRequest', request ); + + function finishLoading( response ) { + request.response = response; + + // Check if widget is still valid. + if ( !that.editor.widgets.instances[ that.id ] ) { + CKEDITOR.warn( 'embedbase-widget-invalid' ); + + if ( request.task ) { + request.task.done(); + } + + return; + } + + if ( that._handleResponse( request ) ) { + that._cacheResponse( url, response ); + if ( opts.callback ) { + opts.callback(); + } + } + } + + return request; + }, + + /** + * Checks whether the URL is valid. Usually the content provider makes the final validation + * as only the provider knows what kind of URLs are accepted. However, to give the user some immediate feedback + * a synchronous validation is performed using the {@link #urlRegExp} pattern and the {@link #validateUrl} event. + * + * @param {String} url The URL to check. + * @returns {Boolean} Whether the URL is valid (supported). + */ + isUrlValid: function( url ) { + return this.urlRegExp.test( url ) && this.fire( 'validateUrl', url ) !== false; + }, + + /** + * Generates an error message based on the message type (with a possible suffix) or + * the custom message template. + * + * This method is used when showing a notification or an alert (in a dialog) about an error. + * Usually it is used with an error type which is a string from the `editor.lang.embedbase` object. + * + * There are two error types available at the moment: `'unsupportedUrl'` and `'fetchingFailed'`. + * Additionally, both can be suffixed with `'Given'`. See the language entries to see the difference. + * Inside the dialog this method is used with a suffix and to generate a notification message it is + * used without a suffix. + * + * Additionally, a custom message may be passed and just like language entries, it can use the `{url}` + * placeholder. + * + * While {@link #handleResponse handling the response} you can set an error message or its type. It will + * be passed to this method later. + * + * widget.on( 'handleResponse', function( evt ) { + * if ( evt.data.response.type != 'rich' ) { + * evt.data.errorMessage = '{url} cannot be embedded. Only rich type is supported.'; + * evt.cancel(); + * + * // Or: + * evt.data.errorMessage = 'unsupportedUrl.'; + * evt.cancel(); + * } + * } ); + * + * If you need to display your own error: + * + * editor.showNotification( + * widget.getErrorMessage( '{url} cannot be embedded. Only rich type is supported.', wrongUrl ) + * ); + * + * Or with a message type: + * + * editor.showNotification( + * widget.getErrorMessage( 'unsupportedUrl', wrongUrl ) + * ); + * + * @param {String} messageTypeOrMessage + * @param {String} [url] + * @param {String} [suffix] + * @returns {String} + */ + getErrorMessage: function( messageTypeOrMessage, url, suffix ) { + var message = editor.lang.embedbase[ messageTypeOrMessage + ( suffix || '' ) ]; + if ( !message ) { + message = messageTypeOrMessage; + } + + return new CKEDITOR.template( message ).output( { url: url || '' } ); + }, + + /** + * Sends the request to the {@link #providerUrl provider} using + * the {@link CKEDITOR.plugins.embedBase._jsonp JSONP} technique. + * + * @private + * @param {CKEDITOR.plugins.embedBase.request} request + */ + _sendRequest: function( request ) { + var that = this, + jsonpRequest = Jsonp.sendRequest( + this.providerUrl, + { + url: encodeURIComponent( request.url ) + }, + request.callback, + function() { + request.errorCallback( 'fetchingFailed' ); + } + ); + + request.cancel = function() { + jsonpRequest.cancel(); + that.fire( 'requestCanceled', request ); + }; + }, + + /** + * Handles the response of a successful request. + * + * Fires the {@link #handleResponse} event in order to convert the oEmbed response + * to HTML that can be embedded. + * + * If the response can be handled, the {@link #_setContent content is set}. + * + * @private + * @param {CKEDITOR.plugins.embedBase.request} request + * @returns {Boolean} Whether the response can be handled. Returns `false` if {@link #handleResponse} + * was canceled or the default listener could not convert oEmbed response into embeddable HTML. + */ + _handleResponse: function( request ) { + var evtData = { + url: request.url, + html: '', + response: request.response + }; + + if ( this.fire( 'handleResponse', evtData ) !== false ) { + if ( request.task ) { + request.task.done(); + } + + this._setContent( request.url, evtData.html ); + return true; + } else { + request.errorCallback( evtData.errorMessage ); + return false; + } + }, + + /** + * Handles an error. An error can be caused either by a request failure or an unsupported + * oEmbed response type. + * + * @private + * @param {CKEDITOR.plugins.embedBase.request} request + * @param {String} messageTypeOrMessage See {@link #getErrorMessage}. + */ + _handleError: function( request, messageTypeOrMessage ) { + if ( request.task ) { + request.task.cancel(); + + if ( !request.noNotifications ) { + editor.showNotification( this.getErrorMessage( messageTypeOrMessage, request.url ), 'warning' ); + } + } + }, + + /** + * Returns embeddable HTML for an oEmbed response if it is of the `photo`, `video` or `rich` type. + * + * @private + * @param {Object} response The oEmbed response. + * @returns {String/null} HTML string to be embedded or `null` if this response type is not supported. + */ + _responseToHtml: function( url, response ) { + if ( response.type == 'photo' ) { + return '<img src="' + CKEDITOR.tools.htmlEncodeAttr( response.url ) + '" ' + + 'alt="' + CKEDITOR.tools.htmlEncodeAttr( response.title || '' ) + '" style="max-width:100%;height:auto" />'; + } else if ( response.type == 'video' || response.type == 'rich' ) { + // Embedded iframes are added to page's focus list. Adding negative tabindex attribute + // removes their ability to be focused by user. (http://dev.ckeditor.com/ticket/14538) + response.html = response.html.replace( /<iframe/g, '<iframe tabindex="-1"' ); + + return response.html; + } + + return null; + }, + + /** + * The very final step of {@link #loadContent content loading}. The `url` data property is changed + * and the content is embedded ({@link CKEDITOR.plugins.widget#element}'s HTML is set). + * + * @private + * @param {String} url The resource URL. + * @param {String} content HTML content to be embedded. + */ + _setContent: function( url, content ) { + this.setData( 'url', url ); + this.element.setHtml( content ); + }, + + /** + * Creates a notification aggregator task. + * + * @private + * @returns {CKEDITOR.plugins.notificationAggregator.task} + */ + _createTask: function() { + if ( !aggregator || aggregator.isFinished() ) { + aggregator = new CKEDITOR.plugins.notificationAggregator( editor, lang.fetchingMany, lang.fetchingOne ); + + aggregator.on( 'finished', function() { + aggregator.notification.hide(); + } ); + } + + return aggregator.createTask(); + }, + + /** + * Caches the provider response. + * + * @private + * @param {String} url + * @param {Object} response + */ + _cacheResponse: function( url, response ) { + this._cache[ url ] = response; + }, + + /** + * Returns the cached response. + * + * @private + * @param {String} url + * @returns {Object/undefined} Response or `undefined` if the cache was missed. + */ + _getCachedResponse: function( url ) { + return this._cache[ url ]; + } + }; + + /** + * Fired by the {@link #isUrlValid} method. Cancel the event to make the URL invalid. + * + * @event validateUrl + * @param {String} data The URL being validated. + */ + + /** + * Fired by the {@link #loadContent} method to dispatch a request to the provider. + * You can cancel this event and send the request using a different technique. + * By default, if the event is not stopped or canceled a request will be sent + * using the JSONP technique. + * + * widget.on( 'sendRequest', function( evt ) { + * var request = evt.data; + * + * // Send the request using a technique of your choice (XHR with CORS for instance). + * myApp.requestOembedProvider( request.url, function( err, response ) { + * if ( err ) { + * request.errorCallback( err ); + * } else { + * request.callback( response ); + * } + * } ); + * + * // Do not call other listeners, so the default behavior (JSONP request) + * // will not be executed. + * evt.stop(); + * } ); + * + * @event sendRequest + * @param {CKEDITOR.plugins.embedBase.request} data + */ + + /** + * Fired after receiving a response from the {@link #providerUrl provider}. + * This event listener job is to turn the oEmbed response to embeddable HTML by setting + * `evt.data.html`. + * + * widget.on( 'handleReaponse', function( evt ) { + * evt.data.html = customOembedToHtmlConverter( evt.data.response ); + * } ); + * + * This event can also be canceled to indicate that the response cannot be handled. In such + * case the `evt.data.errorMessage` must be set (see {@link #getErrorMessage}). + * + * widget.on( 'handleReaponse', function( evt ) { + * if ( evt.data.response.type == 'photo' ) { + * // Will display the editor.lang.embedbase.unsupportedUrl(Given) message. + * evt.data.errorMessage = 'unsupportedUrl'; + * evt.cancel(); + * } + * } ); + * + * This event has a default late-listener (with a priority of `999`) that, if `evt.data.html` has not + * been set yet, will try to handle the response by using the {@link #_responseToHtml} method. + * + * @event handleResponse + * @param {Object} data + * @param {String} data.url The resource URL. + * @param {Object} data.response The oEmbed response. + * @param {String} [data.html=''] The HTML which will be embedded. + * @param {String} [data.errorMessage] The error message or message type (see {@link #getErrorMessage}) + * that must be set if this event is canceled to indicate an unsupported oEmbed response. + */ + } + + /** + * Class representing the request object. It is created by the {@link CKEDITOR.plugins.embedBase.baseDefinition#loadContent} + * method and is passed to other methods and events of this class. + * + * @abstract + * @class CKEDITOR.plugins.embedBase.request + */ + + /** + * The resource URL to be embedded (not the {@link CKEDITOR.plugins.embedBase.baseDefinition#providerUrl provider URL}). + * + * @property {String} url + */ + + /** + * Success callback to be executed once a response to a request is received. + * + * @property {Function} [callback] + * @param {Object} response The response object. + */ + + /** + * Callback executed in case of an error. + * + * @property {Function} [errorCallback] + * @param {String} messageTypeOrMessage See {@link CKEDITOR.plugins.embedBase.baseDefinition#getErrorMessage}. + */ + + /** + * Task that should be resolved once the request is done. + * + * @property {CKEDITOR.plugins.notificationAggregator.task} [task] + */ + + /** + * Response object. It is set once a response is received. + * + * @property {Object} [response] + */ + + /** + * Cancels the request. + * + * @method cancel + */ + + CKEDITOR.plugins.embedBase = { + createWidgetBaseDefinition: createWidgetBaseDefinition, + _jsonp: Jsonp + }; + +} )(); diff --git a/libraries/ckeditor/plugins/embedsemantic/icons/embedsemantic.png b/libraries/ckeditor/plugins/embedsemantic/icons/embedsemantic.png new file mode 100644 index 0000000000000000000000000000000000000000..9a9a73568eff8443f69985e68bc1f8039940b498 Binary files /dev/null and b/libraries/ckeditor/plugins/embedsemantic/icons/embedsemantic.png differ diff --git a/libraries/ckeditor/plugins/embedsemantic/icons/hidpi/embedsemantic.png b/libraries/ckeditor/plugins/embedsemantic/icons/hidpi/embedsemantic.png new file mode 100644 index 0000000000000000000000000000000000000000..97dc75475839dece3638850cd2d1628e1af4ed6b Binary files /dev/null and b/libraries/ckeditor/plugins/embedsemantic/icons/hidpi/embedsemantic.png differ diff --git a/libraries/ckeditor/plugins/embedsemantic/plugin.js b/libraries/ckeditor/plugins/embedsemantic/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..58ceb081358c2488ae6f0235ef7e10c758f01f93 --- /dev/null +++ b/libraries/ckeditor/plugins/embedsemantic/plugin.js @@ -0,0 +1,114 @@ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +( function() { + 'use strict'; + + CKEDITOR.plugins.add( 'embedsemantic', { + icons: 'embedsemantic', // %REMOVE_LINE_CORE% + hidpi: true, // %REMOVE_LINE_CORE% + requires: 'embedbase', + + onLoad: function() { + this.registerOembedTag(); + }, + + init: function( editor ) { + var widgetDefinition = CKEDITOR.plugins.embedBase.createWidgetBaseDefinition( editor ), + origInit = widgetDefinition.init; + + CKEDITOR.tools.extend( widgetDefinition, { + // Use a dialog exposed by the embedbase plugin. + dialog: 'embedBase', + button: editor.lang.embedbase.button, + allowedContent: 'oembed', + requiredContent: 'oembed', + styleableElements: 'oembed', + // Share config with the embed plugin. + providerUrl: new CKEDITOR.template( + editor.config.embed_provider || + '//ckeditor.iframe.ly/api/oembed?url={url}&callback={callback}' + ), + + init: function() { + var that = this; + + origInit.call( this ); + + // Need to wait for #ready with the initial content loading, because on #init there's no data yet. + this.once( 'ready', function() { + // When widget is created using dialog, the dialog's code will handle loading the content + // (because it handles success and error), so do load the content only when loading data. + if ( this.data.loadOnReady ) { + this.loadContent( this.data.url, { + callback: function() { + // Do not load the content again on widget's next initialization (e.g. after undo or paste). + // Plus, this is a small trick that we change loadOnReady now, inside the callback. + // It guarantees that if the content was not loaded (an error occurred or someone + // undid/copied sth to fast) the content will be loaded on the next initialization. + that.setData( 'loadOnReady', false ); + editor.fire( 'updateSnapshot' ); + } + } ); + } + } ); + }, + + upcast: function( element, data ) { + if ( element.name != 'oembed' ) { + return; + } + + var text = element.children[ 0 ], + div; + + if ( text && text.type == CKEDITOR.NODE_TEXT && text.value ) { + data.url = text.value; + data.loadOnReady = true; + div = new CKEDITOR.htmlParser.element( 'div' ); + element.replaceWith( div ); + + // Transfer widget classes from data to widget element (http://dev.ckeditor.com/ticket/13199). + div.attributes[ 'class' ] = element.attributes[ 'class' ]; + + return div; + } + }, + + downcast: function( element ) { + var ret = new CKEDITOR.htmlParser.element( 'oembed' ); + ret.add( new CKEDITOR.htmlParser.text( this.data.url ) ); + + // Transfer widget classes from widget element back to data (http://dev.ckeditor.com/ticket/13199). + if ( element.attributes[ 'class' ] ) { + ret.attributes[ 'class' ] = element.attributes[ 'class' ]; + } + + return ret; + } + }, true ); + + editor.widgets.add( 'embedSemantic', widgetDefinition ); + }, + + // Extends CKEDITOR.dtd so editor accepts <oembed> tag. + registerOembedTag: function() { + var dtd = CKEDITOR.dtd, + name; + + // The oembed tag may contain text only. + dtd.oembed = { '#': 1 }; + + // Register oembed tag as allowed child, in each tag that can contain a div. + // It also registers the oembed tag in objects like $block, $blockLimit, etc. + for ( name in dtd ) { + if ( dtd[ name ].div ) { + dtd[ name ].oembed = 1; + } + } + } + } ); + +} )(); diff --git a/libraries/ckeditor/plugins/notification/lang/az.js b/libraries/ckeditor/plugins/notification/lang/az.js new file mode 100644 index 0000000000000000000000000000000000000000..4f49687444260a8e1b5eb1b1f1d5dacadc59ccc0 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/az.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'az', { + closed: 'XÉ™bÉ™rdarlıq pÉ™ncÉ™rÉ™si baÄŸlanıb' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/ca.js b/libraries/ckeditor/plugins/notification/lang/ca.js new file mode 100644 index 0000000000000000000000000000000000000000..003b15855329d44302b00159afc6e6ec6a2ff8f9 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/ca.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'ca', { + closed: 'Notificació tancada.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/cs.js b/libraries/ckeditor/plugins/notification/lang/cs.js new file mode 100644 index 0000000000000000000000000000000000000000..7010669fdd0de6e48a180cdf4590131ee0a2f311 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/cs.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'cs', { + closed: 'Oznámenà zavÅ™eno.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/da.js b/libraries/ckeditor/plugins/notification/lang/da.js new file mode 100644 index 0000000000000000000000000000000000000000..59edbc68344e0464d16b7b156a4ef413848a3619 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/da.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'da', { + closed: 'Notefikation lukket.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/de-ch.js b/libraries/ckeditor/plugins/notification/lang/de-ch.js new file mode 100644 index 0000000000000000000000000000000000000000..d12540ad7dd660219031ee399bb6b1b4fdd7eec5 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/de-ch.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'de-ch', { + closed: 'Benachrichtigung geschlossen.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/de.js b/libraries/ckeditor/plugins/notification/lang/de.js new file mode 100644 index 0000000000000000000000000000000000000000..806a8d2f2496e839dfa8d43b535395c603f2db91 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/de.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'de', { + closed: 'Benachrichtigung geschlossen.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/en.js b/libraries/ckeditor/plugins/notification/lang/en.js new file mode 100644 index 0000000000000000000000000000000000000000..23297f14a01254700accd7bed60352bc76c6bb8c --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/en.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'en', { + closed: 'Notification closed.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/eo.js b/libraries/ckeditor/plugins/notification/lang/eo.js new file mode 100644 index 0000000000000000000000000000000000000000..f9f24dd207b24230d7a25cb4acb8df67946b1461 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/eo.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'eo', { + closed: 'Sciigo fermita' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/es-mx.js b/libraries/ckeditor/plugins/notification/lang/es-mx.js new file mode 100644 index 0000000000000000000000000000000000000000..e88ea36b96534eb0ddc0c49dad080e8330472b65 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/es-mx.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'es-mx', { + closed: 'Notificación cerrada.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/es.js b/libraries/ckeditor/plugins/notification/lang/es.js new file mode 100644 index 0000000000000000000000000000000000000000..d186eb8f9036c4aa16403f093ed6f72ad9a9834d --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/es.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'es', { + closed: 'Notificación cerrada.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/eu.js b/libraries/ckeditor/plugins/notification/lang/eu.js new file mode 100644 index 0000000000000000000000000000000000000000..d1f44dc2cf8057afad9fdcd84624f43a82bbb566 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/eu.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'eu', { + closed: 'Jakinarazpena itxita.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/fr.js b/libraries/ckeditor/plugins/notification/lang/fr.js new file mode 100644 index 0000000000000000000000000000000000000000..1f93a897123a7aeedc2e2e2d610278cfedf39d65 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/fr.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'fr', { + closed: 'Notification fermée.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/gl.js b/libraries/ckeditor/plugins/notification/lang/gl.js new file mode 100644 index 0000000000000000000000000000000000000000..fa54787a26721844691db26d7e5b77c54f1b0095 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/gl.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'gl', { + closed: 'Notificación pechada.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/hr.js b/libraries/ckeditor/plugins/notification/lang/hr.js new file mode 100644 index 0000000000000000000000000000000000000000..84d6789ae32ac0a87dbc5a29a169830a4fe113ce --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/hr.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'hr', { + closed: 'Obavijest zatvorena.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/hu.js b/libraries/ckeditor/plugins/notification/lang/hu.js new file mode 100644 index 0000000000000000000000000000000000000000..0db63f4b9a91e9761e0299b1b300f4dbb83b8f84 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/hu.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'hu', { + closed: 'ÉrtesÃtés bezárva.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/id.js b/libraries/ckeditor/plugins/notification/lang/id.js new file mode 100644 index 0000000000000000000000000000000000000000..5e7ec7a7f4cb8bc7c0d6bf167ef2aa6b4097a52b --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/id.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'id', { + closed: 'Pemberitahuan ditutup' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/it.js b/libraries/ckeditor/plugins/notification/lang/it.js new file mode 100644 index 0000000000000000000000000000000000000000..35e0bfa6ba735384db2fe9d5591d7f67e5d3499e --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/it.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'it', { + closed: 'Notifica chiusa.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/ja.js b/libraries/ckeditor/plugins/notification/lang/ja.js new file mode 100644 index 0000000000000000000000000000000000000000..9c917751a79cd8ba50860cde28c45ab72297eb10 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/ja.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'ja', { + closed: '通知を閉ã˜ã¾ã—ãŸã€‚' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/km.js b/libraries/ckeditor/plugins/notification/lang/km.js new file mode 100644 index 0000000000000000000000000000000000000000..cb3ba92b47ea2033f10e0ea57d4f708228efa62d --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/km.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'km', { + closed: 'បាន​បិទ​ការ​ផ្ដល់​ដំណឹង។' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/ko.js b/libraries/ckeditor/plugins/notification/lang/ko.js new file mode 100644 index 0000000000000000000000000000000000000000..78f069963b01afc39644c9def1040ae403f3eb7e --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/ko.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'ko', { + closed: 'ì•Œë¦¼ì´ ë‹«íž˜.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/ku.js b/libraries/ckeditor/plugins/notification/lang/ku.js new file mode 100644 index 0000000000000000000000000000000000000000..9ca9e27f7ea7cd904f6c93806ddc45e21d01b5b4 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/ku.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'ku', { + closed: 'ئاگادارکەرەوەکە داخرا.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/nb.js b/libraries/ckeditor/plugins/notification/lang/nb.js new file mode 100644 index 0000000000000000000000000000000000000000..0e94128126d79c8f9409a55d237c3dbcb7126ad0 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/nb.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'nb', { + closed: 'Varsling lukket.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/nl.js b/libraries/ckeditor/plugins/notification/lang/nl.js new file mode 100644 index 0000000000000000000000000000000000000000..d53e11470aacf62d7b14117758aacde9867ce99a --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/nl.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'nl', { + closed: 'Melding gesloten.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/oc.js b/libraries/ckeditor/plugins/notification/lang/oc.js new file mode 100644 index 0000000000000000000000000000000000000000..60da9ca7314558f00160c5313700257f94a8e35f --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/oc.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'oc', { + closed: 'Notificacion tampada.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/pl.js b/libraries/ckeditor/plugins/notification/lang/pl.js new file mode 100644 index 0000000000000000000000000000000000000000..5adbe0468ff15db45413ebe3290c4a7e6195f56e --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/pl.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'pl', { + closed: 'Powiadomienie zostaÅ‚o zamkniÄ™te.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/pt-br.js b/libraries/ckeditor/plugins/notification/lang/pt-br.js new file mode 100644 index 0000000000000000000000000000000000000000..b5a4980511fffef3a5b4d0fcec508e845e1d5106 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/pt-br.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'pt-br', { + closed: 'Notificação fechada.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/pt.js b/libraries/ckeditor/plugins/notification/lang/pt.js new file mode 100644 index 0000000000000000000000000000000000000000..6546eb4f6a2c2b101ddb11a88cdf12bf775959d5 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/pt.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'pt', { + closed: 'Notificação encerrada.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/ru.js b/libraries/ckeditor/plugins/notification/lang/ru.js new file mode 100644 index 0000000000000000000000000000000000000000..ee644a119ebf1e34292ae282648b749076b5a61e --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/ru.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'ru', { + closed: 'Уведомление закрыто' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/sk.js b/libraries/ckeditor/plugins/notification/lang/sk.js new file mode 100644 index 0000000000000000000000000000000000000000..56132ebc6f333cdec6d3bd3cada3354b38566ab8 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/sk.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'sk', { + closed: 'Notifikácia zatvorená.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/sv.js b/libraries/ckeditor/plugins/notification/lang/sv.js new file mode 100644 index 0000000000000000000000000000000000000000..3ce23680bc03bfbd2d7d5088cc3f888d7f28414c --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/sv.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'sv', { + closed: 'Notifiering stängd.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/tr.js b/libraries/ckeditor/plugins/notification/lang/tr.js new file mode 100644 index 0000000000000000000000000000000000000000..4cd2ed4f9c22a77b8b688e6ce7c4a31b4f6d17c0 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/tr.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'tr', { + closed: 'Uyarılar kapatıldı.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/ug.js b/libraries/ckeditor/plugins/notification/lang/ug.js new file mode 100644 index 0000000000000000000000000000000000000000..07b8c6003cd1fe61c7b71b8a90db4fbedeb1c2e9 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/ug.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'ug', { + closed: 'ئوقتۇرۇش تاقالدى.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/uk.js b/libraries/ckeditor/plugins/notification/lang/uk.js new file mode 100644 index 0000000000000000000000000000000000000000..91b77248fcec65c45225e55098978016e803b65b --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/uk.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'uk', { + closed: 'Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°ÐºÑ€Ð¸Ñ‚Ð¾.' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/zh-cn.js b/libraries/ckeditor/plugins/notification/lang/zh-cn.js new file mode 100644 index 0000000000000000000000000000000000000000..697d153e873f64d17995dfbfaab5a60e54a7f449 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/zh-cn.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'zh-cn', { + closed: '通知已关é—' +} ); diff --git a/libraries/ckeditor/plugins/notification/lang/zh.js b/libraries/ckeditor/plugins/notification/lang/zh.js new file mode 100644 index 0000000000000000000000000000000000000000..d3eb04e49d9443c89bd531f671bfb89b623f4a24 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/lang/zh.js @@ -0,0 +1,7 @@ +/* +Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.md or http://ckeditor.com/license +*/ +CKEDITOR.plugins.setLang( 'notification', 'zh', { + closed: '通知已關閉。' +} ); diff --git a/libraries/ckeditor/plugins/notification/plugin.js b/libraries/ckeditor/plugins/notification/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..a61d940cfde50e15f5d4428e4d376292efbbce91 --- /dev/null +++ b/libraries/ckeditor/plugins/notification/plugin.js @@ -0,0 +1,923 @@ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +/** + * @fileOverview The "Notification" plugin. + * + */ + +'use strict'; + +CKEDITOR.plugins.add( 'notification', { + lang: 'az,ca,cs,da,de,de-ch,en,eo,es,es-mx,eu,fr,gl,hr,hu,id,it,ja,km,ko,ku,nb,nl,oc,pl,pt,pt-br,ru,sk,sv,tr,ug,uk,zh,zh-cn', // %REMOVE_LINE_CORE% + requires: 'toolbar', + + init: function( editor ) { + editor._.notificationArea = new Area( editor ); + + // Overwrites default `editor.showNotification`. + editor.showNotification = function( message, type, progressOrDuration ) { + var progress, duration; + + if ( type == 'progress' ) { + progress = progressOrDuration; + } else { + duration = progressOrDuration; + } + + var notification = new CKEDITOR.plugins.notification( editor, { + message: message, + type: type, + progress: progress, + duration: duration + } ); + + notification.show(); + + return notification; + }; + + // Close the last notification on ESC. + editor.on( 'key', function( evt ) { + if ( evt.data.keyCode == 27 ) { /* ESC */ + var notifications = editor._.notificationArea.notifications; + + if ( !notifications.length ) { + return; + } + + // As long as this is not a common practice to inform screen-reader users about actions, in this case + // this is the best solution (unfortunately there is no standard for accessibility for notifications). + // Notification has an `alert` aria role what means that it does not get a focus nor is needed to be + // closed (unlike `alertdialog`). However notification will capture ESC key so we need to inform user + // why it does not do other actions. + say( editor.lang.notification.closed ); + + // Hide last. + notifications[ notifications.length - 1 ].hide(); + + evt.cancel(); + } + } ); + + // Send the message to the screen readers. + function say( text ) { + var message = new CKEDITOR.dom.element( 'div' ); + message.setStyles( { + position: 'fixed', + 'margin-left': '-9999px' + } ); + message.setAttributes( { + 'aria-live': 'assertive', + 'aria-atomic': 'true' + } ); + message.setText( text ); + + CKEDITOR.document.getBody().append( message ); + + setTimeout( function() { + message.remove(); + }, 100 ); + } + } +} ); + +/** + * Notification class. Notifications are used to display short messages to the user. They might be used to show the result of + * asynchronous actions or information about changes in the editor content. It is recommended to use them instead of + * alert dialogs. They should **not** be used if a user response is required nor with dialog windows (e.g. in dialog validation). + * + * There are four types of notifications available, see the {@link #type} property. + * + * Note that the notification constructor only creates a notification instance. To show it, use the {@link #show} method: + * + * var notification = new CKEDITOR.plugins.notification( editor, { message: 'Foo' } ); + * notification.show(); + * + * You can also use the {@link CKEDITOR.editor#showNotification} method: + * + * editor.showNotification( 'Foo' ); + * + * All of the notification actions: ({@link #show}, {@link #update} and {@link #hide}) fire cancelable events + * on the related {@link CKEDITOR.editor} instance so you can integrate editor notifications with your website notifications. + * + * Refer to the [Notifications](http://docs.ckeditor.com/#!/guide/dev_notifications) article for more information about this feature. + * + * @since 4.5 + * @class CKEDITOR.plugins.notification + * @constructor Create a notification object. Call {@link #show} to show the created notification. + * @param {CKEDITOR.editor} editor The editor instance. + * @param {Object} options + * @param {String} options.message The message displayed in the notification. + * @param {String} [options.type='info'] Notification type, see {@link #type}. + * @param {Number} [options.progress=0] If the type is `progress` this may be a progress from 0 to 1. + * @param {Number} [options.duration] How long the notification will be visible, see {@link #duration}. + */ +function Notification( editor, options ) { + CKEDITOR.tools.extend( this, options, { + editor: editor, + id: 'cke-' + CKEDITOR.tools.getUniqueId(), + area: editor._.notificationArea + } ); + + if ( !options.type ) { + this.type = 'info'; + } + + this.element = this._createElement(); + + // Don't allow dragging on notification (http://dev.ckeditor.com/ticket/13184). + editor.plugins.clipboard && CKEDITOR.plugins.clipboard.preventDefaultDropOnElement( this.element ); +} + +/** + * The editor instance. + * + * @readonly + * @property {CKEDITOR.editor} editor + */ + +/** + * Message displayed in the notification. + * + * @readonly + * @property {String} message + */ + +/** + * Notification type. There are four types available: + * + * * `info` (default) – Information for the user (e.g. "File is uploading.", "ACF modified content."), + * * `warning` – Warning or error message (e.g. "This type of file is not supported.", + * "You cannot paste the script."), + * * `success` – Information that an operation finished successfully (e.g. "File uploaded.", "Data imported."). + * * `progress` – Information about the progress of an operation. When the operation is done, the notification + * type should be changed to `success`. + * + * @readonly + * @property {String} type + */ + +/** + * If the notification {@link #type} is `'progress'`, this is the progress from `0` to `1`. + * + * @readonly + * @property {Number} progress + */ + +/** + * Notification duration. Determines after how many milliseconds the notification should close automatically. + * `0` means that the notification will not close automatically and that the user needs to close it manually. + * The default value for `warning` and `progress` notifications is `0`. For `info` and `success` the value can + * either be set through the {@link CKEDITOR.config#notification_duration} configuration option or equals `5000` + * if the configuration option is not set. + * + * @readonly + * @property {Number} duration + */ + +/** + * Unique notification ID. + * + * @readonly + * @property {Number} id + */ + +/** + * Notification DOM element. There is one element per notification. It is created when the notification is created, + * even if it is not shown. If the notification is hidden, the element is detached from the document but not deleted. + * It will be reused if the notification is shown again. + * + * @readonly + * @property {CKEDITOR.dom.element} element + */ + +/** + * {@link CKEDITOR.plugins.notification.area Notification area} reference. + * + * @readonly + * @property {CKEDITOR.plugins.notification.area} area + */ + +Notification.prototype = { + /** + * Adds the notification element to the notification area. The notification will be hidden automatically if + * {@link #duration} is set. + * + * Fires the {@link CKEDITOR.editor#notificationShow} event. + */ + show: function() { + if ( this.editor.fire( 'notificationShow', { notification: this } ) === false ) { + return; + } + + this.area.add( this ); + + this._hideAfterTimeout(); + }, + + /** + * Updates the notification object and element. + * + * Fires the {@link CKEDITOR.editor#notificationUpdate} event. + * + * @param {Object} options + * @param {String} [options.message] {@link #message} + * @param {String} [options.type] {@link #type} + * @param {Number} [options.progress] {@link #progress} + * @param {Number} [options.duration] {@link #duration} + * @param {Boolean} [options.important=false] If the update is important, the notification will be shown + * if it was hidden and read by screen readers. + */ + update: function( options ) { + var show = true; + + if ( this.editor.fire( 'notificationUpdate', { notification: this, options: options } ) === false ) { + // The idea of cancelable event is to let user create his own way of displaying notification, so if + // `notificationUpdate` event will be canceled there will be no interaction with notification area, but on + // the other hand the logic should work anyway so object will be updated (including `element` property). + // Note: we can safely update the element's attributes below, because this element is created inside + // the constructor. If the notificatinShow event was canceled as well, the element is detached from DOM. + show = false; + } + + var element = this.element, + messageElement = element.findOne( '.cke_notification_message' ), + progressElement = element.findOne( '.cke_notification_progress' ), + type = options.type; + + element.removeAttribute( 'role' ); + + // Change type to progress if `options.progress` is set. + if ( options.progress && this.type != 'progress' ) { + type = 'progress'; + } + + if ( type ) { + element.removeClass( this._getClass() ); + element.removeAttribute( 'aria-label' ); + + this.type = type; + + element.addClass( this._getClass() ); + element.setAttribute( 'aria-label', this.type ); + + if ( this.type == 'progress' && !progressElement ) { + progressElement = this._createProgressElement(); + progressElement.insertBefore( messageElement ); + } else if ( this.type != 'progress' && progressElement ) { + progressElement.remove(); + } + } + + if ( options.message !== undefined ) { + this.message = options.message; + messageElement.setHtml( this.message ); + } + + if ( options.progress !== undefined ) { + this.progress = options.progress; + + if ( progressElement ) { + progressElement.setStyle( 'width', this._getPercentageProgress() ); + } + } + + if ( show && options.important ) { + element.setAttribute( 'role', 'alert' ); + + if ( !this.isVisible() ) { + this.area.add( this ); + } + } + + // Overwrite even if it is undefined. + this.duration = options.duration; + + this._hideAfterTimeout(); + }, + + /** + * Removes the notification element from the notification area. + * + * Fires the {@link CKEDITOR.editor#notificationHide} event. + */ + hide: function() { + if ( this.editor.fire( 'notificationHide', { notification: this } ) === false ) { + return; + } + + this.area.remove( this ); + }, + + /** + * Returns `true` if the notification is in the notification area. + * + * @returns {Boolean} `true` if the notification is in the notification area. + */ + isVisible: function() { + return CKEDITOR.tools.indexOf( this.area.notifications, this ) >= 0; + }, + + /** + * Creates the notification DOM element. + * + * @private + * @returns {CKEDITOR.dom.element} Notification DOM element. + */ + _createElement: function() { + var notification = this, + notificationElement, notificationMessageElement, notificationCloseElement, + close = this.editor.lang.common.close; + + notificationElement = new CKEDITOR.dom.element( 'div' ); + notificationElement.addClass( 'cke_notification' ); + notificationElement.addClass( this._getClass() ); + notificationElement.setAttributes( { + id: this.id, + role: 'alert', + 'aria-label': this.type + } ); + + if ( this.type == 'progress' ) + notificationElement.append( this._createProgressElement() ); + + notificationMessageElement = new CKEDITOR.dom.element( 'p' ); + notificationMessageElement.addClass( 'cke_notification_message' ); + notificationMessageElement.setHtml( this.message ); + notificationElement.append( notificationMessageElement ); + + notificationCloseElement = CKEDITOR.dom.element.createFromHtml( + '<a class="cke_notification_close" href="javascript:void(0)" title="' + close + '" role="button" tabindex="-1">' + + '<span class="cke_label">X</span>' + + '</a>' ); + notificationElement.append( notificationCloseElement ); + + notificationCloseElement.on( 'click', function() { + // Focus editor on close (http://dev.ckeditor.com/ticket/12865) + notification.editor.focus(); + + notification.hide(); + } ); + + return notificationElement; + }, + + /** + * Gets the notification CSS class. + * + * @private + * @returns {String} Notification CSS class. + */ + _getClass: function() { + return ( this.type == 'progress' ) ? + 'cke_notification_info' : + ( 'cke_notification_' + this.type ); + }, + + /** + * Creates a progress element for the notification element. + * + * @private + * @returns {CKEDITOR.dom.element} Progress element for the notification element. + */ + _createProgressElement: function() { + var element = new CKEDITOR.dom.element( 'span' ); + element.addClass( 'cke_notification_progress' ); + element.setStyle( 'width', this._getPercentageProgress() ); + return element; + }, + + /** + * Gets the progress as a percentage (ex. `0.3` -> `30%`). + * + * @private + * @returns {String} Progress as a percentage. + */ + _getPercentageProgress: function() { + return Math.round( ( this.progress || 0 ) * 100 ) + '%'; + }, + + /** + * Hides the notification after a timeout. + * + * @private + */ + _hideAfterTimeout: function() { + var notification = this, + duration; + + if ( this._hideTimeoutId ) { + clearTimeout( this._hideTimeoutId ); + } + + if ( typeof this.duration == 'number' ) { + duration = this.duration; + } else if ( this.type == 'info' || this.type == 'success' ) { + duration = ( typeof this.editor.config.notification_duration == 'number' ) ? + this.editor.config.notification_duration : + 5000; + } + + if ( duration ) { + notification._hideTimeoutId = setTimeout( function() { + notification.hide(); + }, duration ); + } + } +}; + +/** + * Notification area is an area where all notifications are put. The area is laid out dynamically. + * When the first notification is added, the area is shown and all listeners are added. + * When the last notification is removed, the area is hidden and all listeners are removed. + * + * @since 4.5 + * @private + * @class CKEDITOR.plugins.notification.area + * @constructor + * @param {CKEDITOR.editor} editor The editor instance. + */ +function Area( editor ) { + var that = this; + + this.editor = editor; + this.notifications = []; + this.element = this._createElement(); + this._uiBuffer = CKEDITOR.tools.eventsBuffer( 10, this._layout, this ); + this._changeBuffer = CKEDITOR.tools.eventsBuffer( 500, this._layout, this ); + + editor.on( 'destroy', function() { + that._removeListeners(); + that.element.remove(); + } ); +} + +/** + * The editor instance. + * + * @readonly + * @property {CKEDITOR.editor} editor + */ + +/** + * The array of added notifications. + * + * @readonly + * @property {Array} notifications + */ + +/** + * Notification area DOM element. This element is created when the area object is created. It will be attached to the document + * when the first notification is added and removed when the last notification is removed. + * + * @readonly + * @property {CKEDITOR.dom.element} element + */ + +/** + * Notification width. Cached for performance reasons. + * + * @private + * @property {CKEDITOR.dom.element} _notificationWidth + */ + +/** + * Notification margin. Cached for performance reasons. + * + * @private + * @property {CKEDITOR.dom.element} _notificationMargin + */ + +/** + * Event buffer object for UI events to optimize performance. + * + * @private + * @property {Object} _uiBuffer + */ + +/** + * Event buffer object for editor change events to optimize performance. + * + * @private + * @property {Object} _changeBuffer + */ + +Area.prototype = { + /** + * Adds the notification to the notification area. If it is the first notification, the area will also be attached to + * the document and listeners will be attached. + * + * Note that the proper way to show a notification is to call the {@link CKEDITOR.plugins.notification#show} method. + * + * @param {CKEDITOR.plugins.notification} notification Notification to add. + */ + add: function( notification ) { + this.notifications.push( notification ); + + this.element.append( notification.element ); + + if ( this.element.getChildCount() == 1 ) { + CKEDITOR.document.getBody().append( this.element ); + this._attachListeners(); + } + + this._layout(); + }, + + /** + * Removes the notification from the notification area. If it is the last notification, the area will also be + * detached from the document and listeners will be detached. + * + * Note that the proper way to hide a notification is to call the {@link CKEDITOR.plugins.notification#hide} method. + * + * @param {CKEDITOR.plugins.notification} notification Notification to remove. + */ + remove: function( notification ) { + var i = CKEDITOR.tools.indexOf( this.notifications, notification ); + + if ( i < 0 ) { + return; + } + + this.notifications.splice( i, 1 ); + + notification.element.remove(); + + if ( !this.element.getChildCount() ) { + this._removeListeners(); + this.element.remove(); + } + }, + + /** + * Creates the notification area element. + * + * @private + * @returns {CKEDITOR.dom.element} Notification area element. + */ + _createElement: function() { + var editor = this.editor, + config = editor.config, + notificationArea = new CKEDITOR.dom.element( 'div' ); + + notificationArea.addClass( 'cke_notifications_area' ); + notificationArea.setAttribute( 'id', 'cke_notifications_area_' + editor.name ); + notificationArea.setStyle( 'z-index', config.baseFloatZIndex - 2 ); + + return notificationArea; + }, + + /** + * Attaches listeners to the notification area. + * + * @private + */ + _attachListeners: function() { + var win = CKEDITOR.document.getWindow(), + editor = this.editor; + + win.on( 'scroll', this._uiBuffer.input ); + win.on( 'resize', this._uiBuffer.input ); + editor.on( 'change', this._changeBuffer.input ); + editor.on( 'floatingSpaceLayout', this._layout, this, null, 20 ); + editor.on( 'blur', this._layout, this, null, 20 ); + }, + + /** + * Detaches listeners from the notification area. + * + * @private + */ + _removeListeners: function() { + var win = CKEDITOR.document.getWindow(), + editor = this.editor; + + win.removeListener( 'scroll', this._uiBuffer.input ); + win.removeListener( 'resize', this._uiBuffer.input ); + editor.removeListener( 'change', this._changeBuffer.input ); + editor.removeListener( 'floatingSpaceLayout', this._layout ); + editor.removeListener( 'blur', this._layout ); + }, + + /** + * Sets the position of the notification area based on the editor content, toolbar as well as + * viewport position and dimensions. + * + * @private + */ + _layout: function() { + var area = this.element, + editor = this.editor, + contentsRect = editor.ui.contentsElement.getClientRect(), + contentsPos = editor.ui.contentsElement.getDocumentPosition(), + top = editor.ui.space( 'top' ), + topRect = top.getClientRect(), + areaRect = area.getClientRect(), + notification, + notificationWidth = this._notificationWidth, + notificationMargin = this._notificationMargin, + win = CKEDITOR.document.getWindow(), + scrollPos = win.getScrollPosition(), + viewRect = win.getViewPaneSize(), + body = CKEDITOR.document.getBody(), + bodyPos = body.getDocumentPosition(), + cssLength = CKEDITOR.tools.cssLength; + + // Cache for optimization + if ( !notificationWidth || !notificationMargin ) { + notification = this.element.getChild( 0 ); + notificationWidth = this._notificationWidth = notification.getClientRect().width; + notificationMargin = this._notificationMargin = + parseInt( notification.getComputedStyle( 'margin-left' ), 10 ) + + parseInt( notification.getComputedStyle( 'margin-right' ), 10 ); + } + + // --------------------------------------- Horizontal layout ---------------------------------------- + + // +---Viewport-------------------------------+ +---Viewport-------------------------------+ + // | | | | + // | +---Toolbar----------------------------+ | | +---Content----------------------------+ | + // | | | | | | | | + // | +---Content----------------------------+ | | | | | + // | | | | | +---Toolbar----------------------+ | | + // | | +------Notification------+ | | | | | | | + // | | | | OR | +--------------------------------+ | | + // | | | | | | | | + // | | | | | | +------Notification------+ | | + // | | | | | | | | + // | | | | | | | | + // | +--------------------------------------+ | | +--------------------------------------+ | + // +------------------------------------------+ +------------------------------------------+ + if ( top.isVisible() && + topRect.bottom > contentsRect.top && + topRect.bottom < contentsRect.bottom - areaRect.height ) { + setBelowToolbar(); + + // +---Viewport-------------------------------+ + // | | + // | +---Content----------------------------+ | + // | | | | + // | | +------Notification------+ | | + // | | | | + // | | | | + // | | | | + // | +--------------------------------------+ | + // | | + // +------------------------------------------+ + } else if ( contentsRect.top > 0 ) { + setTopStandard(); + + // +---Content----------------------------+ + // | | + // +---Viewport-------------------------------+ + // | | | | + // | | +------Notification------+ | | + // | | | | + // | | | | + // | | | | + // | +--------------------------------------+ | + // | | + // +------------------------------------------+ + } else if ( contentsPos.y + contentsRect.height - areaRect.height > scrollPos.y ) { + setTopFixed(); + + // +---Content----------------------------+ +---Content----------------------------+ + // | | | | + // | | | | + // | | | +------Notification------+ | + // | | | | + // | | OR +--------------------------------------+ + // +---Viewport-------------------------------+ + // | | +------Notification------+ | | +---Viewport-------------------------------+ + // | | | | | | + // | +--------------------------------------+ | | | + // | | | | + // +------------------------------------------+ +------------------------------------------+ + } else { + setBottom(); + } + + function setTopStandard() { + area.setStyles( { + position: 'absolute', + top: cssLength( contentsPos.y ) + } ); + } + + function setBelowToolbar() { + area.setStyles( { + position: 'fixed', + top: cssLength( topRect.bottom ) + } ); + } + + function setTopFixed() { + area.setStyles( { + position: 'fixed', + top: 0 + } ); + } + + function setBottom() { + area.setStyles( { + position: 'absolute', + top: cssLength( contentsPos.y + contentsRect.height - areaRect.height ) + } ); + } + + // ---------------------------------------- Vertical layout ----------------------------------------- + + var leftBase = area.getStyle( 'position' ) == 'fixed' ? + contentsRect.left : + body.getComputedStyle( 'position' ) != 'static' ? contentsPos.x - bodyPos.x : contentsPos.x; + + // Content is narrower than notification + if ( contentsRect.width < notificationWidth + notificationMargin ) { + + // +---Viewport-------------------------------+ + // | | + // | +---Content------------+ | + // | | | | + // | +------Notification------+ | | + // | | | | + // | +----------------------+ | + // | | + // +------------------------------------------+ + if ( contentsPos.x + notificationWidth + notificationMargin > scrollPos.x + viewRect.width ) { + setRight(); + + // +---Viewport-------------------------------+ +---Viewport--------------------------+ + // | | | | + // | +---Content------------+ | +---Content------------+ | + // | | | | | | | | + // | | +------Notification------+ | OR | +------Notification------+ | + // | | | | | | | | + // | +----------------------+ | +----------------------+ | + // | | | | + // +------------------------------------------+ +-------------------------------------+ + } else { + setLeft(); + } + + // Content is wider than notification. + } else { + + // +--+Viewport+------------------------+ + // | | + // | +---Content-----------------------------------------+ + // | | | | + // | | +-----+Notification+-----+ | + // | | | | + // | | | | + // | | | | + // | +---------------------------------------------------+ + // | | + // +------------------------------------+ + if ( contentsPos.x + notificationWidth + notificationMargin > scrollPos.x + viewRect.width ) { + setLeft(); + + // +---Viewport-------------------------+ + // | | + // | +---Content----------------------------------------------+ + // | | | | + // | | +------Notification------+ | | + // | | | | + // | | | | + // | +--------------------------------------------------------+ + // | | + // +------------------------------------+ + } else if ( contentsPos.x + contentsRect.width / 2 + + notificationWidth / 2 + notificationMargin > scrollPos.x + viewRect.width ) { + setRightFixed(); + + // +---Viewport-------------------------+ + // | | + // +---Content----------------------------+ | + // | | | | + // | +------Notification------+ | | + // | | | | + // | | | | + // +--------------------------------------+ | + // | | + // +------------------------------------+ + } else if ( contentsRect.left + contentsRect.width - notificationWidth - notificationMargin < 0 ) { + setRight(); + + // +---Viewport-------------------------+ + // | | + // +---Content---------------------------------------------+ | + // | | | | + // | | +------Notification------+ | | + // | | | | + // | | | | + // +-------------------------------------------------------+ | + // | | + // +------------------------------------+ + } else if ( contentsRect.left + contentsRect.width / 2 - notificationWidth / 2 < 0 ) { + setLeftFixed(); + + // +---Viewport-------------------------+ + // | | + // | +---Content----------------------+ | + // | | | | + // | | +-----Notification-----+ | | + // | | | | + // | | | | + // | +--------------------------------+ | + // | | + // +------------------------------------+ + } else { + setCenter(); + } + } + + function setLeft() { + area.setStyle( 'left', cssLength( leftBase ) ); + } + + function setLeftFixed() { + area.setStyle( 'left', cssLength( leftBase - contentsPos.x + scrollPos.x ) ); + } + + function setCenter() { + area.setStyle( 'left', cssLength( leftBase + contentsRect.width / 2 - notificationWidth / 2 - notificationMargin / 2 ) ); + } + + function setRight() { + area.setStyle( 'left', cssLength( leftBase + contentsRect.width - notificationWidth - notificationMargin ) ); + } + + function setRightFixed() { + area.setStyle( 'left', cssLength( leftBase - contentsPos.x + scrollPos.x + viewRect.width - + notificationWidth - notificationMargin ) ); + } + } +}; + +CKEDITOR.plugins.notification = Notification; + +/** + * After how many milliseconds the notification of the `info` and `success` + * {@link CKEDITOR.plugins.notification#type type} should close automatically. + * `0` means that notifications will not close automatically. + * Note that `warning` and `progress` notifications will never close automatically. + * + * Refer to the [Notifications](http://docs.ckeditor.com/#!/guide/dev_notifications) article + * for more information about this feature. + * + * @since 4.5 + * @cfg {Number} [notification_duration=5000] + * @member CKEDITOR.config + */ + +/** + * Event fired when the {@link CKEDITOR.plugins.notification#show} method is called, before the + * notification is shown. If this event is canceled, the notification will not be shown. + * + * Using this event allows you to fully customize how a notification will be shown. It may be used to integrate + * the CKEditor notification system with your web page notifications. + * + * @since 4.5 + * @event notificationShow + * @member CKEDITOR.editor + * @param data + * @param {CKEDITOR.plugins.notification} data.notification Notification which will be shown. + * @param {CKEDITOR.editor} editor The editor instance. + */ + +/** + * Event fired when the {@link CKEDITOR.plugins.notification#update} method is called, before the + * notification is updated. If this event is canceled, the notification will not be shown even if the update was important, + * but the object will be updated anyway. Note that canceling this event does not prevent updating {@link #element} + * attributes, but if {@link #notificationShow} was canceled as well, this element is detached from the DOM. + * + * Using this event allows you to fully customize how a notification will be updated. It may be used to integrate + * the CKEditor notification system with your web page notifications. + * + * @since 4.5 + * @event notificationUpdate + * @member CKEDITOR.editor + * @param data + * @param {CKEDITOR.plugins.notification} data.notification Notification which will be updated. + * Note that it contains the data that has not been updated yet. + * @param {Object} data.options Update options, see {@link CKEDITOR.plugins.notification#update}. + * @param {CKEDITOR.editor} editor The editor instance. + */ + +/** + * Event fired when the {@link CKEDITOR.plugins.notification#hide} method is called, before the + * notification is hidden. If this event is canceled, the notification will not be hidden. + * + * Using this event allows you to fully customize how a notification will be hidden. It may be used to integrate + * the CKEditor notification system with your web page notifications. + * + * @since 4.5 + * @event notificationHide + * @member CKEDITOR.editor + * @param data + * @param {CKEDITOR.plugins.notification} data.notification Notification which will be hidden. + * @param {CKEDITOR.editor} editor The editor instance. + */ diff --git a/libraries/ckeditor/plugins/notificationaggregator/plugin.js b/libraries/ckeditor/plugins/notificationaggregator/plugin.js new file mode 100644 index 0000000000000000000000000000000000000000..ad2ae4a983ded4a8be8275924fd09c287554a2fe --- /dev/null +++ b/libraries/ckeditor/plugins/notificationaggregator/plugin.js @@ -0,0 +1,548 @@ +/** + * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +/** + * @fileOverview The "Notification Aggregator" plugin. + * + */ + +( function() { + 'use strict'; + + CKEDITOR.plugins.add( 'notificationaggregator', { + requires: 'notification' + } ); + + /** + * An aggregator of multiple tasks (progresses) which should be displayed using one + * {@link CKEDITOR.plugins.notification notification}. + * + * Once all the tasks are done, it means that the whole process is finished and the {@link #finished} + * event will be fired. + * + * New tasks can be created after the previous set of tasks is finished. This will continue the process and + * fire the {@link #finished} event again when it is done. + * + * Simple usage example: + * + * // Declare one aggregator that will be used for all tasks. + * var aggregator; + * + * // ... + * + * // Create a new aggregator if the previous one finished all tasks. + * if ( !aggregator || aggregator.isFinished() ) { + * // Create a new notification aggregator instance. + * aggregator = new CKEDITOR.plugins.notificationAggregator( editor, 'Loading process, step {current} of {max}...' ); + * + * // Change the notification type to 'success' on finish. + * aggregator.on( 'finished', function() { + * aggregator.notification.update( { message: 'Done', type: 'success' } ); + * } ); + * } + * + * // Create 3 tasks. + * var taskA = aggregator.createTask(), + * taskB = aggregator.createTask(), + * taskC = aggregator.createTask(); + * + * // At this point the notification contains a message: "Loading process, step 0 of 3...". + * + * // Let's close the first one immediately. + * taskA.done(); // "Loading process, step 1 of 3...". + * + * // One second later the message will be: "Loading process, step 2 of 3...". + * setTimeout( function() { + * taskB.done(); + * }, 1000 ); + * + * // Two seconds after the previous message the last task will be completed, meaning that + * // the notification will be closed. + * setTimeout( function() { + * taskC.done(); + * }, 3000 ); + * + * @since 4.5 + * @class CKEDITOR.plugins.notificationAggregator + * @mixins CKEDITOR.event + * @constructor Creates a notification aggregator instance. + * @param {CKEDITOR.editor} editor + * @param {String} message The template for the message to be displayed in the notification. The template can use + * the following variables: + * + * * `{current}` – The number of completed tasks. + * * `{max}` – The number of tasks. + * * `{percentage}` – The progress (number 0-100). + * + * @param {String/null} [singularMessage=null] An optional template for the message to be displayed in the notification + * when there is only one task remaining. This template can use the same variables as the `message` template. + * If `null`, then the `message` template will be used. + */ + function Aggregator( editor, message, singularMessage ) { + /** + * @readonly + * @property {CKEDITOR.editor} editor + */ + this.editor = editor; + + /** + * Notification created by the aggregator. + * + * The notification object is modified as aggregator tasks are being closed. + * + * @readonly + * @property {CKEDITOR.plugins.notification/null} + */ + this.notification = null; + + /** + * A template for the notification message. + * + * The template can use the following variables: + * + * * `{current}` – The number of completed tasks. + * * `{max}` – The number of tasks. + * * `{percentage}` – The progress (number 0-100). + * + * @private + * @property {CKEDITOR.template} + */ + this._message = new CKEDITOR.template( message ); + + /** + * A template for the notification message used when only one task is loading. + * + * Sometimes there might be a need to specify a special message when there + * is only one task loading, and to display standard messages in other cases. + * + * For example, you might want to show a message "Translating a widget" rather than + * "Translating widgets (1 of 1)", but still you would want to have a message + * "Translating widgets (2 of 3)" if more widgets are being translated at the same + * time. + * + * Template variables are the same as in {@link #_message}. + * + * @private + * @property {CKEDITOR.template/null} + */ + this._singularMessage = singularMessage ? new CKEDITOR.template( singularMessage ) : null; + + // Set the _tasks, _totalWeights, _doneWeights, _doneTasks properties. + this._tasks = []; + this._totalWeights = 0; + this._doneWeights = 0; + this._doneTasks = 0; + + /** + * Array of tasks tracked by the aggregator. + * + * @private + * @property {CKEDITOR.plugins.notificationAggregator.task[]} _tasks + */ + + /** + * Stores the sum of declared weights for all contained tasks. + * + * @private + * @property {Number} _totalWeights + */ + + /** + * Stores the sum of done weights for all contained tasks. + * + * @private + * @property {Number} _doneWeights + */ + + /** + * Stores the count of tasks done. + * + * @private + * @property {Number} _doneTasks + */ + } + + Aggregator.prototype = { + /** + * Creates a new task that can be updated to indicate the progress. + * + * @param [options] Options object for the task creation. + * @param [options.weight] For more information about weight, see the + * {@link CKEDITOR.plugins.notificationAggregator.task} overview. + * @returns {CKEDITOR.plugins.notificationAggregator.task} An object that represents the task state, and allows + * for its manipulation. + */ + createTask: function( options ) { + options = options || {}; + + var initialTask = !this.notification, + task; + + if ( initialTask ) { + // It's a first call. + this.notification = this._createNotification(); + } + + task = this._addTask( options ); + + task.on( 'updated', this._onTaskUpdate, this ); + task.on( 'done', this._onTaskDone, this ); + task.on( 'canceled', function() { + this._removeTask( task ); + }, this ); + + // Update the aggregator. + this.update(); + + if ( initialTask ) { + this.notification.show(); + } + + return task; + }, + + /** + * Triggers an update on the aggregator, meaning that its UI will be refreshed. + * + * When all the tasks are done, the {@link #finished} event is fired. + */ + update: function() { + this._updateNotification(); + + if ( this.isFinished() ) { + this.fire( 'finished' ); + } + }, + + /** + * Returns a number from `0` to `1` representing the done weights to total weights ratio + * (showing how many of the tasks are done). + * + * Note: For an empty aggregator (without any tasks created) it will return `1`. + * + * @returns {Number} Returns the percentage of tasks done as a number ranging from `0` to `1`. + */ + getPercentage: function() { + // In case there are no weights at all we'll return 1. + if ( this.getTaskCount() === 0 ) { + return 1; + } + + return this._doneWeights / this._totalWeights; + }, + + /** + * @returns {Boolean} Returns `true` if all notification tasks are done + * (or there are no tasks at all). + */ + isFinished: function() { + return this.getDoneTaskCount() === this.getTaskCount(); + }, + + /** + * @returns {Number} Returns a total tasks count. + */ + getTaskCount: function() { + return this._tasks.length; + }, + + /** + * @returns {Number} Returns the number of tasks done. + */ + getDoneTaskCount: function() { + return this._doneTasks; + }, + + /** + * Updates the notification content. + * + * @private + */ + _updateNotification: function() { + this.notification.update( { + message: this._getNotificationMessage(), + progress: this.getPercentage() + } ); + }, + + /** + * Returns a message used in the notification. + * + * @private + * @returns {String} + */ + _getNotificationMessage: function() { + var tasksCount = this.getTaskCount(), + doneTasks = this.getDoneTaskCount(), + templateParams = { + current: doneTasks, + max: tasksCount, + percentage: Math.round( this.getPercentage() * 100 ) + }, + template; + + // If there's only one remaining task and we have a singular message, we should use it. + if ( tasksCount == 1 && this._singularMessage ) { + template = this._singularMessage; + } else { + template = this._message; + } + + return template.output( templateParams ); + }, + + /** + * Creates a notification object. + * + * @private + * @returns {CKEDITOR.plugins.notification} + */ + _createNotification: function() { + return new CKEDITOR.plugins.notification( this.editor, { + type: 'progress' + } ); + }, + + /** + * Creates a {@link CKEDITOR.plugins.notificationAggregator.task} instance based + * on `options`, and adds it to the task list. + * + * @private + * @param options Options object coming from the {@link #createTask} method. + * @returns {CKEDITOR.plugins.notificationAggregator.task} + */ + _addTask: function( options ) { + var task = new Task( options.weight ); + this._tasks.push( task ); + this._totalWeights += task._weight; + return task; + }, + + /** + * Removes a given task from the {@link #_tasks} array and updates the UI. + * + * @private + * @param {CKEDITOR.plugins.notificationAggregator.task} task Task to be removed. + */ + _removeTask: function( task ) { + var index = CKEDITOR.tools.indexOf( this._tasks, task ); + + if ( index !== -1 ) { + // If task was already updated with some weight, we need to remove + // this weight from our cache. + if ( task._doneWeight ) { + this._doneWeights -= task._doneWeight; + } + + this._totalWeights -= task._weight; + + this._tasks.splice( index, 1 ); + // And we also should inform the UI about this change. + this.update(); + } + }, + + /** + * A listener called on the {@link CKEDITOR.plugins.notificationAggregator.task#update} event. + * + * @private + * @param {CKEDITOR.eventInfo} evt Event object of the {@link CKEDITOR.plugins.notificationAggregator.task#update} event. + */ + _onTaskUpdate: function( evt ) { + this._doneWeights += evt.data; + this.update(); + }, + + /** + * A listener called on the {@link CKEDITOR.plugins.notificationAggregator.task#event-done} event. + * + * @private + * @param {CKEDITOR.eventInfo} evt Event object of the {@link CKEDITOR.plugins.notificationAggregator.task#event-done} event. + */ + _onTaskDone: function() { + this._doneTasks += 1; + this.update(); + } + }; + + CKEDITOR.event.implementOn( Aggregator.prototype ); + + /** + * # Overview + * + * This type represents a single task in the aggregator, and exposes methods to manipulate its state. + * + * ## Weights + * + * Task progess is based on its **weight**. + * + * As you create a task, you need to declare its weight. As you want the update to inform about the + * progress, you will need to {@link #update} the task, telling how much of this weight is done. + * + * For example, if you declare that your task has a weight that equals `50` and then call `update` with `10`, + * you will end up with telling that the task is done in 20%. + * + * ### Example Usage of Weights + * + * Let us say that you use tasks for file uploading. + * + * A single task is associated with a single file upload. You can use the file size in bytes as a weight, + * and then as the file upload progresses you just call the `update` method with the number of bytes actually + * downloaded. + * + * @since 4.5 + * @class CKEDITOR.plugins.notificationAggregator.task + * @mixins CKEDITOR.event + * @constructor Creates a task instance for notification aggregator. + * @param {Number} [weight=1] + */ + function Task( weight ) { + /** + * Total weight of the task. + * + * @private + * @property {Number} + */ + this._weight = weight || 1; + + /** + * Done weight of the task. + * + * @private + * @property {Number} + */ + this._doneWeight = 0; + + /** + * Indicates when the task is canceled. + * + * @private + * @property {Boolean} + */ + this._isCanceled = false; + } + + Task.prototype = { + /** + * Marks the task as done. + */ + done: function() { + this.update( this._weight ); + }, + + /** + * Updates the done weight of a task. + * + * @param {Number} weight Number indicating how much of the total task {@link #_weight} is done. + */ + update: function( weight ) { + // If task is already done or canceled there is no need to update it, and we don't expect + // progress to be reversed. + if ( this.isDone() || this.isCanceled() ) { + return; + } + + // Note that newWeight can't be higher than _doneWeight. + var newWeight = Math.min( this._weight, weight ), + weightChange = newWeight - this._doneWeight; + + this._doneWeight = newWeight; + + // Fire updated event even if task is done in order to correctly trigger updating the + // notification's message. If we wouldn't do this, then the last weight change would be ignored. + this.fire( 'updated', weightChange ); + + if ( this.isDone() ) { + this.fire( 'done' ); + } + }, + + /** + * Cancels the task (the task will be removed from the aggregator). + */ + cancel: function() { + // If task is already done or canceled. + if ( this.isDone() || this.isCanceled() ) { + return; + } + + // Mark task as canceled. + this._isCanceled = true; + + // We'll fire cancel event it's up to aggregator to listen for this event, + // and remove the task. + this.fire( 'canceled' ); + }, + + /** + * Checks if the task is done. + * + * @returns {Boolean} + */ + isDone: function() { + return this._weight === this._doneWeight; + }, + + /** + * Checks if the task is canceled. + * + * @returns {Boolean} + */ + isCanceled: function() { + return this._isCanceled; + } + }; + + CKEDITOR.event.implementOn( Task.prototype ); + + /** + * Fired when all tasks are done. When this event occurs, the notification may change its type to `success` or be hidden: + * + * aggregator.on( 'finished', function() { + * if ( aggregator.getTaskCount() == 0 ) { + * aggregator.notification.hide(); + * } else { + * aggregator.notification.update( { message: 'Done', type: 'success' } ); + * } + * } ); + * + * @event finished + * @member CKEDITOR.plugins.notificationAggregator + */ + + /** + * Fired upon each weight update of the task. + * + * var myTask = new Task( 100 ); + * myTask.update( 30 ); + * // Fires updated event with evt.data = 30. + * myTask.update( 40 ); + * // Fires updated event with evt.data = 10. + * myTask.update( 20 ); + * // Fires updated event with evt.data = -20. + * + * @event updated + * @param {Number} data The difference between the new weight and the previous one. + * @member CKEDITOR.plugins.notificationAggregator.task + */ + + /** + * Fired when the task is done. + * + * @event done + * @member CKEDITOR.plugins.notificationAggregator.task + */ + + /** + * Fired when the task is canceled. + * + * @event canceled + * @member CKEDITOR.plugins.notificationAggregator.task + */ + + // Expose Aggregator type. + CKEDITOR.plugins.notificationAggregator = Aggregator; + CKEDITOR.plugins.notificationAggregator.task = Task; +} )(); diff --git a/varbase.info.yml b/varbase.info.yml index c96e5d488aed4931164c18c54438d76d50886eca..d1e7aeab16d15036a11bc6d710d73b129fc33e59 100644 --- a/varbase.info.yml +++ b/varbase.info.yml @@ -106,6 +106,7 @@ dependencies: - better_exposed_filters - link_attributes - login_destination + - ckeditor_media_embed themes: # Contrib themes.