Open silva96 opened 2 years ago
Hey @silva96, thanks for sharing, amazing instructions! I implemented it and it works great! Maybe you might add - as reminder for newbies like me- to update the Stimulus manifest with ./bin/rails stimulus:manifest:update
after adding the Trix Controller.
Hey @silva96, thanks for sharing, amazing instructions! I implement it and it works great! Maybe you might add - as reminder for newbies like me- to update the Stimulus manifest with
./bin/rails stimulus:manifest:update
after adding the Trix Controller.
Sure, I'll add it!
UPDATE: for trix 2.0+ the controller is slightly different (and better, less hacky)
import { Controller } from '@hotwired/stimulus'
import Trix from 'trix'
const { lang } = Trix.config
// Connects to data-controller="trix"
export default class extends Controller {
static targets = ['editor', 'foregroundColorPicker', 'backgroundColorPicker']
connect () {
document.addEventListener('trix-before-initialize', () => {
this.initTrix()
})
}
initTrix () {
Trix.config.blockAttributes.heading1.tagName = 'h3'
Trix.config.toolbar.getDefaultHTML = this.getDefaultHTML.bind(this)
this.addForegroundButtonConfig()
this.addBackgroundButtonConfig()
this.addTextAlignCenterButtonConfig()
}
openForegroundColorPicker () {
this.foregroundColorPickerTarget.click()
}
openBackgroundColorPicker () {
this.backgroundColorPickerTarget.click()
}
foregroundColorChanged () {
this.editorTarget.editor.activateAttribute('foregroundColor', this.foregroundColorPickerTarget.value)
}
backgroundColorChanged () {
this.editorTarget.editor.activateAttribute('backgroundColor', this.backgroundColorPickerTarget.value)
}
addForegroundButtonConfig () {
Trix.config.textAttributes.foregroundColor = {
styleProperty: 'color',
inheritable: true
}
}
addBackgroundButtonConfig () {
Trix.config.textAttributes.backgroundColor = {
styleProperty: 'backgroundColor',
inheritable: true
}
}
addTextAlignCenterButtonConfig () {
Trix.config.blockAttributes.textAlignCenter = {
tagName: 'centered-div'
}
}
getDefaultHTML () {
return `<div class="trix-button-row">
<span class="trix-button-group trix-button-group--text-tools" data-trix-button-group="text-tools">
<button type="button" class="trix-button trix-button--icon trix-button--icon-bold" data-trix-attribute="bold" data-trix-key="b" title="${lang.bold}" tabindex="-1">${lang.bold}</button>
<button type="button" class="trix-button trix-button--icon trix-button--icon-italic" data-trix-attribute="italic" data-trix-key="i" title="${lang.italic}" tabindex="-1">${lang.italic}</button>
<button type="button" class="trix-button trix-button--icon trix-button--icon-strike" data-trix-attribute="strike" title="${lang.strike}" tabindex="-1">${lang.strike}</button>
<button type="button" class="trix-button trix-button--icon trix-button--icon-link" data-trix-attribute="href" data-trix-action="link" data-trix-key="k" title="${lang.link}" tabindex="-1">${lang.link}</button>
${this.foregroundColorButtons}
${this.backgroundColorButtons}
</span>
<span class="trix-button-group trix-button-group--block-tools" data-trix-button-group="block-tools">
<button type="button" class="trix-button trix-button--icon trix-button--icon-heading-1" data-trix-attribute="heading1" title="${lang.heading1}" tabindex="-1">${lang.heading1}</button>
<button type="button" class="trix-button trix-button--icon trix-button--icon-quote" data-trix-attribute="quote" title="${lang.quote}" tabindex="-1">${lang.quote}</button>
<button type="button" class="trix-button trix-button--icon trix-button--icon-code" data-trix-attribute="code" title="${lang.code}" tabindex="-1">${lang.code}</button>
<button type="button" class="trix-button trix-button--icon trix-button--icon-bullet-list" data-trix-attribute="bullet" title="${lang.bullets}" tabindex="-1">${lang.bullets}</button>
<button type="button" class="trix-button trix-button--icon trix-button--icon-number-list" data-trix-attribute="number" title="${lang.numbers}" tabindex="-1">${lang.numbers}</button>
<button type="button" class="trix-button trix-button--icon trix-button--icon-decrease-nesting-level" data-trix-action="decreaseNestingLevel" title="${lang.outdent}" tabindex="-1">${lang.outdent}</button>
<button type="button" class="trix-button trix-button--icon trix-button--icon-increase-nesting-level" data-trix-action="increaseNestingLevel" title="${lang.indent}" tabindex="-1">${lang.indent}</button>
${this.textAlignButtons}
</span>
<span class="trix-button-group trix-button-group--file-tools" data-trix-button-group="file-tools">
<button type="button" class="trix-button trix-button--icon trix-button--icon-attach" data-trix-action="attachFiles" title="${lang.attachFiles}" tabindex="-1">${lang.attachFiles}</button>
</span>
<span class="trix-button-group-spacer"></span>
<span class="trix-button-group trix-button-group--history-tools" data-trix-button-group="history-tools">
<button type="button" class="trix-button trix-button--icon trix-button--icon-undo" data-trix-action="undo" data-trix-key="z" title="${lang.undo}" tabindex="-1">${lang.undo}</button>
<button type="button" class="trix-button trix-button--icon trix-button--icon-redo" data-trix-action="redo" data-trix-key="shift+z" title="${lang.redo}" tabindex="-1">${lang.redo}</button>
</span>
</div>
<div class="trix-dialogs" data-trix-dialogs>
<div class="trix-dialog trix-dialog--link" data-trix-dialog="href" data-trix-dialog-attribute="href">
<div class="trix-dialog__link-fields">
<input type="url" name="href" class="trix-input trix-input--dialog" placeholder="${lang.urlPlaceholder}" aria-label="${lang.url}" required data-trix-input>
<div class="trix-button-group">
<input type="button" class="trix-button trix-button--dialog" value="${lang.link}" data-trix-method="setAttribute">
<input type="button" class="trix-button trix-button--dialog" value="${lang.unlink}" data-trix-method="removeAttribute">
</div>
</div>
</div>
</div>`
}
get foregroundColorButtons () {
return `<input type="color" style="width:0;height:0;padding:0;margin-top:20px;visibility:hidden"
data-trix-target="foregroundColorPicker" data-action="trix#foregroundColorChanged">
<button type="button" class="trix-button" data-action="click->trix#openForegroundColorPicker" title="Text color">
<span class="icon"><i class="fas fa-palette fa-lg"></i></span>
</button>`
}
get backgroundColorButtons () {
return `<input type="color" style="width:0;height:0;padding:0;margin-top:20px;visibility:hidden"
data-trix-target="backgroundColorPicker" data-action="trix#backgroundColorChanged">
<button type="button" class="trix-button" data-action="click->trix#openBackgroundColorPicker" title="Text background color">
<span class="icon"><i class="fas fa-fill-drip fa-lg"></i></span>
</button>`
}
get textAlignButtons () {
return `<button type="button" class="trix-button" data-trix-attribute="textAlignCenter">
<span class="icon"><i class="fas fa-align-center fa-lg"></i></span>
</button>`
}
}
Thank you especially for mentioning the call to reset()
. That might have me some hours of searching.
Thank you especially for mentioning the call to
reset()
. That might have me some hours of searching.
In trix 2.0 it's not needed! (since we init trix on the event trix-before-initialize, so it always initialize properly)
In trix 2.0 it's not needed! (since we init trix on the event trix-before-initialize, so it always initialize properly)
Thanks, you are right. With the upgrade to 2.0.1 we do not need the call anymore. :+1:
it's greate, thank you very much!
In trix 1.x,
I add text align left and right button by this idea, and find that tags will nested if you click left\center\right button in same words.
finally i find a method: put these attributes(nestable: false\exclusive: true) toTrix.config.blockAttributes.textAlignLeft
will reslove this issue.
Hope this helps someone who has the same problem。
addTextAlignLeftButtonInToolbar () {
console.log(Trix.config.blockAttributes)
console.log(this.element)
Trix.config.blockAttributes.textAlignLeft = {
tagName: 'align-left',
nestable: false,
exclusive: true
}
this.element
.querySelector('.trix-button-group.trix-button-group--block-tools')
.insertAdjacentHTML('beforeend', this.textAlignLeftButtons)
}
Is there a video explaining how to install the color editor on it?
od: put these attributes(nestable: false\exclusive: true) to
Trix.config.blockAttributes.textAlignLeft
will reslove this issue.
There's no video, there's a step by step tutorial that is very well explained. Do you have any doubt? feel free to ask!
FWIW, we have color pickers both in Basecamp and Hey. You can view the code with inspect source.
For example:
https://app.hey.com/assets/initializers/rich_text-61ba21bdd43c434b34620c74dc222edd0a26ab07.js https://app.hey.com/assets/controllers/color_picker_controller-3a32b84428f8a3b78c1b0f06f2e2f6b4ade1790a.js
FWIW, we have color pickers both in Basecamp and Hey. You can view the code with inspect source.
For example:
https://app.hey.com/assets/initializers/rich_text-61ba21bdd43c434b34620c74dc222edd0a26ab07.js https://app.hey.com/assets/controllers/color_picker_controller-3a32b84428f8a3b78c1b0f06f2e2f6b4ade1790a.js
That's nice! out of curiosity, how do they look? can you show a picture or gif?
@silva96 Here is an example from composing a new email in Hey with a color picker:
https://github.com/basecamp/trix/assets/215958/ed2d9c11-1cbb-4d7b-a2c8-be4141d7bb0c
This all looks great, but it looks like it is tied in with Rails. Is there an example how to add a color picker with just straight javascript. For example, adding it to this page?
<!DOCTYPE html>
<html>
<head>
<title>Trix Test</title>
<link rel="stylesheet" type="text/css" href="https://unpkg.com/trix/dist/trix.css" />
<script type="text/javascript" src="https://unpkg.com/trix/dist/trix.umd.js"></script>
</head>
<body>
<trix-editor class="trix-content"></trix-editor>
</body>
</html>
@JimCook57 it's tied to Stimulus more than rails actually. But you can extract the relevant code and do vanilla JS instead of stimulus.
Thank you, I like this instruction very much and hope this color picker feature is included as default (OOTB). However, I encounter an issue.
In my tests, the first stimulus controller code worked perfectly on Rails 7.0.8 with Trix 1.3.1, but the second stimulus code did not initialize the Trix editor on Rails 7.1.2 with Trix 2.0.8. It does not initially (at the first page loading) show the color tool buttons and color span tags (missing) on the rich_text_area. If I refresh the page, they are shown and work properly.
For the test on Rails 7.1.2, I just created a simple Rails scaffold and modified the application.rb since the sanitizer was changed on Rails 7.1, otherwise it causes a system error.
Rails.application.config.after_initialize do
# ActionText::ContentHelper.allowed_attributes.add 'style'
# ActionText::ContentHelper.allowed_attributes.add 'controls'
# ActionText::ContentHelper.allowed_attributes.add 'poster'
#
# ActionText::ContentHelper.allowed_tags.add 'video'
# ActionText::ContentHelper.allowed_tags.add 'source'
# ActionText::ContentHelper.allowed_tags.add 'centered-div'
ActionText::ContentHelper.allowed_attributes = Loofah::HTML5::SafeList::ACCEPTABLE_ATTRIBUTES.add('controls')
ActionText::ContentHelper.allowed_tags = Loofah::HTML5::SafeList::ACCEPTABLE_ELEMENTS.merge(['source', 'centered-div'])
end
Initially (at the first page loading), the trix-before-initialize event does not occur, so the color tool buttons are not shown. If I refresh the editor page, the event occurs and the color tool buttons are shown and work properly.
@chiaki8 can you create a reproduction repo to test locally?
@silva96 thanks, here is the reproduction repo.
I found out that it works fine (shows the color tool buttons at the first page loading) by disabling turbo for the links to Trix Editor, sorry.
Thanks you @silva96 - it's working perfectly fine for me 👍
so what about javascript ? or projects not based on ROR?
EDIT: if you are using Trix 2.0+ read the tutorial but instead of using this stimulus_controller, please use the stimulus_controller here: https://github.com/basecamp/trix/issues/985#issuecomment-1307422240
After a good time of reading issues and thinking I finally could create a fully functional color picker for Trix
This also works when reloading the editor page because I call reset after the config.
I also added text-align center icon to center blocks
For this to work, just wrap your
rich_text_area
in a div withdata-controller="trix"
and add adata: { trix_target: 'editor' }
to the rich_text_areaAlso add a stimulus controller called trix-controller.js and then update the stimulus manifest
update the Stimulus manifest with ./bin/rails stimulus:manifest:update
You may want to replace the icon
<span class="icon"><i class="fas fa-palette"></i></span>
(I use fontawesome, feel free to use whatever you like, maybe a 🎨 icon would work)this solves https://github.com/basecamp/trix/issues/498 https://github.com/basecamp/trix/issues/606 https://github.com/basecamp/trix/issues/655 and many others.
For the centered text you will need to:
Add this css
Also add
centered-div
as allowed tags (I have this in my application.rb)