I'm working on an Angular 6 application where I am having a textarea. On having an error, an asterisk sign should be displayed beside the textarea on the top-right corner. The issue I'm having is on resizing the textarea element, there is a gap between the textarea element and the asterisk sign. I think I need to dynamically give the width of the textarea to the asterisk. But, I am not able to to it by CSS or get a (resize) event on it. How to go about it? Any help will be appreciated.
Sample code is given below.
demo-file.html
<div class="col-6 fix-custom-width">
<label for="dataVal"><span>*</span>Data Value</label>
<textarea id="dataVal" placeholder="Max 20 Characters" tabindex="2" type="text" class="form-control resizable-textarea" formControlName="dataVal" [ngClass]="{'is-invalid': dataVal.errors && (dataVal.dirty || dataVal.touched || submitted)}" required></textarea>
<span *ngIf="dataVal.errors && (dataVal.dirty || dataVal.touched || submitted)" class="display-inline error-asterisk">*</span>
<div class="red-color" *ngIf="dataVal.errors && (dataVal.dirty || dataVal.touched) || submitted">
<p *ngIf="dataVal.errors && dataVal.errors.required>
Required
</p>
</div>
</div>
demo-file.css
.error-asterisk {
position: absolute;
right: 0px;
top: 30px;
color: $error-message-text-color;
}
.fix-custom-width {
max-width: 100%;
}
.resizable-textarea {
max-width: inherit;
resize: both;
}
.textareaContainer{
display:flex;
}
<div class="textareaContainer">
<textarea id="dataVal" placeholder="Max 20 Characters"></textarea>
<span class="display-inline error-asterisk">*</span>
</div>
This can be easily done by display:flex; by default align-items is set to flex-start which means all element will start from top & flex by default puts elements in one after another
Related
This question already has answers here:
Javascript: Creating Functions in a For Loop
(3 answers)
Closed 1 year ago.
I have a website with a bunch of inputs that looks like this (I cannot edit the HTML since this part is automatically generated):
<div style="display: inline; position: relative;">
<div>
<label for="inputID">label here</label>
<label >*</label>
</div>
<div>
<div>
<input type="text" fieldformat="None" id="inputID" placeholder="something">
</div>
</div>
</div>
I want to make it so that when the user is entering something on input field, the label will disappear appear
___________________________ _first name (label)_______
| first name (placeholder) | click | |
|___________________________| --------> |__________________________|
here is my attempt at doing it with javascript:
function displayOnFocusAndOnFocusOut() {
var inputs = [
'inputID1',
'inputID2',
'inputID3',
...
]
for(var i = 0; i < inputs.length; i++) {
var input = document.getElementById(inputs[i])
input.onfocus = function() {
input.parentElement.parentElement.parentElement.firstChild.style.display = 'none'
console.log(input.parentElement.parentElement.parentElement.firstChild)
}
input.onfocusout = function() {
input.parentElement.parentElement.parentElement.firstChild.style.display = 'block'
}
}
}
However this doesnt work as the label still displays when I click on the input, and with a console log it shows that only the last input is affected. I've also tried adding !important but it still does not work.
How can I fix this?
Thanks
You don't need any javascript:
body {
height: 200vh;
}
.field>div {
display: inline-flex;
flex-direction: column-reverse;
}
.label {
height: 1em;
margin-bottom: 0.2em;
}
.label>label {
transition: height 0.5s;
height: 0;
overflow: hidden;
display: inline-block;
}
.field input:not(:placeholder-shown) ~.label>label {
height: 1em;
}
<div class="field">
<div>
<input type="text" fieldformat="None" id="inputID1" placeholder="something">
<div class="label"><label>label here *</label></div>
</div>
</div>
<br>
<div class="field">
<div>
<input type="text" fieldformat="None" id="inputID2" placeholder="something">
<div class="label"><label>label here *</label></div>
</div>
</div>
This example will show labels when placeholder is hidden, you can change it so it would show labels when input field is in focus by replacing :not(:placeholder-shown) with :focus
Summary: I've created a search bar with three inputs: name, date of birth, and social security number. The functionality is all there, but I am attempting to elevate the design and am running into an issue on input focus.
When the user selects the inputs, there are focus effects in my CSS. What I am trying to do is toggle the images on input focus. Currently they are written like this:
<div class="adv-searchbar__wrapper__search-box">
<span class="column-1"><img src="/img/person-name.png" class="input-ico"/><input type="text" class="input" id="adv-input-1" placeholder="John Adam Smith"></span>
<span class="column-2"><input type="date" class="input" id="adv-input-2" placeholder="MM / DD / YY"></span>
<span class="column-3"><img src="/img/person-ssn.png" class="input-ico"/><input type="text" class="input" id="adv-input-3" placeholder="### - ## - ####"></span>
<button type="submit" class="advSearchBtn"><img src="/img/search_white.png"/></button>
</div>
The user can either click the button to execute the next function, or use the Enter key.
Effort: I've tried using if-else statements in jQuery when the user Clicks an input. The issue with that that I've found is that I am not sure how to 'measure' when the user leaves the input. So while the image will change correctly, it will not change back once the user moves on.
$('.input').click(function() {
let currIco = $(this)[0].previousSibling.src.slice(0, -4);
if ($(this).is(':focus')) {
console.log('input is focused');
currIco = currIco + '__focus.png';
$(this)[0].previousSibling.src = currIco;
} else {
console.log('input is blurred');
}
});
I've found several tutorials for changing images on click or on hover, but I haven't been able to implement those solutions to my needs.
You say in a comment that the only reason you didn't use CSS is because the images are not in the input.
As CSS is still an option for you and it is much easier to achieve in CSS (plus you haven't got a JS answer yet), take a look at the solution below.
FYI CSS-only is also a more efficient option - the more client-side processing you add, the slower the page load and the worse for SEO and user experience.
.column-1 input, .column-3 input {
background-repeat: no-repeat;
background-position: top left;
padding-left: 40px;
}
.column-1 input {
background-image: url(https://lorempixel.com/output/abstract-q-c-30-30-1.jpg);
}
.column-1 input:focus {
background-image: url(https://lorempixel.com/output/abstract-q-c-30-30-2.jpg);
}
.column-3 input {
background-image: url(https://lorempixel.com/output/abstract-q-c-30-30-3.jpg);
}
.column-3 input:focus {
background-image: url(https://lorempixel.com/output/abstract-q-c-30-30-4.jpg);
}
<div class="adv-searchbar__wrapper__search-box">
<span class="column-1">
<input type="text" class="input" id="adv-input-1" placeholder="John Adam Smith">
</span>
<span class="column-2"><input type="date" class="input" id="adv-input-2" placeholder="MM / DD / YY"></span>
<span class="column-3"><input type="text" class="input" id="adv-input-3" placeholder="### - ## - ####"></span>
<button type="submit" class="advSearchBtn"><img src="/img/search_white.png"/></button>
</div>
Obviously I haven't applied your styling to the inputs because you hadn't included it, but you can apply that the same way excluding the image.
You could, alternatively to the existing answer (provided by FluffyKitten), create a <label> element and place it after the <input>.
I too, don't recommend using JavaScript over CSS if you are indeed able to get it done in CSS.
In this case, you can separate the icon (and therefore the styling) from the rest of the input field if you so desire.
.adv-searchbar__wrapper__search-box span {
position: relative;
}
.input {
box-sizing: border-box;
padding: 2px 2px 2px 20px;
max-height: 20px;
border: 1px solid #888;
}
.input~.icon {
position: absolute;
left: 2px;
top: 0px;
height: 16px;
width: 16px;
background-image: url('https://via.placeholder.com/16?text=icon');
background-repeat: no-repeat;
}
.input:focus~.icon {
filter: blur(1px);
background-image: url('https://via.placeholder.com/16/FF9900');
}
<div class="adv-searchbar__wrapper__search-box">
<span class="column-1">
<input type="text" class="input" id="adv-input-1" placeholder="John Adam Smith">
<label class="icon" for="adv-input-1"></label>
</span>
<span class="column-2">
<input type="date" class="input" id="adv-input-2" placeholder="MM / DD / YY">
</span>
<span class="column-3">
<input type="text" class="input" id="adv-input-3" placeholder="### - ## - ####">
<label class="icon" for="adv-input-3"></label>
</span>
<button type="submit" class="advSearchBtn">
<img src="https://via.placeholder.com/16?text= "/>
</button>
</div>
Here is an other way, using focus on parent element.
span:focus-within .input-ico-focus {
display: inline-block;
}
span:focus-within .input-ico {
display: none
}
span .input-ico-focus {
display: none
}
span .input-ico {
display: inline-block;
}
.input-ico, .input-ico-focus {
width: 16px;
}
<div>
<span class="column-1">
<img src="https://i.stack.imgur.com/pd8J3.png" class="input-ico">
<img src="https://i.stack.imgur.com/XdkNO.png" class="input-ico-focus">
<input type="text" class="input" id="adv-input-1" placeholder="John Adam Smith">
</span>
</div>
I tried to change the position of bootstrap input-group-addon when on mobile by using two input and playing with their display and visibility.
From a frontend visibility perspective I got what I want, the input is now behind the addons ... but I'm running some javascript on #input-newsearch and when on mobile it's not working. It looks like it's still looking at the first input. What am I missing or how can I solve this?
html:
<div class="input-group">
<input id="input-newsearch" class="form-control input-newsearch-desktop" type="text">
<span class="input-group-addon" id="delete-newsearch">Delete</span>
<span class="input-group-addon" id="remove-newsearch">Remove</span>
<input id="input-newsearch" class="form-control input-newsearch-mobile" type="text">
</div>
css:
.input-newsearch-mobile {
display: none;
visibility: hidden;
}
#media (max-width: 768px){
.input-newsearch-desktop {
display: none;
visibility: hidden;
}
.input-newsearch-mobile {
display: initial;
visibility: initial;
}
}
javascript:
$('#delete-newsearch, #delete-newsearch').on('click', function() {
$('#input-newsearch').val('');
});
$('#input-newsearch').autocomplete({
source:'/source.php',
minLength: 3,
...
});
Instead of using Id's as your selection I would use a class instead.
The reason it is not working as you intended is because Id's are expected to only show up once. It causes problems when you have multiple elements with the same Id and try to reference one of them.
Styles
Added the class input-newsearch
<div class="input-group">
<input id="input-newsearch" class="form-control input-newsearch input-newsearch-desktop" type="text">
<span class="input-group-addon" id="delete-newsearch">Delete</span>
<span class="input-group-addon" id="remove-newsearch">Remove</span>
<input id="input-newsearch" class="form-control input-newsearch input-newsearch-mobile" type="text">
</div>
Javascript
Changed Id selector '#input-newsearch' to the class '.input-newsearch'
$('#delete-newsearch, #delete-newsearch').on('click', function() {
$('.input-newsearch').val('');
});
$('.input-newsearch').autocomplete({
source:'/source.php',
minLength: 3,
...
});
I have a series of inline elements (with input text boxes) that should fit within one row. See picture below.
The number of input boxes can vary (dynamically loaded via AJAX), as can the labels of the input boxes. In the example below, it is length x width x height.
The div that the inline elements are in is a dynamic width, which depends on the content above and below this row.
In the event of the screenshot below, how can I get the input boxes to equally increase in width so that the content is justified on both sides? Is there a pure CSS solution?
.dynamicWidth {
background-color: green;
height: 400px;
position: absolute;
}
<div class="dynamicWidth">
<div>
<select>
<option>This could be longer or shorter dependending on what is dynamically loaded</option>
</select>
</div>
<hr>
<div>
<span>Length</span>
<input type="text" placeholder="length"><span> x Width</span>
<input type="text" placeholder="width"><span> x Height</span>
<input type="text" placeholder="height">
</div>
</div>
You can accomplish this using flexbox's justify-content and assigning the value of space-around to the div containing the input elements.
.dynamicWidth {
background-color: green;
width: 100%;
height: 400px;
position: absolute;
}
.dynamicWidth div:nth-of-type(2) {
display: flex;
justify-content: space-around;
}
<div class="dynamicWidth">
<div>
<select>
<option>This could be longer or shorter dependending on what is dynamically loaded</option>
</select>
</div>
<hr>
<div>
<span>Length</span>
<input type="text" placeholder="length"><span> x Width</span>
<input type="text" placeholder="width"><span> x Height</span>
<input type="text" placeholder="height">
</div>
</div>
If you're trying to support legacy browsers that don't support flexbox your alternative option would be to wrap each label and input in their own respective divs, give the enclosing parent of those divs a display of table and give the input divs a display of table-cell with width percentages of 33.3% (1/3s).
.dynamicWidth {
background-color: green;
width: 100%;
height: 400px;
position: absolute;
}
.dynamicWidth div:nth-of-type(2) {
display: table;
width: 100%;
}
.input-container {
width: 33.3%;
display: table-cell;
}
<div class="dynamicWidth">
<div>
<select>
<option>This could be longer or shorter dependending on what is dynamically loaded</option>
</select>
</div>
<hr>
<div>
<div class="input-container">
<span>Length</span>
<input type="text" placeholder="length">
</div>
<div class="input-container">
<span> x Width</span>
<input type="text" placeholder="width">
</div>
<div class="input-container">
<span> x Height</span>
<input type="text" placeholder="height">
</div>
</div>
</div>
I am using bootstrap datetimepicker with formatting to enable only editing time in my code, I do it like this:
function setTimepicker(object){
object.datetimepicker({
format: 'HH:mm'
});
}
I call this function in document.ready like so:
$(document).ready(function(){
setTimepicker(starttimefield);
setTimepicker(endtimefield);
});
The html I am using is like this:
<div class="panel-body">
<form id="myform">
<p> <b>Create a New Event:</b></p>
<br>
<p>Description for main page: <br>
<textarea id="summary" name="summary" maxlength="100"></textarea>
</p>
<p> Full description: <br>
<textarea id="description" name="description" maxlength="500"></textarea>
</p>
<div class="wrapper">
<div class="titles">
<p> Event date:
</p>
<p> Start time:
</p>
<p> End time:
</p>
</div>
<div class="values">
<input type="text" id="eventdate" readonly/><br>
<div id="starttimepicker">
<input type="text" id="starttime" onkeydown="return false"/><br>
</div>
<div id="endttimepicker">
<input type="text" id="endtime" onkeydown="return false"/>
</div>
</div>
</div>
<p> Location: <input type="text" id="location"/> </p>
<p><input type="hidden" id="userid" value="<?php echo Auth::id();?>"/></p>
<p><input id="saveevent" type="button" value="Save Event" />
</p>
</form>
</div>
Except for the standard css files (jquery-ui.css, bootstrap-datetimepicker.css) I added 1 extra css file that contains:
.wrapper {
display: inline-block;
width: auto;
overflow: hidden;
}
.titles {
width: 100px;
float:left;
}
.values {
overflow: hidden;
margin-left: 100px;
}
Now for the issue at hand, the fields endtime and starttime should have a timepicker when clicked (this works) but look at where it renders the timepicker in this image:
Can anyone help me to get that timepicker element next to (or above or close by, anything) the field that it belongs to
You are missing an .input-group wrapper which has a position value of "relative". Since the datepicker is absolutely positioned it's container needs to be relatively positioned for the datepicker to be positioned correctly.
So I believe something like this would work:
.values {
position: relative;
overflow: hidden;
margin-left: 100px;
}
Better yet, let's set position relative on the divs that actually hold our inputs like so:
#starttimepicker {
position: relative;
}
#endtimepicker {
position: relative;
}
If you want my opinion though that is not very DRY. If you have control over the html you might try to add a class of "values__datepicker" (or whatever class) to #starttimepicker and #endtimepicker and set just one CSS rule like so:
.values__datepicker {
position: relative;
}