diff --git a/app/assets/javascripts/discourse/app/initializers/post-decorations.js b/app/assets/javascripts/discourse/app/initializers/post-decorations.js index 598d283310..ba032490f7 100644 --- a/app/assets/javascripts/discourse/app/initializers/post-decorations.js +++ b/app/assets/javascripts/discourse/app/initializers/post-decorations.js @@ -10,6 +10,25 @@ import { withPluginApi } from "discourse/lib/plugin-api"; import { create } from "virtual-dom"; import showModal from "discourse/lib/show-modal"; +export function createTableWrapperButton(label, icon, classes, event) { + const openPopupBtn = document.createElement("button"); + const defaultClasses = [ + "open-popup-link", + "btn-default", + "btn", + "btn-icon-text", + ]; + openPopupBtn.classList.add(...defaultClasses); + openPopupBtn.classList.add(...classes); + const expandIcon = create(iconNode(icon)); + const openPopupText = document.createTextNode(I18n.t(label)); + openPopupBtn.append(expandIcon, openPopupText); + openPopupBtn.addEventListener("click", event, false); + return openPopupBtn; +} + +export const apiExtraTableWrapperButtons = []; + export default { name: "post-decorations", initialize(container) { @@ -135,25 +154,6 @@ export default { { id: "discourse-video-codecs" } ); - function _createButton() { - const openPopupBtn = document.createElement("button"); - openPopupBtn.classList.add( - "open-popup-link", - "btn-default", - "btn", - "btn-icon-text", - "btn-expand-table" - ); - const expandIcon = create( - iconNode("discourse-expand", { class: "expand-table-icon" }) - ); - const openPopupText = document.createTextNode( - I18n.t("fullscreen_table.expand_btn") - ); - openPopupBtn.append(expandIcon, openPopupText); - return openPopupBtn; - } - function isOverflown({ clientWidth, scrollWidth }) { return scrollWidth > clientWidth; } @@ -167,25 +167,36 @@ export default { function generatePopups(tables) { tables.forEach((table) => { - if (!isOverflown(table.parentNode)) { + const tableButtons = generateButtons(table); + if (tableButtons.length === 0) { return; } - if (site.isMobileDevice) { - return; - } - - const popupBtn = _createButton(); table.parentNode.classList.add("fullscreen-table-wrapper"); - // Create a button wrapper for case of multiple buttons (i.e. table builder extension) const buttonWrapper = document.createElement("div"); buttonWrapper.classList.add("fullscreen-table-wrapper-buttons"); - buttonWrapper.append(popupBtn); - popupBtn.addEventListener("click", generateModal, false); + buttonWrapper.append(...tableButtons); table.parentNode.insertBefore(buttonWrapper, table); }); } + function generateButtons(table) { + const buttons = []; + + if (isOverflown(table.parentNode) && !site.isMobileDevice) { + const expandButton = createTableWrapperButton( + "fullscreen_table.expand_btn", + "discourse-expand", + ["btn-expand-table"], + generateModal + ); + buttons.push(expandButton); + } + + buttons.push(...apiExtraTableWrapperButtons); + return buttons; + } + api.decorateCookedElement( (post) => { schedule("afterRender", () => { diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.js b/app/assets/javascripts/discourse/app/lib/plugin-api.js index 3fa4fcf197..eb19805e0a 100644 --- a/app/assets/javascripts/discourse/app/lib/plugin-api.js +++ b/app/assets/javascripts/discourse/app/lib/plugin-api.js @@ -105,12 +105,13 @@ import { registerNotificationTypeRenderer } from "discourse/lib/notification-typ import { registerUserMenuTab } from "discourse/lib/user-menu/tab"; import { registerModelTransformer } from "discourse/lib/model-transformers"; import { registerHashtagSearchParam } from "discourse/lib/hashtag-autocomplete"; +import { createTableWrapperButton } from "discourse/initializers/post-decorations"; // If you add any methods to the API ensure you bump up the version number // based on Semantic Versioning 2.0.0. Please update the changelog at // docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md whenever you change the version // using the format described at https://keepachangelog.com/en/1.0.0/. -const PLUGIN_API_VERSION = "1.4.0"; +const PLUGIN_API_VERSION = "1.5.0"; // This helper prevents us from applying the same `modifyClass` over and over in test mode. function canModify(klass, type, resolverName, changes) { @@ -2014,6 +2015,29 @@ class PluginApi { registerHashtagSearchParam(param, context, priority) { registerHashtagSearchParam(param, context, priority); } + + /** + * Add a new button to be overlaid ontop of a table appearing in a post. + * On wider tables the button will be appending along with the Expand table button. + * + * Example usage: + * + * api.addTableWrapperButton( + * themePrefix("discourse_table_builder.edit.btn_edit"), + * "pencil-alt", + * ["btn-edit-table"], + * generateModalEvent + * ); + * + * @param {string} label - An i18n key for the button label + * @param {icon} icon - An icon name from fontawesome + * @param {array} classes - An array of strings to be added as classes to the button + * @param {function} event - A function that returns an event to be dispatched when the button is clicked + * + */ + addTableWrapperButton(label, icon, classes, event) { + createTableWrapperButton(label, icon, classes, event); + } } // from http://stackoverflow.com/questions/6832596/how-to-compare-software-version-number-using-js-only-number diff --git a/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md b/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md index e4f5627568..07d261a227 100644 --- a/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md +++ b/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md @@ -7,6 +7,12 @@ in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.5.0] - 2022-11-01 + +### Added + +- Adds `addTableWrapperButton`, which allows users to register a button that appears on top of posts with markdown tables. The button will appear on hover over a table that appears in a post. If the post's table is a very wide table, the button will be appended next to the Expand Table button. + ## [1.4.0] - 2022-09-27 ### Added