How to create an input field (HTML) that spans two lines - html

I want to be able to use an <input> field type of control but allow only two lines.
At the moment I am using two fields but was wondering if anyone can come up with a solution to allow input (similar to a textarea) but no more than two lines. I control the width etc of the field.
For reference, Jquery and Bootstrap 3 are loaded.
Any help much appreciated.

try this
var element = document.getElementById('tworows');
make2Lines(element);
function make2Lines(el){
el.setAttribute('rows', 2); // limit height to 2 rows
// el.setAttribute('wrap', 'off'); // ensure no softwrap is not required anymore if we limit the length
el.addEventListener('keydown', limit); // add listener everytime a key is pressed
function limit(e){
if(e.keyCode == 13 && this.value.indexOf('\n')>-1){
// 13 is the ENTER key and \n is the value it make in the textarea
// so if we already have a line break and it's the ENTER key, we prevent it
e.preventDefault();
}
// async to let the dom update before changin the value
setTimeout(limitRow.bind(this), 0);
}
function limitRow(){
var maxLength = 10;
var rows = this.value.split('\n');
rows.forEach(cutOverflow)
this.value = rows.join('\n');
function cutOverflow(row, index, rows) {
rows[index] = row.substring(0, maxLength);
// this if is only if you want to automatically jump to the next line
if (index === 0 && row.length > maxLength)
rows[1] = row.substring(maxLength) + (rows[1] || '');
}
}
}
<textarea id="tworows"></textarea>
short version : function make2Lines(a){function b(a){13==a.keyCode&&this.value.indexOf("\n")>-1&&a.preventDefault(),setTimeout(c.bind(this),0)}function c(){function c(b,c,d){d[c]=b.substring(0,a),0===c&&b.length>a&&(d[1]=b.substring(a)+(d[1]||""))}var a=10,b=this.value.split("\n");b.forEach(c),this.value=b.join("\n")}a.setAttribute("rows",2),a.addEventListener("keydown",b)}

Two ways come to mind:
You could use a <textarea> instead, and augment it with some script that only allows two lines.
You could continue to use two <input> fields, but style them so they stack on top of each other to create the illusion of one field. You might still need a bit of script to take care of some usability annoyances, such as pressing ENTER to go from line one to line two.

If you are talking about wrapping lines if the text is too long, according to documentation <input type="text"> cannot wrap text.
However, if you are talking about limiting the character length, you could use the maxlength attribute like- <input type="text" maxlength="10">

An input field can only display one line http://www.w3.org/TR/html-markup/input.text.html#input.text. For multiline you need to use textarea and set the rows attribute. If you need two separate values you can do it after in PHP, Javascript or other means.
<textarea class="form-control" rows="2">The default text or empty for nothing this is passed as value for this field</textarea>

Related

React: How to provide procedurally generated <li> elements distinct HTML id values?

