UNPKG

@instructure/canvas-rce

Version:

A component wrapping Canvas's usage of Tinymce

108 lines (107 loc) 3.38 kB
/* * Copyright (C) 2019 - present Instructure, Inc. * * This file is part of Canvas. * * Canvas is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation, version 3 of the License. * * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ import React from 'react'; import ReactDOM from 'react-dom'; import bridge from '../../../../../bridge'; import { getLinkContentFromEditor } from '../../../shared/ContentSelection'; import { getAnchorElement } from '../../../../contentInsertionUtils'; import LinkOptionsTray from '.'; export const CONTAINER_ID = 'instructure-link-options-tray-container'; export default class LinkOptionsTrayController { constructor() { this._editor = null; this._isOpen = false; this._shouldOpen = false; this._renderId = 0; } get $container() { let $container = document.getElementById(CONTAINER_ID); if ($container == null) { $container = document.createElement('div'); $container.id = CONTAINER_ID; document.body.appendChild($container); } return $container; } get isOpen() { return this._isOpen; } showTrayForEditor(editor) { this._editor = editor; this._shouldOpen = true; const selectedElm = editor.selection.getNode(); if (editor.selection.isCollapsed() && selectedElm.nodeName === 'A') { // expand the selection to include the whole <a> editor.selection.select(editor.selection.getNode()); } else { const anchorElm = getAnchorElement(editor, selectedElm); editor.selection.select(anchorElm); } if (bridge.focusedEditor) { // Dismiss any content trays that may already be open bridge.hideTrays(); } this._renderTray(); } hideTrayForEditor(editor) { if (this._editor === editor) { this._dismissTray(); } } _applyLinkOptions(linkOptions) { this._dismissTray(); bridge.insertLink({ ...linkOptions, userText: true }); } _dismissTray() { this._shouldOpen = false; this._renderTray(); this._editor = null; } _renderTray() { let content = {}; if (this._shouldOpen) { content = getLinkContentFromEditor(this._editor); /* * When the tray is being opened again, it should be rendered fresh * (clearing the internal state) so that the currently-selected content * can be used for initial options. */ this._renderId++; } const element = /*#__PURE__*/React.createElement(LinkOptionsTray, { content: content, key: this._renderId, onEntered: () => { this._isOpen = true; }, onExited: () => { bridge.focusActiveEditor(false); this._isOpen = false; }, onSave: linkOptions => { this._applyLinkOptions(linkOptions); }, onRequestClose: () => this._dismissTray(), open: this._shouldOpen }); ReactDOM.render(element, this.$container); } }