/* global tinymce, ss */ import i18n from 'i18n'; import TinyMCEActionRegistrar from 'lib/TinyMCEActionRegistrar'; import React from 'react'; import ReactDOM from 'react-dom'; import { ApolloProvider } from 'react-apollo'; import { Provider } from 'react-redux'; import jQuery from 'jquery'; import ShortcodeSerialiser from 'lib/ShortcodeSerialiser'; import { createInsertLinkModal } from 'containers/InsertLinkModal/InsertLinkModal'; import { provideInjector } from 'lib/Injector'; import { updatedCurrentField } from '../state/anchorSelector/AnchorSelectorActions'; const commandName = 'sslinkanchor'; const plugin = { init(editor) { // Add "Anchor on a page" to link menu for this editor TinyMCEActionRegistrar .addAction( 'sslink', { text: i18n._t('CMS.LINKLABEL_ANCHOR', 'Anchor on a page'), onclick: (activeEditor) => activeEditor.execCommand(commandName), priority: 60, }, editor.settings.editorIdentifier, ) .addCommandWithUrlTest(commandName, /^\[sitetree_link.+]#[^#\]]+$/); // Add a command that corresponds with the above menu item editor.addCommand(commandName, () => { const field = jQuery(`#${editor.id}`).entwine('ss'); // Get the anchors in the current field and save them as props for AnchorSelectorField const currentPageID = Number(jQuery('#Form_EditForm_ID').val() || 0); const validTargets = editor .$('[id],[name]', editor.getBody()) .toArray() .map((element) => element.id || element.name); ss.store.dispatch(updatedCurrentField(currentPageID, validTargets, editor.id)); // Open the anchor link form field.openLinkAnchorDialog(); }); }, }; const modalId = 'insert-link__dialog-wrapper--anchor'; const sectionConfigKey = 'SilverStripe\\CMS\\Controllers\\CMSPageEditController'; const formName = 'editorAnchorLink'; const InsertLinkInternalModal = provideInjector(createInsertLinkModal(sectionConfigKey, formName)); jQuery.entwine('ss', ($) => { $('textarea.htmleditor').entwine({ openLinkAnchorDialog() { let dialog = $(`#${modalId}`); if (!dialog.length) { dialog = $(`
`); $('body').append(dialog); } dialog.addClass('insert-link__dialog-wrapper'); dialog.setElement(this); dialog.open(); }, }); /** * Assumes that $('.insert-link__dialog-wrapper').entwine({}); is defined for shared functions */ $(`#${modalId}`).entwine({ renderModal(isOpen) { const store = ss.store; const client = ss.apolloClient; const handleHide = () => this.close(); const handleInsert = (...args) => this.handleInsert(...args); const attrs = this.getOriginalAttributes(); const requireLinkText = this.getRequireLinkText(); const currentPageID = Number($('#Form_EditForm_ID').val() || 0); // create/update the react component ReactDOM.render( , this[0] ); }, /** * @param {Object} data - Posted data * @return {Object} */ buildAttributes(data) { const shortcode = ShortcodeSerialiser.serialise({ name: 'sitetree_link', properties: { id: data.PageID }, }, true); // Add anchor const anchor = data.Anchor && data.Anchor.length ? `#${data.Anchor}` : ''; const href = `${shortcode}${anchor}`; return { href, target: data.TargetBlank ? '_blank' : '', title: data.Description, }; }, getOriginalAttributes() { const editor = this.getElement().getEditor(); const node = $(editor.getSelectedNode()); // Get href const hrefParts = (node.attr('href') || '').split('#'); if (!hrefParts[0]) { return {}; } // check if page is safe const shortcode = ShortcodeSerialiser.match('sitetree_link', false, hrefParts[0]); if (!shortcode) { return {}; } return { PageID: shortcode.properties.id ? parseInt(shortcode.properties.id, 10) : 0, Anchor: hrefParts[1] || '', Description: node.attr('title'), TargetBlank: !!node.attr('target'), }; }, }); }); // Adds the plugin class to the list of available TinyMCE plugins tinymce.PluginManager.add(commandName, (editor) => plugin.init(editor)); export default plugin;