plugin.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /**
  2. * DO NOT EDIT THIS FILE.
  3. * See the following change record for more information,
  4. * https://www.drupal.org/node/2815083
  5. * @preserve
  6. **/
  7. (function (jQuery, Drupal, CKEDITOR) {
  8. function getFocusedWidget(editor) {
  9. var widget = editor.widgets.focused;
  10. if (widget && widget.name === 'drupalmedia') {
  11. return widget;
  12. }
  13. return null;
  14. }
  15. function linkCommandIntegrator(editor) {
  16. if (!editor.plugins.drupallink) {
  17. return;
  18. }
  19. CKEDITOR.plugins.drupallink.registerLinkableWidget('drupalmedia');
  20. editor.getCommand('drupalunlink').on('exec', function (evt) {
  21. var widget = getFocusedWidget(editor);
  22. if (!widget) {
  23. return;
  24. }
  25. widget.setData('link', null);
  26. this.refresh(editor, editor.elementPath());
  27. evt.cancel();
  28. });
  29. editor.getCommand('drupalunlink').on('refresh', function (evt) {
  30. var widget = getFocusedWidget(editor);
  31. if (!widget) {
  32. return;
  33. }
  34. this.setState(widget.data.link ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED);
  35. evt.cancel();
  36. });
  37. if (editor.contextMenu) {
  38. editor.contextMenu.addListener(function () {
  39. var widget = getFocusedWidget(editor);
  40. if (!widget) {
  41. return;
  42. }
  43. if (widget.data.link) {
  44. return {
  45. link: CKEDITOR.TRISTATE_OFF,
  46. unlink: CKEDITOR.TRISTATE_OFF
  47. };
  48. }
  49. return {};
  50. });
  51. }
  52. }
  53. CKEDITOR.plugins.add('drupalmedia', {
  54. requires: 'widget',
  55. beforeInit: function beforeInit(editor) {
  56. var dtd = CKEDITOR.dtd;
  57. dtd['drupal-media'] = { '#': 1 };
  58. Object.keys(dtd).forEach(function (tagName) {
  59. if (dtd[tagName].div) {
  60. dtd[tagName]['drupal-media'] = 1;
  61. }
  62. });
  63. dtd.a['drupal-media'] = 1;
  64. editor.widgets.add('drupalmedia', {
  65. allowedContent: {
  66. 'drupal-media': {
  67. attributes: {
  68. '!data-entity-type': true,
  69. '!data-entity-uuid': true,
  70. 'data-align': true,
  71. 'data-caption': true,
  72. alt: true,
  73. title: true
  74. },
  75. classes: {}
  76. }
  77. },
  78. requiredContent: new CKEDITOR.style({
  79. element: 'drupal-media',
  80. attributes: {
  81. 'data-entity-type': '',
  82. 'data-entity-uuid': ''
  83. }
  84. }),
  85. pathName: Drupal.t('Embedded media'),
  86. editables: {
  87. caption: {
  88. selector: 'figcaption',
  89. allowedContent: 'a[!href]; em strong cite code br',
  90. pathName: Drupal.t('Caption')
  91. }
  92. },
  93. getLabel: function getLabel() {
  94. if (this.data.label) {
  95. return this.data.label;
  96. }
  97. return Drupal.t('Embedded media');
  98. },
  99. upcast: function upcast(element, data) {
  100. var attributes = element.attributes;
  101. if (element.name !== 'drupal-media' || attributes['data-entity-type'] !== 'media' || attributes['data-entity-uuid'] === undefined) {
  102. return;
  103. }
  104. data.attributes = CKEDITOR.tools.copy(attributes);
  105. data.hasCaption = data.attributes.hasOwnProperty('data-caption');
  106. if (data.hasCaption && data.attributes['data-caption'] === '') {
  107. data.attributes['data-caption'] = ' ';
  108. }
  109. data.label = null;
  110. data.link = null;
  111. if (element.parent.name === 'a') {
  112. data.link = CKEDITOR.tools.copy(element.parent.attributes);
  113. Object.keys(element.parent.attributes).forEach(function (attrName) {
  114. if (attrName.indexOf('data-cke-') !== -1) {
  115. delete data.link[attrName];
  116. }
  117. });
  118. }
  119. var hostEntityLangcode = document.getElementById(editor.name).getAttribute('data-media-embed-host-entity-langcode');
  120. if (hostEntityLangcode) {
  121. data.hostEntityLangcode = hostEntityLangcode;
  122. }
  123. return element;
  124. },
  125. destroy: function destroy() {
  126. this._tearDownDynamicEditables();
  127. },
  128. data: function data(event) {
  129. var _this = this;
  130. if (this.oldData) {
  131. if (!this.data.hasCaption && this.oldData.hasCaption) {
  132. delete this.data.attributes['data-caption'];
  133. } else if (this.data.hasCaption && !this.data.attributes['data-caption']) {
  134. this.data.attributes['data-caption'] = ' ';
  135. }
  136. }
  137. if (this._previewNeedsServerSideUpdate()) {
  138. editor.fire('lockSnapshot');
  139. this._tearDownDynamicEditables();
  140. this._loadPreview(function (widget) {
  141. widget._setUpDynamicEditables();
  142. widget._setUpEditButton();
  143. editor.fire('unlockSnapshot');
  144. });
  145. }
  146. if (this.oldData) {
  147. Object.keys(this.oldData.attributes).forEach(function (attrName) {
  148. _this.element.removeAttribute(attrName);
  149. });
  150. }
  151. this.element.setAttributes(this.data.attributes);
  152. this.oldData = CKEDITOR.tools.clone(this.data);
  153. },
  154. downcast: function downcast() {
  155. var downcastElement = new CKEDITOR.htmlParser.element('drupal-media', this.data.attributes);
  156. if (this.data.link) {
  157. var link = new CKEDITOR.htmlParser.element('a', this.data.link);
  158. link.add(downcastElement);
  159. return link;
  160. }
  161. return downcastElement;
  162. },
  163. _setUpDynamicEditables: function _setUpDynamicEditables() {
  164. var _this2 = this;
  165. if (this.initEditable('caption', this.definition.editables.caption)) {
  166. var captionEditable = this.editables.caption;
  167. captionEditable.setAttribute('data-placeholder', Drupal.t('Enter caption here'));
  168. this.captionObserver = new MutationObserver(function () {
  169. var mediaAttributes = CKEDITOR.tools.clone(_this2.data.attributes);
  170. mediaAttributes['data-caption'] = captionEditable.getData();
  171. _this2.setData('attributes', mediaAttributes);
  172. });
  173. this.captionObserver.observe(captionEditable.$, {
  174. characterData: true,
  175. attributes: true,
  176. childList: true,
  177. subtree: true
  178. });
  179. if (captionEditable.$.childNodes.length === 1 && captionEditable.$.childNodes.item(0).nodeName === 'BR') {
  180. captionEditable.$.removeChild(captionEditable.$.childNodes.item(0));
  181. }
  182. }
  183. },
  184. _setUpEditButton: function _setUpEditButton() {
  185. if (this.element.findOne('.media-embed-error')) {
  186. return;
  187. }
  188. var isElementNode = function isElementNode(n) {
  189. return n.type === CKEDITOR.NODE_ELEMENT;
  190. };
  191. var embeddedMediaContainer = this.data.hasCaption ? this.element.findOne('figure') : this.element;
  192. var embeddedMedia = embeddedMediaContainer.getFirst(isElementNode);
  193. if (this.data.link) {
  194. embeddedMedia = embeddedMedia.getFirst(isElementNode);
  195. }
  196. embeddedMedia.setStyle('position', 'relative');
  197. var editButton = CKEDITOR.dom.element.createFromHtml(Drupal.theme('mediaEmbedEditButton'));
  198. embeddedMedia.getFirst().insertBeforeMe(editButton);
  199. var widget = this;
  200. this.element.findOne('.media-library-item__edit').on('click', function (event) {
  201. var saveCallback = function saveCallback(values) {
  202. event.cancel();
  203. editor.fire('saveSnapshot');
  204. if (values.hasOwnProperty('attributes')) {
  205. CKEDITOR.tools.extend(values.attributes, widget.data.attributes);
  206. Object.keys(values.attributes).forEach(function (prop) {
  207. if (values.attributes[prop] === false || prop === 'data-align' && values.attributes[prop] === 'none') {
  208. delete values.attributes[prop];
  209. }
  210. });
  211. }
  212. widget.setData({
  213. attributes: values.attributes,
  214. hasCaption: !!values.hasCaption
  215. });
  216. editor.fire('saveSnapshot');
  217. };
  218. Drupal.ckeditor.openDialog(editor, Drupal.url('editor/dialog/media/' + editor.config.drupal.format), widget.data, saveCallback, {});
  219. });
  220. this.element.findOne('.media-library-item__edit').on('keydown', function (event) {
  221. var returnKey = 13;
  222. var spaceBar = 32;
  223. if (typeof event.data !== 'undefined') {
  224. var keypress = event.data.getKey();
  225. if (keypress === returnKey || keypress === spaceBar) {
  226. event.sender.$.click();
  227. }
  228. event.data.$.stopPropagation();
  229. event.data.$.stopImmediatePropagation();
  230. }
  231. });
  232. },
  233. _tearDownDynamicEditables: function _tearDownDynamicEditables() {
  234. if (this.captionObserver) {
  235. this.captionObserver.disconnect();
  236. }
  237. },
  238. _previewNeedsServerSideUpdate: function _previewNeedsServerSideUpdate() {
  239. if (!this.ready) {
  240. return true;
  241. }
  242. return this._hashData(this.oldData) !== this._hashData(this.data);
  243. },
  244. _hashData: function _hashData(data) {
  245. var dataToHash = CKEDITOR.tools.clone(data);
  246. delete dataToHash.attributes['data-caption'];
  247. delete dataToHash.label;
  248. if (dataToHash.link) {
  249. delete dataToHash.link.href;
  250. }
  251. return JSON.stringify(dataToHash);
  252. },
  253. _loadPreview: function _loadPreview(callback) {
  254. var _this3 = this;
  255. jQuery.get({
  256. url: Drupal.url('media/' + editor.config.drupal.format + '/preview'),
  257. data: {
  258. text: this.downcast().getOuterHtml(),
  259. uuid: this.data.attributes['data-entity-uuid']
  260. },
  261. dataType: 'html',
  262. success: function success(previewHtml, textStatus, jqXhr) {
  263. _this3.element.setHtml(previewHtml);
  264. _this3.setData('label', jqXhr.getResponseHeader('Drupal-Media-Label'));
  265. callback(_this3);
  266. },
  267. error: function error() {
  268. _this3.element.setHtml(Drupal.theme('mediaEmbedPreviewError'));
  269. }
  270. });
  271. }
  272. });
  273. },
  274. afterInit: function afterInit(editor) {
  275. linkCommandIntegrator(editor);
  276. }
  277. });
  278. })(jQuery, Drupal, CKEDITOR);