stimulus-read-more
stimulus-read-more copied to clipboard
Read more should not be visible if it is not truncated
Hi, it is not a bug. It is a feature request.
It would be cool if toggle button would be not visible if content target already displays full test. What do you think?
Kind regards
Not that easy but could be a nice addition
Could you open a PR? I will try to code that later too
Would love this feature too. How can it be detected?
Hey there.. just stumbled upon this issue.
I have 2 different ideas, that may be suitable to solve this issue:
1) Working with ScrollHeight
I guess, you could use the offsetHeight and scrollHeight properties of the content element, like so (pseudo-code - not sure if this works)
// element where the truncated content is rendered to
var element = document.querySelector('div');
if (element.scrollHeight > element.offsetHeight || // y-truncation
element.scrollWidth > element.offsetWidth) { // x-truncation
// the content was truncated - show button
} else {
// no content-overflow - hide button
}
2) Checking for the content
You could also add the "original" (non-truncated) text to another variable (i.e. data-original-content) and pass it to the stimulus component. Then you could check:
if (truncatedContent == originalContent) {
// both contents are the same - hide button
} else {
// the truncatedContent is obviously "smaller" than the original content - show button
}
Guess, that could work as well..
I guess, solution 1 would be cleaner, because it would also work with additional HTML content (i.e,. tags / images within the content).
All the best Johannes
PS: i did not test any of these approaches ;)
Yes this works:
<div data-controller="read-more"
data-read-more-more-text-value="Read more"
data-read-more-less-text-value="Read less">
<div class="line-clamp-6" data-read-more-target="content">
text to truncate goes here
</div>
<button data-action="read-more#toggle" data-read-more-target="button"></button>
</div>
import {Controller} from "@hotwired/stimulus"
import {useResize} from "stimulus-use"
export default class extends Controller {
static targets = ["content", "button"]
static values = { moreText: String, lessText: String }
connect() {
this.buttonTarget.innerHTML = this.moreTextValue
useResize(this)
this.open = false
}
toggle() {
this.open = !this.open
this.buttonTarget.innerHTML = this.open ? this.lessTextValue : this.moreTextValue
this.contentTarget.classList.toggle("line-clamp-6", !this.open)
}
resize() {
if (!this.open) {
this.buttonTarget.classList.toggle("hidden", this.contentTarget.scrollHeight <= this.contentTarget.clientHeight)
}
}
}
Hi @sedubois! Thank you for providing your solution—it worked brilliantly!
For anyone implementing this, keep in mind that if you’re using Bootstrap, you should replace the “hidden” class (which corresponds to display: none in Tailwind CSS) with “d-none.” Alternatively, for a more general approach, consider modifying the resize method as follows:
resize() { if (!this.open && this.contentTarget.scrollHeight <= this.contentTarget.clientHeight) { this.buttonTarget.style.display = "none" } }
Also, remember that you’ll need to replace the class “line-clamp-6” with the specific class you are using in your project.