Additional whitespace appearing at bottom of auto-resizing textarea element - html

I have a textarea which I have added an onChange listener to in order to update the field's height whenever a new line is required (or if a line is no longer required). The issue I'm having is that, when the cursor approaches the end of the (current) final line of the textarea, additional whitespace is created which does not actually "exist" (i.e. it consists of no characters - sort of an "empty line").
My description probably isn't sufficient to explain the issue I'm having, but the same effect can be observed in the JSFiddle below (I'm using an identical implementation for my own form):
https://jsfiddle.net/d9fqaest/
As you can see, when the end of the first line is reached, a new line is added without issue:
But when the end of the second line (or any following lines) is reached, a new "empty" line is added too soon (with any following lines requiring fewer and fewer characters before adding the erroneous line):
I suspect the issue lies somewhere in the way the row count is calculated:
handleChange(e) {
const oldRows = e.target.rows;
e.target.rows = 1;
const newRows = ~~(e.target.scrollHeight/lineHeight);
if (newRows === oldRows) {
e.target.rows = newRows;
}
this.setState({
value: e.target.value,
rows: newRows
});
}
I've tried a few different flows of logic here, including simply setting the element's height to its scrollHeight, but I haven't been able to produce the desired behaviour (the aforementioned approach somewhat worked, but I was unable to figure out how to remove lines as text was deleted). I'm aware of several external libraries which would solve this problem, but I'd like to avoid using those if at all possible.
Thanks!

So it turns out all that was needed was overflow-y: hidden on the textarea to prevent the scrollbar from being included in the height calculation. Simple fix!

Related

How to fix div height and cut down extra text from it

I am using bootstrap cards to display my content. I want every bootstrap card height to be equal. Everything else is fine but issue comes when I display discription as it is of variable length.
Sometimes it occupies two lines and sometimes three.
I want to fix description div height and cut down extra text from it.
Note Card are being displayed through loop
This is what I tried:
$('address').height(30);
var txt= $('address').text();
if(txt.length > 155)
$('address ').text(txt.substring(0,50) + '.....');
This is working perfectly fine for one card. But when there are multiple cards running in loop, same description text appears along every card due to this line: var txt= $('address').text();
How to make it work separately for each card?
Your current select is targetting all the address element. You need to filter out the elements based on if condition. You can use jquery filter function for this.
Then iterate over those objects and modify the text.
var $addressToChange= $('address').filter(function(){
return $(this).text().length > 155;
});
$addressToChange.each(function(){
$(this).text($(this).text()..substring(0,50) + '.....')
})
I am thankful to #Milind Anantwar for his answer as his answer gave me a clue. I little modify his answer and achieved my desired result by using this piece of code:
$('address').height(40);
$('address').each(function(i){
if ($(this).text().length > 40)
{
$(this).text($(this).text().substring(0,50) + '.....')
}
});

Align to the right values in uitable after formatting with html code

I have an annoying problem with Matlab coding: I have created a uitable which store values and I have implemented a function for highlight the number in cells in particular conditions. This has been done giving an html command, the problem is that after the setting of new colour the number from a "double" becomes a "cell" and updating the data in the table it highlights correctly the value, but aligns all the numbers to the left; instead I would like to keep them constantly on the right. I tried everything without positive results; I think is enough to add the alignment command in the html syntax, but somebody can give me some suggestion?
This is the part of the code:
tab = findobj('Tag',tab_name);
valrow = cellstr(num2str(tab.Data(index,1))); %number in the cell has to be highligthed
color = [1 1 0.4]; %yellow
clr = dec2hex(round(color*255),2)'; clr = ['#';clr(:)]';
valrow = strcat(...
['<html><body bgcolor="' clr '"text="#010101; font-weight: width=100px">'],...
valrow); %html code for highlight the number
fulltab = cellstr(num2str(tab.Data(:,1))); %transform all the data in the table from double to cell
fulltab(index,1) = valrow; % switch the old value in the tab with the same value highligthed
set(tab,'Data',[fulltab]);
As I said previously, this code works but put all the data in the table from right usual alignment to the left.
I had the same problem... then I realized the width was set at 100% not the actual cell width. Once I made the correction the text was aligned within the width setting.
CellVal = strcat('',MaxOver,'');

How to force browser to break text where possible?

I need to determine minimum width adequate for displaying a possibly wrapped dynamic HTML string. Without word-wrapping this is simple: create a span, set its innerHTML and read offsetWidth. However, I'm not sure how to force linebreaks... Easiest incomplete approach I see is to replace all spaces by <br/>, but lines can be wrapped not only on spaces but also e.g. on hyphens.
So, basically, I want a browser to lay out sth. like
Max.
word-
wrapped
string
<----->
somewhere off-screen to measure width of the longest contained word. Is there a generic way to do that?
EDIT
I.e., for no line wraps:
function computeWidth (str) { // code to make it off-screen and caching omitted
var span = document.createElement ('span');
document.body.appendChild (span);
span.innerHTML = str;
return span.offsetWidth;
}
How would I write a similar function which forces line breaks on str, presumably playing with span.style?
You can use CSS work-break / word-wrap and programmatically inserted soft-hyphens (­, but I'd advise you to read up on cross browser problems regarding soft hyphens, as there are quite a few - I normally us the unicode for a soft hypen (U+00AD), but your mileage may vary), and then determine the width with javascript using the range object and measuring cursor offset from the left.
I'm suggesting the use of soft-hyphens, because even the same browser will normally break words differently depending on the OS / which dictionary (on OSX) is used. If that's not an issue for you, you can do it without soft hyphens.
Afaik there is no generic way to get what you want in html/js (it's different if you were using something like flash).
Range object:
https://developer.mozilla.org/en-US/docs/Web/API/range
A different approach would be using the canvas object, but you would probably not get exact results there, as there is just too much factors influencing text rendering in browsers nowadays (font, size, kerning, tracking, ...)
Again another approach would be using <pre> tags / whitespace: pre-wrap, setting the font to what you normally use, and then either emulate breaking words by inserting linebreaks or copying them from still another span/div/whatever set up with word wrap - I haven't tested this yet, but if it works, it might be easer than iterating with the range object.
Edit: Just so it's not only in the comments, still another solution:
Start your container with width 1px, then increase the width, checking the height every time ; when the height decreases, go back one step, and you got your width. Simplest implementation would use 1px increase/1px decrease, but you could of course optimize it to using something like a binary search algorithm, e.g. starting with 1px, then 2px, then 4px increases, then the same backwards, and forwards again and so on till you have a result at a 1px step. But that's only if the 1px inc/dec sollution is too slow ;)
Use the CSS word-break rule:
The word-break CSS property is used to specify how (or if) to break lines within words.
Normal
Use the default line break rule.
break-all
Word breaks may be inserted between any character for non-CJK (Chinese/Japanese/Korean) text.
keep-all
Don't allow word breaks for CJK text. Non-CJK text behavior is same as normal.
<p style="word-break:break-all;">
Max.word-wrapped string<----->
</p>
(source)
Try to play with the word-break Property.
More here: http://www.w3schools.com/cssref/tryit.asp?filename=trycss3_word-break
You should try:
word-break: break-all;
Add it to the CSS like in this fiddle, or read here.

TextField autoSize+italics cuts of last character

In actionscript 3, my TextField has :
CSS styling
embedded fonts
textAlign : CENTER
autoSize : CENTER
... when italics are used the very right character gets slightly cut off (specially caps).
It basically seems that it fails detecting the right size.
I've had this problem before but just wondered is there a nice workaround (instead of checking textWidth or offsetting text etc.)?
Initialize your textField as you always do, using multiline, autosize, htmlText...
Then do this little trick :
// saving wanted width and height plus 1px to get some space for last char
var savedWidth = myTextField.width + 1;
var savedHeight = myTextField.height + 1;
// removing autoSize, wich is the origin of the problem i think
myTextField.autoSize = "none";
// now manually autoSizing the textField with saved values
myTextField.width = savedWidth;
myTextField.height = savedHeight;
Not that it is much comfort to you, but Flash sometimes has trouble with this seemingly simple task. CSS styling of html TextField was a nice addition but it has caused headaches for text-rendering. In fact I very rarely use CSS for styling text for that reason. I can only imagine that combining bold, italic and normal type faces within the HTML causes Flash to get some of the width calculations wrong which causes autoSize to set the mask a tiny bit short. I hope very much that the new text rendering engine in Flash Player 10 will finally fix these issues (it certainly looks better in theory).
So my solution is never to use HTML with the exception being when I require <a> links in my text ... and there are even some tricky text shifting issues there. In those cases I avoid mixing different font weights and font styles within the same text field. All other cases I use TextFormat directly on TextField.
I suppose if you can't get out of your current architecture (for some reason) you could try adding to the end of your html encoded strings. Or you could manually set the width of the field and not rely on autoSize (as you have mentioned). But if you keep on the CSS/HTML route you may find another new and painful limitation just when you don't want it.
I've had issues with TextField masks behaving differently in the Flash preview, and in the actual browser plugin. Usually, and this is strange to me, it would appear more correctly in the browser. Have you tried running the swf in a browser to see if the problem is actually an annoyance rather than a permanent problem?
I had said this:
My in-ideal approach to solving this is to attach a change event to the TextField which always adds a space after the last character of the field. And then to remember to trim this space off when using the value.
But that didn't take into account that this probably doesn't have a change event and that it's an HTML rendered text field. To add a trailing space in the HTML text field throw in an again, that's not really fixing the problem.

Style html text input size to match its contents

I've asked a few other questions here about this system, so I'll try to avoid repeating a lot of detail.
The short version is that I have many html pages, each with a form that accepts input, but never saves the input anywhere- they are only ever printed out for mailing. A previously developer who had never heard of #media print did the initial work on most of them, and so he came up with some... odd solutions to hide the ugly text boxes on the printed page, usually resulting in two completely separate copies of nearly the same html. Unfortunately, that broke the back button in many cases, and so now I must go back and fix them.
In some cases, these html forms really are form letters, with text inputs in the middle of the text. I can style the text inputs so that the box doesn't show, but they are still the wrong size. This results in a bunch of extra ugly whitespace where it doesn't belong. How can make the inputs fit the text entered by the user?
The best I can come up with at the moment is to have a hidden <span> next to each input that is styled to show instead of the input when printing, and use javascript to keep it in sync. But this is ugly. I'm looking for something better.
Update:
Most of our users are still in IE6, but we have some IE7 and firefox out there.
Update2:
I re-thought this a little to use a label rather than a span. I'll maintain the relationship using the label's for attribute. See this question for my final code.
The span idea isn't that bad. With a Javascript library like jquery, a single 1-2 line Javascript function could dynamically replace all the appropriate <input> tags with <span>..</span>. You wouldn't have to enter in any of the spans yourself.
In really rough pseudo-javascript code with jquery it would be something like:
function replaceInputsOnSomeButtonClick() {
// Find all inputs, wrap value with span tag, remove the input tag
$("input").text().wrap("<span>").remove();
}
CSS doesn't have answer for this one. Inputs are "replaced elements" – a black box in CSS.
input {content:attr(value)} works only for initial value in HTML, and won't reflect any later changes.
So the best you can get is less ugly Javascript.
for(var i=0; i < form.elements.length; i++)
{
var input = form.elements[i];
if (input.type != 'text') continue;
var span = document.createElement('span');
input.parentNode.insertBefore(span,input);
span.className = 'show-in-print';
input.className = 'hide-in-print';
input.onchange = (function(span){ // trick to preserve current value of span
return function()
{
if (span.firstChild) span.removeChild(span.firstChild);
span.appendChild(document.createTextNode(this.value));
}
})(span);
}