Skip to content

Commit

Permalink
Use alchemy-tinymce web component only on textareas
Browse files Browse the repository at this point in the history
it is increasing the readability and "feels" a bit better. Also removed a method on the richtext - model, which isn't used anymore.
  • Loading branch information
sascha-karnatz committed Sep 1, 2023
1 parent 675ab92 commit 93777f1
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 71 deletions.
71 changes: 28 additions & 43 deletions app/javascript/alchemy_admin/components/tinymce.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
class Tinymce extends HTMLElement {
import { createHtmlElement, wrap } from "alchemy_admin/utils/dom_helpers"
import Spinner from "alchemy_admin/spinner"

class Tinymce extends HTMLTextAreaElement {
constructor() {
super()

// add default css classes to support the current styles
this.className = "tinymce_container"
this.textarea.className = "has_tinymce"
// create a wrapper around the the textarea and place everything inside that container
this.container = createHtmlElement('<div class="tinymce_container" />')
wrap(this, this.container)
this.className = "has_tinymce"
}

/**
Expand All @@ -31,7 +35,7 @@ class Tinymce extends HTMLElement {
observerCallback,
options
)
this.tinymceIntersectionObserver.observe(this)
this.tinymceIntersectionObserver.observe(this.container)
}

/**
Expand All @@ -42,81 +46,62 @@ class Tinymce extends HTMLElement {
this.tinymceIntersectionObserver.disconnect()
}

tinymce.get(this.textareaId)?.remove(this.textareaId)
tinymce.get(this.id)?.remove(this.id)
}

initTinymceEditor() {
this.appendSpinner("small")

const element = document
.getElementById(this.textareaId)
.closest(".element-editor")
const spinner = new Spinner("small")
spinner.spin(this)

// initialize TinyMCE
tinymce.init(this.configuration).then((editors) => {
editors.forEach((editor) => {
this.removeSpinner()
spinner.stop()

editors.forEach((editor) => {
// mark the editor container as visible
// without these correction the editor remains hidden
// after a drag and drop action
editor.editorContainer.style.display = null
editor.show()

const elementEditor = document
.getElementById(this.id)
.closest(".element-editor")

// event listener to mark the editor as dirty
editor.on("dirty", () => Alchemy.setElementDirty(element))
editor.on("dirty", () => Alchemy.setElementDirty(elementEditor))
editor.on("click", (event) => {
event.target = element
event.target = elementEditor
Alchemy.ElementEditors.onClickElement(event)
})
})
})
}

appendSpinner() {
const spinner = new Alchemy.Spinner("small")
this.prepend(spinner.spin().el.get(0))
}

removeSpinner() {
const spinners = this.getElementsByClassName("spinner")
while (spinners.length > 0) {
spinners[0].parentNode.removeChild(spinners[0])
}
}

get textarea() {
return this.getElementsByTagName("textarea")[0]
}

get textareaId() {
return this.textarea.id
}

get configuration() {
const externalConfig = {}
const customConfig = {}

// read the attributes on the component and add them as custom configuration
this.getAttributeNames().forEach((attributeName) => {
if (attributeName !== "class") {
if (!["class", "id", "is", "name"].includes(attributeName)) {
const config = this.getAttribute(attributeName)
const key = attributeName.replaceAll("-", "_")

try {
externalConfig[key] = JSON.parse(config)
customConfig[key] = JSON.parse(config)
} catch (e) {
// also string values as parameter
externalConfig[key] = config
customConfig[key] = config
}
}
})

return {
...Alchemy.TinymceDefaults,
...externalConfig,
...customConfig,
locale: Alchemy.locale,
selector: `#${this.textareaId}`
selector: `#${this.id}`
}
}
}

customElements.define("alchemy-tinymce", Tinymce)
customElements.define("alchemy-tinymce", Tinymce, { extends: "textarea" })
7 changes: 1 addition & 6 deletions app/models/alchemy/ingredients/richtext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,8 @@ def has_tinymce?
true
end

# Returns true if there is a tinymce setting defined that contains settings.
def has_custom_tinymce_config?
custom_tinymce_config.is_a?(Hash)
end

def custom_tinymce_config
settings[:tinymce] || []
settings[:tinymce] || {}
end

private
Expand Down
10 changes: 3 additions & 7 deletions app/views/alchemy/ingredients/_richtext_editor.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@
data: richtext_editor.data_attributes do %>
<%= element_form.fields_for(:ingredients, richtext_editor.ingredient) do |f| %>
<%= ingredient_label(richtext_editor, :value) %>
<alchemy-tinymce
<% richtext_editor.custom_tinymce_config.each do |k, v| %>
<%= k.to_s.dasherize %>="<%= v.to_json %>"
<% end %>
>
<%= f.text_area :value %>
</alchemy-tinymce>

<%- custom_tinymce_config = richtext_editor.custom_tinymce_config.inject({}) { |obj, (k, v)| obj[k.to_s.dasherize] = v.to_json; obj} %>
<%= f.text_area :value, custom_tinymce_config.merge(is: "alchemy-tinymce", id: richtext_editor.form_field_id(:value)) %>
<% end %>
<% end %>
13 changes: 1 addition & 12 deletions spec/models/alchemy/ingredients/richtext_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,10 @@
expect(richtext_ingredient.sanitized_body).to eq("<h1>Hello!</h1><p class=\"green\">Welcome to Peters Petshop.</p>")
end

describe "#has_custom_tinymce_config?" do
subject { richtext_ingredient.has_custom_tinymce_config? }

it { is_expected.to be_falsy }

context "with custom configuration" do
let(:richtext_settings) { {tinymce: {plugin: "link"}} }
it { is_expected.to be_truthy }
end
end

describe "#custom_tinymce_config" do
subject { richtext_ingredient.custom_tinymce_config }

it { is_expected.to eq([]) }
it { is_expected.to eq({}) }

context "with custom configuration" do
let(:richtext_settings) { {tinymce: {plugin: "link"}} }
Expand Down
10 changes: 7 additions & 3 deletions spec/views/alchemy/ingredients/richtext_editor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
end

it "renders a text area for tinymce" do
expect(rendered).to have_selector("alchemy-tinymce textarea")
expect(rendered).to have_selector("textarea[is=alchemy-tinymce]")
end

context "without custom configuration" do
Expand All @@ -29,10 +29,14 @@
end

context "with custom configuration" do
let(:settings) { {tinymce: {plugin: "link"}} }
let(:settings) { {tinymce: {plugin: "link", foo_bar: "foo-bar"}} }

it "renders a custom configuration" do
expect(rendered).to have_selector("alchemy-tinymce[plugin]")
expect(rendered).to have_selector("textarea[is=alchemy-tinymce][plugin]")
end

it "dasherize the attribute keys" do
expect(rendered).to have_selector("textarea[is=alchemy-tinymce][foo-bar]")
end
end
end

0 comments on commit 93777f1

Please sign in to comment.