I'm rendering a map of items retrieved from a database and filtered via the value state of an input field and attempting to then set the state of the input field as the value stored in some list item on click. I figured that using document.getElementById().innerHTML would allow me to retrieve the content stored within the appropriate tag and then set it to state which does work, the issue I'm facing is that it will only retrieve the innerHTML of the first item rendered in the map.
I've tried solutions ranging from applying UUID to making the mapped content available to the window and transfering the state of the individual objects but each disparate solution only moves the value of the first item to state - any ideas?
Rendered Content:
window.filteredItems = this.state.items.filter(
(item) => {
return item.companyNameObj.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
}
);
<div className="fixed-width">
<div className="search-container">
<form>
<input type="text" name="search" className="search-bar" placeholder="Search: " onChange={this.handleChange} value={this.state.search} />
</form>
<ul className="search-results">
{window.filteredItems.map((item) => {
return (
<div className="distinct-result-container">
<li key={item.id}>
<div className="image-container">
<img src={item.imageObj} alt={item.companyNameObj + " logo."}/>
</div>
<div className="company-container">
<span onClick={this.stateTransfer}><h3 id={"ID"}>{item.companyNameObj}</h3></span>
<p>Owned by: {item.ownerNameObj}</p>
</div>
</li>
</div>
)
})}
</ul>
</div>
<Footer />
</div>
);
stateTransfer()
stateTransfer(id) {
var search = this.state.search;
var uniqueID = document.getElementById("ID").innerHTML;
this.setState({
search: uniqueID
});
}
The current content of stateTransfer() doesn't represent any significant attempts at approaching a solution to this issue, it's just the minimum required implementation to move the innerHTML content to the input fields value.
EDIT: I've further clarified on the task at hand and a potential solution in the comments below (which follow this), I'm just hoping someone is able to help me with the actual implementation.
#DILEEPTHOMAS The list is comprised of data pulled from a Firebase Realtime Database and is rendered via mapping the filteredList and a search query; that functoionality works fine - what I need is to be able to click the element of any distinct li and have the innerHTML (the text stored in that li's item.companyNameObj) be moved to the value of the input field (so users can navigate the search content with re-typing).
#JoshuaLink I can't necessarily configure the items of the list any
further as it's just data pulled from an external database - I believe
the appropriate solution is to somehow provide a unique HTML ID value
to each newly rendered li and have that selected ID moved to
stateTransfer() where it can be set as the input fields value, I'm
just struggling with the actual implementation of this.
EDIT 2: I've managed to figure out a solution to both parts of the problem as described above - I'll post it as an answer below.
I managed to solve both parts of my problem:
The key issue, which was moving the text stored in each distinct li to the input value, which was apparently easily solved by making my stateTransfer() function accept an event and passing the .innerText value of the h3 through the event (I assumed I would have to use .innerHTML, which would require me to provide each distinct li with a unique generated ID) as follows:
stateTransfer(e) {
var search = this.state.search;
var innerText = e.target.innerText
this.setState({
search: innerText
})
}
The secondary issue, (which I incorrectly assumed was integral to implementing a solution to my question), assigning unique HTML id values to my procedurally generated li's was solved by implementing a for-loop in a componentDidUpdate() function which iterates through the current total length of the list and and assigns an id with the loop iterator concatenated to the end of the string as follows:
componentDidUpdate() {
var i;
var searchCompanyNames = document.querySelectorAll('.comapnyNames');
for(i = 0; i < searchCompanyNames.length; i++) {
searchCompanyNames[i].id = 'companyName-' + i;
}
}
Whilst I didn't need to assign unique ID's to the li's in the correct implementation, it's a useful trick worth noting nonetheless.

How to detect up and down clicks on html input[number]?

I have an html <input type="number"> box that has some custom validation logic. A valid value is any integer x where x < -100 OR x >= 100.
My goal is to implement this behavior:
when the user clicks on the native down arrow or presses the down arrow key and the current value is 100, the value changes to -101.
similarly when the user clicks on the native up arrow or presses the up arrow key and the current value is -101, the value changes to 100.
A few caveats:
Users must still be able to type numbers that fall within the invalid range since they may need to type 10 in order to type 109. And validation logic already occurs for this.
I am using angularjs, but I suspect that the solution is not going to be angular specific.
This is an internal application, meant for Chrome only, so browser specific answers are fine.
I think I have what you need, or at least I'm getting close:
window.onload = function() {
function changeNum(input, typing) {
var lower=-101, upper=100, x=parseInt(input.value), active=(input==document.activeElement);
if ((typing && String(Math.abs(x)).length>2 && lower<x&&x<upper) || (!typing && lower<x&&x<upper)) {
if (Math.abs(x-upper) < Math.abs(x-lower)) {input.value = (!active||typing?upper:lower);}
else {input.value = (!active||typing?lower:upper);}
}
}
document.getElementById("num").addEventListener("keyup",function(){changeNum(this,true);},false);
document.getElementById("num").addEventListener("change",function(){changeNum(this,false);},false);
};
<input type="number" id="num" value="100" />
jsfiddle: https://jsfiddle.net/9zz0ra35/4/
codepen: http://codepen.io/anon/pen/Ndqbog
When the user clicks on the input's up&down-buttons, the value flips over on the lower and upper threshold (-100 -> 100, 99 -> -101).
When the user types a value and then clicks outside the input, invalid values are changed to the closest threshold (-100 -> -101, 99 -> 100).
While typing, invalid values are also changed to the closest threshold, but only if the value.length is more than 2 chars (-100 -> -101).
This last one isn't as clean as the others, because it only works if both the lower and upper threshold have the same length (in this case 3 chars).
But if you need thresholds with different lengths, you can always change the String(Math.abs(x)).length>2 to an extra if-clause and first check whether the value is positive or negative, and then check for separate lengths.
I'm not sure if I'm getting what you want. Is it something like this?
var number = document.getElementById('number-input');
number.onchange = function(event) {
if(number.value > 100) {
number.value = -101;
} else if(number.value < -100) {
number.value = 101;
}
};
<input type="number" id="number-input">

