shinychang / react-text-truncate Goto Github PK
View Code? Open in Web Editor NEWTruncate multi-lines text for all browsers base on react.js
Home Page: http://ShinyChang.github.io/React-Text-Truncate/
License: MIT License
Truncate multi-lines text for all browsers base on react.js
Home Page: http://ShinyChang.github.io/React-Text-Truncate/
License: MIT License
warning.js:36 Warning: Unknown prop `element` on <div> tag. Remove this prop from the element. For details, see https://fb.me/react-unknown-prop
Your demo shows how to truncate text, but how do you untruncate it?
When the available width is less than the width of truncateText
, the do-while loop spins infinitely because the width check will never succeed. In this case, I think that the only reasonably thing to do is to give up. The patch below works in my testing.
+++ src/TextTruncate.js 2016-11-10 10:58:06.400619073 +1000
@@ -120,7 +120,7 @@
}
}
width = this.measureWidth(truncatedText + ext);
- } while (width >= scopeWidth);
+ } while (width >= scopeWidth && truncatedText.length > 0);
startPos += currentPos;
break;
}
For more flexible.
Sorry, I don't mean to keep spamming you with issues but the more I use this component obviously the more I get to imagining. It's not uncommon to have the link to the "more" or "read more" or whatever be on the same line as the truncated text. Is it possible to add this functionality? So instead of:
This is truncated text...
more
you'd have:
This is truncated text... more
This would obviously require calculating the width of the textTruncateChild
and subtracting it from the last truncated line and truncating at that point.
Thoughts?
Using the package with React 15.5 triggers this warning:
Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
More info is here: https://facebook.github.io/react/blog/2017/04/07/react-v15.5.0.html
Note that with React 16.0 it will be removed.
<TextTruncate line={2} truncateText='...' text={'V3'}></TextTruncate>
simply displays '...'.
If I add another character to make it 'V33', for instance, it displays text. The div container this is in is 320px, so plenty of room there.
Hello, I am getting an error when trying to use this.
ERROR in ./~/react-text-truncate/lib/index.js
Module build failed: ReferenceError: Unknown plugin "add-module-exports" specified in "/Users/rr239696/Projects/Personal/parkflix/node_modules/react-text-truncate/.babelrc" at 0, attempted to resolve relative to "/Users/
rr239696/Projects/Personal/parkflix/node_modules/react-text-truncate"
at /Users/rr239696/Projects/Personal/parkflix/node_modules/babel-core/lib/transformation/file/options/option-manager.js:176:17
at Array.map (native)
at Function.normalisePlugins (/Users/rr239696/Projects/Personal/parkflix/node_modules/babel-core/lib/transformation/file/options/option-manager.js:154:20)
at OptionManager.mergeOptions (/Users/rr239696/Projects/Personal/parkflix/node_modules/babel-core/lib/transformation/file/options/option-manager.js:229:36)
at OptionManager.init (/Users/rr239696/Projects/Personal/parkflix/node_modules/babel-core/lib/transformation/file/options/option-manager.js:374:12)
at File.initOptions (/Users/rr239696/Projects/Personal/parkflix/node_modules/babel-core/lib/transformation/file/index.js:216:65)
at new File (/Users/rr239696/Projects/Personal/parkflix/node_modules/babel-core/lib/transformation/file/index.js:139:24)
at Pipeline.transform (/Users/rr239696/Projects/Personal/parkflix/node_modules/babel-core/lib/transformation/pipeline.js:46:16)
at transpile (/Users/rr239696/Projects/Personal/parkflix/node_modules/babel-loader/lib/index.js:38:20)
at Object.module.exports (/Users/rr239696/Projects/Personal/parkflix/node_modules/babel-loader/lib/index.js:133:12)
@ ./app/components/ParkCard.jsx 8:19-49
example:
<div style="200px">
<TextTruncate line={3} text="LoremIpsumissimplydummytextoftheprintingand typesettingindustry.fuhefjfvfjfkvjkvhjkjkvhjjhdfvjfhvjvj hfvjvfhjjhfjsfhjf ghj" />
</div>
Currently i am using version 0.8.3
but i tested all version till 0.11.0
still issue is there in all
Any idea how should we fix this @ShinyChang
I have a Highlighter component that highlights substrings based off of a search
prop. It would be great if I could pass my Highlighter component to your text
prop so that the string could be both truncated and highlighted.
Example:
const desc = <Highlighter search={this.props.search}>{this.props.description}</Highlighter>;
return (
<Truncate
line={2}
truncateText="…"
text={desc}
/>
);
Is it possible to add a feature so that the hidden text can be shown on mouse hover?
是不是應該要加上符合 OSI 公布的 open source license.
Maybe in future version, you can add an optional onClick property? Its not really an issue because I can wrap it in a span tag and have the onClick there. But it would be nice if its built in to the component itself. Thanks.
If a long text has no space in it, the TextTruncate-comonent hang when trying to display all text.
Since componentWillMount
will run both on the server and the client, document
may not be available when it is running, resulting in a runtime error.
Suggest moving the canvas creation to componentDidMount
which only runs on the client
Text is not truncated right when the style property changes
I'm not sure, but I think the problem occurs because the canvas is created only on componentDidMount, so the width is not measured right if the style property or the css rules changes. Calling to the update method doesn't fix the problem. Removing the style property from the div in the web inspector shows that apparently the component is ignoring the style prop.
This is the rendered text (line prop set to 1):
This is after removing the style prop:
I think a solution would be to recreate the canvas in every render. Of course there are performance concerns about this solution.
Hi,
I'm using TextTruncate in tabbed panels (bootstrap), which results in the components on initially hidden tabs to not have rendered when the tab is made visible. But it redraws when I resize the window.
Can you recommend a way to trigger redraw for this component when its container is made visible?
Thanks
Hola! @ShinyChang has created a ZenHub account for the ShinyChang organization. ZenHub is the leading team collaboration and project management solution built for GitHub.
To get set up with ZenHub, all you have to do is download the browser extension and log in with your GitHub account. Once you do, you’ll get access to ZenHub’s complete feature-set immediately.
ZenHub adds a series of enhancements directly inside the GitHub UI:
Still curious? See more ZenHub features or read user reviews. This issue was written by your friendly ZenHub bot, posted by request from @ShinyChang.
It breaks use without textTruncateChild :(
Hello!
Thank you for your package, it's really good.
Can you please upload latest version to npm? Ability of passing to this component textElement is very useful!
I am having the same issue as described in:
Issue #53
I noticed that your last comment said that it was fixed and to use 0.13.0. but I have tested with it and It seems like long words are still being cut-off in narrow containers.
Is there any plan to fix this @ShinyChang?
Or perhaps I am not using it correctly...
Unit test fails on my component which uses TextTruncate library. I try to mount my component using enzyme and got the following error.
`TypeError: Cannot set property 'font' of null
at TextTruncate.componentDidMount (node_modules/react-text-truncate/lib/index.js:135:26)
at commitLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:15255:22)
at commitAllLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:16523:7)
at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:149:14)
at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27)
at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:126:9)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:36:27)
at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:61:35)
at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:199:16)
at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:256:31)
at commitRoot (node_modules/react-dom/cjs/react-dom.development.js:16677:7)
at completeRoot (node_modules/react-dom/cjs/react-dom.development.js:18069:3)
at performWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:17997:9)
at performWork (node_modules/react-dom/cjs/react-dom.development.js:17901:7)
at performSyncWork (node_modules/react-dom/cjs/react-dom.development.js:17873:3)
at requestWork (node_modules/react-dom/cjs/react-dom.development.js:17761:5)
at scheduleWork (node_modules/react-dom/cjs/react-dom.development.js:17566:5)
at scheduleRootUpdate (node_modules/react-dom/cjs/react-dom.development.js:18240:3)
at updateContainerAtExpirationTime (node_modules/react-dom/cjs/react-dom.development.js:18267:10)
at updateContainer (node_modules/react-dom/cjs/react-dom.development.js:18324:10)
at ReactRoot.Object.<anonymous>.ReactRoot.render (node_modules/react-dom/cjs/react-dom.development.js:18586:3)
at node_modules/react-dom/cjs/react-dom.development.js:18726:14
at unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:18124:10)
at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:18722:5)
at Object.render (node_modules/react-dom/cjs/react-dom.development.js:18783:12)
at Object.render (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:348:114)
at new ReactWrapper (node_modules/enzyme/build/ReactWrapper.js:130:16)
at mount (node_modules/enzyme/build/mount.js:21:10)
at Object.it (src/app/v2/shared/sortableList/__tests__/test.js:66:43)
at new Promise (<anonymous>)
at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:189:7)`
also the snapshot test fails on my component when rendering using 'react-test-renderer'
const tree = renderer.create(<MyComponent { ...props } />).toJSON(); expect(tree).toMatchSnapshot();
this gives a different error message.
`TypeError: Cannot read property 'style' of null
at Window.getComputedStyle (node_modules/jsdom/lib/jsdom/browser/Window.js:371:20)
at TextTruncate.componentDidMount (node_modules/react-text-truncate/lib/index.js:130:28)
at commitLifeCycles (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8272:22)
at commitAllLifeCycles (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9567:7)
at HTMLUnknownElement.callCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2331:14)
at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27)
at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:126:9)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:36:27)
at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:61:35)`
Is there any way to support or not on roadmap?
When lib/index.js is loaded in a browser, it's unable to find global.react. Shouldn't it be global.React? Looking at Reacts documentation and their jsfiddle example, I see that it's available under window.React
not window.react
Thoughts?
Thanks!
I figured I'd open a new issue so as not to plug up the other one since these don't seem to be related. Anyway, my code for these three items is the same, all set to truncate after 2 lines. Here is a screenshot of the result: https://www.dropbox.com/s/gmiacy5rv1qjqdq/Screenshot%202016-06-14%2021.49.11.png?dl=0
The code:
<div className="MessagesSnapshot-item">
<Image
className="MessagesSnapshot-item-image"
src="http://placehold.it/100x100"
alt="Sender name would go here"
round
/>
<div className="MessagesSnapshot-item-info">
<div className="MessagesSnapshot-item-title">
<h3 className="heading-xs">Jen R. via SMS</h3>
<span>3 min ago</span>
</div>
<TextTruncate
className="MessagesSnapshot-item-message"
line={2}
text="I see by your Health Assessment that you're a very good listener and you like fruit."
/>
</div>
</div>
<div className="MessagesSnapshot-item">
<Image
className="MessagesSnapshot-item-image"
src="http://placehold.it/100x100"
alt="Sender name would go here"
round
/>
<div className="MessagesSnapshot-item-info">
<div className="MessagesSnapshot-item-title">
<h3 className="heading-xs">Jen R. via SMS</h3>
<span>5 min ago</span>
</div>
<TextTruncate
className="MessagesSnapshot-item-message"
line={2}
text="Hi! I'm your expert coach, Jen. I'm excited to meet you and get started on your journey!"
/>
</div>
</div>
<div className="MessagesSnapshot-item">
<Image
className="MessagesSnapshot-item-image"
src="http://placehold.it/100x100"
alt="Sender name would go here"
round
/>
<div className="MessagesSnapshot-item-info">
<div className="MessagesSnapshot-item-title">
<h3 className="heading-xs">Jade P. via Mail</h3>
<span>1 hr ago</span>
</div>
<TextTruncate
className="MessagesSnapshot-item-message"
line={2}
text="Welcome to Retrofit, Madeline! I wanted to reach out to you and talk about stuff."
/>
</div>
</div>
This is all placeholder content obviously but you get the idea. It's not truncating correctly as you can see the second and third items are 3 sentences long, only the first is 2.
Just in case you want to see the corresponding Sass as well:
.MessagesSnapshot {
text-align: center;
padding-bottom: 30px;
.Badge {
position: relative;
top: -4px;
}
}
.MessagesSnapshot-item {
display: table;
width: 100%;
margin-bottom: 30px;
text-align: left;
.LazyLoad {
display: table-cell;
width: 100px;
height: 100px;
vertical-align: top;
}
}
.MessagesSnapshot-item-info {
display: table-cell;
width: calc(100% - 100px);
padding-left: 10px;
vertical-align: top;
}
.MessagesSnapshot-item-title {
@extend %clearfix;
width: 100%;
h3 {
float: left;
margin-bottom: 0;
}
span {
@include font-size(1.3);
float: right;
}
}
.MessagesSnapshot-item-message {
@include font-size(1.2);
}
UPDATE: It's odd, sometimes when I refresh it works, sometimes it doesn't... I'm not sure what is causing this to not work, I'm just doing a page refresh. On original load (meaning not a refresh) its also intermittent. Maybe since you know the internals better than I would this will help trigger something in your mind that will get the wheels spinning on what the problem could be.
Let me know if there is anything else you'd like me to add/test to get this corrected.
Hi, first of all, great work.
This is more like a feature request. I think that would be cool if you can set the inner element to use, like h1...h5, p, span or div, for example. This is useful when you already have global css styles for those elements.
ie:
<TextTruncate element="h1" text="hello world" line={1}/>
Is it possible?
Wondering if there is any plans to add unit tests to this component in a future release? I played around with writing a few with jest/enzyme but hit a wall because jsdom does not seem to like the "canvas" element.
Hi,
Do you have any plans for upgrading to react 16?
Seeing issues when using React 16 in our app
npm WARN [email protected] requires a peer of react-dom@^0.14.7 || ^15.0.0 but none was insta
lled.
If the parent container display='none', the scope.getBoundingClientRect().width will be 0.
This results in an infinite loop that will hang the page.
if (scopeWidth >= textWidth) {
return this.props.text;
} else {
let currentPos = 1;
let maxTextLength = this.props.text.length;
let text = '';
let splitPos = 0;
let startPos = 0;
let line = this.props.line;
let width = 0;
let lastIsEng = false;
while(line--) {
let ext = line ? '' : this.props.truncateText;
while (currentPos <= maxTextLength) {
text = this.props.text.substr(startPos, currentPos);
width = this.measureWidth(text + ext);
if (width < scopeWidth) {
splitPos = this.props.text.indexOf(' ', currentPos + 1);
if (splitPos === -1) {
currentPos += 1;
lastIsEng = false;
} else {
lastIsEng = true;
currentPos = splitPos;
}
} else {
return this.props.text;
do {
currentPos--;
text = this.props.text.substr(startPos, currentPos);
if (text[text.length - 1] === ' ') {
text = this.props.text.substr(startPos, currentPos - 1);
}
if (lastIsEng) {
currentPos = text.lastIndexOf(' ');
text = this.props.text.substr(startPos, currentPos);
}
width = this.measureWidth(text + ext);
} while (width >= scopeWidth);
startPos += currentPos;
break;
}
}
When scopeWidth is 0, the first condition fails and so we enter the else block and begin to loop thru the lines. Inside the second loop block, we have the condition: if (width < scopeWidth)
. Since scopeWidth is 0, this will always be false and so we will enter the else block. Here we enter the do-while loop, which we will never exit if the 'ext' is not an empty string, because width = this.measureWidth(text + ext);
will never be 0 and we will never satisfy the exit condition: } while (width >= scopeWidth);
I think a simple fix would be to simply check for a scopeWidth of 0 and return an empty string in that case. This would be the same behavior as when the scope ref is not found. I'm happy to submit a pull request with the fix if you'd like.
Could you please add option which is responsable for where dots appear(at the beginning of text, in the middle of text, at the end of text). Also it would be great to have ability to specify how many characters should go after dots if we chose middle position of dots.
When I want to truncate text with flex: 1
, it doesn't work.
// css
.wrapper {
display: flex;
}
.truncate {
flex: 1;
}
// html
<div className="wrapper">
<div className="truncate">
<TextTruncate line={2} text={long} />
</div>
<div className="rest">rest</div>
</div>
Hey,
May I ask what to require when I try to use the TextTruncate?
I tried
require('react-text-truncate');
require('react-text-truncate/TextTruncate');
require('react-text-truncate').TextTruncate;
all not working. Could you please suggest?
I just added this component to truncate a small piece of copy and I see that its updating ALL the time. I imagine this is not the intended behavior: https://www.dropbox.com/s/hcx0kj0cnjb447a/Screenshot%202016-06-14%2018.31.27.png?dl=0
I'm using react-a11y which puts IDs on elements during development to help identify them. That ID you see is being updated for both the containing div and TextTruncate div constantly. What am I missing here? Here is the code I'm using:
<div className="MessagesSnapshot-item-message">
<TextTruncate className="MessagesSnapshot-item-message" line={2} text="I see by your Health Assessment that you're a very good listener and you like fruit." />
</div>
Also, as you can see in the screenshot, TextTruncate doesn't absorb the className. It would be nice if that was added as well.
In certain cases it would be great to know if the text is actually trimmed or not to e.g. add a "show more" button or something like that.
When adding a ref to TextTruncate
instance variables are not available on the object. I suspect this may be due to the way lib/index.js is built
Component doesn't work well with asian languages that don't use spaces such as Japanese, Chinese, Korean, Thai etc.
When text in these languages is mixed with some latin text with spaces, which is common to include foreign names text is being truncated after the first space even if some more text might fit in. When there are not spaces the text is being truncated just fine.
For example the text SEO担当者であれば、検索順位のチェックは毎日行っていると思います。しかし、検索結果画面(SERPs)の内容までは、日々忙しいマーケッターやWebサイト管理者は、なかなかチェックができていないのではないでしょうか?
is being correctly truncated to SEO担当者であれば、検索順位のチェックは毎日行っていると思います。しかし、検索結果画面(SERPs)の内容...
But the text that contains space Tool SEOは、日々忙しいマーケッターやWebサイト運用者にとって、SEO業務を限りなく効率的に行えるようにしていきたいと考えています。
is being truncated to just Tool...
So this may be specific to how our staging server is set up but I noticed this ONLY when the site is deployed to our staging server. Every instance of this module renders incorrectly: https://www.dropbox.com/s/ft6q4qf7o11brx7/Screenshot%202016-07-29%2006.47.08.png?dl=0
As you can see, the ...
is being rendered as weird characters at the end of every string. I have a feeling this is due to the fact that the truncateText
defaults to the three dots but they aren't actual periods rather the three dot character (whatever thats called). I imagine this is an encoding issue somewhere along the line and will render incorrectly like it is on my server depending on server settings perhaps? It might be worth setting the default to be the actual three dots or allow a global truncateText setting so that a user can set it once and not have to worry about this happening everywhere.
When the text includes characters like \n\r
or <br/>
or Text that are surrounded with <p>
. It would not be converted into line breaks.
thanks for the great lib. I have a need to make a few changes:
you can see my fork here: https://github.com/rt2zz/React-Text-Truncate (sorry about the diff, I made some style tweaks along the way)
I think these changes are probably not general enough to be merged back here, both cut functionality to gain small perf benefits. But I thought I would bring it up here just in case. If some of these changes are desired I am happy to PR.
The styles prop is not working when the text is not truncated.
When the text is not long enough to be truncated, the style prop is not passed to the container div, so styles are not applied.
It happens with long first words (when length is almost as long as width of container)
And outcome is that it won't truncate text - just will show it full.
Sorry, for no snippet for it - writing from phone now :)
Try please, for example, for container with fixed width and just put long word at start.
Thanks!
I would expect the textTruncateChild
node would not be rendered when no text is truncated.
I'm currently facing the problem, that text is cut off when being truncated. As seen in the first screenshot:
As you can see here, the last word was Vivamus:
This is my test code below:
const longText = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis faucibus purus quis nisi blandit, ac semper est elementum. Aenean consequat sollicitudin rhoncus. Suspendisse congue varius augue ut lacinia. Mauris porta magna sem, elementum tempor massa dapibus a. Curabitur tempor dignissim erat feugiat gravida. Vivamus vestibulum luctus nunc, quis rutrum felis viverra et. Aliquam lacinia ipsum sem, eu vestibulum eros tincidunt nec. In et quam quis justo feugiat hendrerit. Nunc faucibus sit amet elit semper fringilla. Nunc placerat tempor metus in fringilla. Quisque tempor lectus elit, ac pharetra quam ultricies non. Aenean posuere malesuada ultrices.
`.trim();
return (
<TextTruncate
line={ 3 }
truncateText="…"
text={ longText }
onTruncated={ () => { /* some action is going on here */ }
/>
);
I'm using "react-text-truncate": "^0.11.2"
and I tested this on Chrome 60.
Hi I get this warning message when i resize the browser window:
Warning: forceUpdate(...): Can only update a mounted or mounting component. This usually means you called forceUpdate() on an unmounted component. This is a no-op. Please check the code for the TextTruncate component.
I saw that you listen the resize window event to foce the render. I don't understand why.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.