Vertical html table without repeating th tags

I'm generating a table using xslt, but for this question I'll keep that side out of it, as it relates more to the actual generated structure of a html table.
What I do is make a vertical table as follows, which suits the layout needed for the data concerned that originated in a spreadsheet. Example is contrived for brevity, actual data fields contain lengthy strings and many more fields.
Title: something or rather bla bla
Description: very long desription
Field1: asdfasdfasdfsdfsd
Field2: asdfasfasdfasdfsdfjasdlfksdjaflk
Title: another title
Description: another description
Field1:
Field2: my previous field was blank but this one is not, anyways
etc.
The only way so far I found to generate such a html table is using repeating tags for every field and every record e.g.:
<tr><th>Title</th><td>something or rather bla bla</td></tr>
<tr><th>Description</th><td>very long desription</td></tr>
...
<tr><th>Title</th><td>another title</td></tr>
<tr><th>Description</th><td>another description</td></tr>
...
Of course this is semantically incorrect but produces correct visual layout. I need it to be semantically correct html, as that's the only sane way of later attaching a filtering javascript facility.
The following correct semantically produces an extremely wide table with a single set of field headers on the left:
<tr><th>Title</th><td>something or rather bla bla</td><td>another title</td></tr>
<tr><th>Description</th><td>very long desription</td><td>another description</td></tr>
...
So to summarise, need a html table (or other html structure) where it's one record under another (visually) with repeating field headers, but the field headers must not be repeated in actual code because that would wreck any record based filtering to be added later on.
Yo. Thanks for updating your question, and including some code. Typically you'd also post what you've tried to correct this issue - but I'm satisfied enough with this post.
Since you want the repeating headers in vertical layout (not something I've seen often, but I can understand the desire), you don't have to modify the HTML formatting, just use a bit more JavaScript to figure it out. I haven't gone through and checked to see if I'm doing things efficiently (I'm probably not, since there are so many loops), but in my testing the following can attach to a vertical table and filter using a couple variables to indicate how many rows there are in each entry.
Firstly, here's the HTML I'm testing this one with. Notice I have a div with the id of filters, and each of my filter inputs has a custom attribute named filter that matches the header of the rows they are supposed to filter:
<div id='filters'>
Title: <input filter='Title'><br>
Desc: <input filter='Description'>
</div>
<table>
<tr><th>Title</th><td>abcd</td></tr>
<tr><th>Description</th><td>efgh</td></tr>
<tr><th>Title</th><td>ijkl</td></tr>
<tr><th>Description</th><td>mnop</td></tr>
<tr><th>Title</th><td>ijkl</td></tr>
<tr><th>Description</th><td>mdep</td></tr>
<tr><th>Title</th><td>ijkl</td></tr>
<tr><th>Description</th><td>mnop</td></tr>
<tr><th>Title</th><td>ijkl</td></tr>
<tr><th>Description</th><td>mnop</td></tr>
</table>
Here are the variables I use at the start:
var filterTable = $('table');
var rowsPerEntry = 2;
var totalEntries = filterTable.find('tbody tr').size() / rowsPerEntry;
var currentEntryNumber = 1;
var currentRowInEntry = 0;
And this little loop will add a class for each entry (based on the rowsPerEntry as seen above) to group the rows together (this way all rows for an entry can be selected together with a class selector in jQuery):
filterTable.find('tbody tr').each(function(){
$(this).addClass('entry' + currentEntryNumber);
currentRowInEntry += 1;
if(currentRowInEntry == rowsPerEntry){
currentRowInEntry = 0;
currentEntryNumber += 1;
}
});
And the magic; on keyup for the filters run a loop through the total number of entries, then a nested loop through the filters to determine if that entry does not match either filter's input. If either field for the entry does not match the corresponding filter value, then we add the entry number to our hide array and move along. Once we've determined which entries should be hidden, we can show all of the entries, and hide the specific ones that should be hidden:
$('#filters input').keyup(function(){
var hide = [];
for(var i = 0; i < totalEntries; i++){
var entryNumber = i + 1;
if($.inArray(entryNumber, hide) == -1){
$('#filters input').each(function(){
var val = $(this).val().toLowerCase();
var fHeader = $(this).attr('filter');
var fRow = $('.entry' + entryNumber + ' th:contains(' + fHeader + ')').closest('tr');
if(fRow.find('td').text().toLowerCase().indexOf(val) == -1){
hide.push(entryNumber);
return false;
}
});
}
}
filterTable.find('tbody tr').show();
$.each(hide, function(k, v){
filterTable.find('.entry' + v).hide();
});
});
It's no masterpiece, but I hope it'll get you started down the right path.
Here's a fiddle too: https://jsfiddle.net/bzjyfejc/

Handling checkboxes and getting values

I'm pretty new to MVC and I'm having a hard understanding how to get the values (basically the IDs) to checkboxes that I'm generating. Here are my checkboxes:
<div id='myCheckboxDiv'>
<input type="checkbox" onclick="checkAll(this)">Check All
#foreach (var form in #Model.DetailObject.DoaFormGroupDocuments)
{
<br>
var checkBoxId = "chk" + form.DocumentId;
#Html.CheckBox(checkBoxId, new { value = form.DocumentId, #checked = true });
#form.DocumentName;
}
</div>
Essentially what I want to do is get the ID to which ever checkbox is checked and save it in to a list after I click a save button at the bottom of the page.
I have run across something like this to handle everything but I'm not quite sure how to use it really...
var values = $('#myCheckboxDiv').find('input:checkbox:checked').map(function () {
// get the name ..
var nameOfSelectedItem = this.attr('name');
// skip the ‘chk’ part and give me the rest
return nameOfSelectedItem.substr(3);
}).get();
The only thing you need to think about is the value of the name attribute your checkbox(es) will have. The way you're handling it right now, your post body is going to have a fairly randomized collection of chkN-named parameters, where N is some number. The modelbinder will need something similarly named as a parameter to your action method in order to bind the posted values to something useful. That's a tall order for something that will be some what variable (the DocumentId values).
The best option would be to set up your checkboxes, instead, as a collection, which means giving them names chk[0], chk[1], etc. Then in your action you can accept a parameter like List<string> chk, and that will contain a list of all the values that were posted.

AS3 TextField: Append text at a certain line?

I'm trying to find a way to append text (appendText) at a certain TextField line number.
I found a way to return the first character of a line:
tf.text.charAt(tf.getLineOffset(10)); //selects line 10
But I haven't found a way to append text. Any help would be appreciated!
This should do the trick (put the supplied text at the start of the supplied line), though there may be a more efficient way of doing it.
function prependToLine(textField:TextField, line:int, text:String):void {
var lineOffset:int = textField.getLineOffset(line-1);
textField.text = textField.text.substring(0,lineOffset) + text + textField.text.substr(lineOffset);
}