I have an input field that accepts a percent, but I'd like to indicate to the user that the value they are entering is a percent.
The problem I'm having is that I'd like the percent to lead the text, so in the input it looks like this: 100% or 10000%, but I don't want the % to be part of the actual input.
Is there a way to achieve? I've tried a couple of options to do this with CSS but fall short when the % value doesn't actually adjust the placement in the input. Instead it's always appended to the very end of the input field instead of catching up with the input.
The component looks like this:
class Input extends Component {
constructor(props) {
super(props);
this.state = {
isActive: false,
}
}
render() {
return (
<div>
<input
value={this.props.value} >
</input>
</div>
)
}
}
CSS:
div {
input:after {
content: '%';
position: absolute;
top: 3.4rem;
z-index: 9999;
color: blue;
font-size: 2rem;
}
}
Example of what I'm trying to achieve, the highlighted text in the example below is what I want the user to be able to edit, and the % to dynamically move depending on the length of the input.
It's easy by using data-attribute on a container (because input cannot handle :before and :after, [More here]) and CSS content:attr()
update = function(el) {
el.parentElement.setAttribute('data-value', el.value)
}
div[data-value] {
position: relative;
}
div[data-value]:after {
content: attr(data-value) "%";
position: absolute;
top: 2px; /* Borders */
left: 2px; /* Borders */
}
div[data-value] input {
color: #FFF; /* Optional bug avoid visual bugs */
}
<div data-value="0.01">
<input value="0.01" oninput="update(this)"/>
</div>
PS: I did it on vanillia but it's easy to update in React
Using jQuery:
$("#input").on("keyup", function(){
$(this).val($(this).val().replace(/[^0-9]/gi, '') + '%')
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="input"/>
This would make it so there's always a % sign at the end and they cannot remove it or add anything except for numbers!
You can also convert this to regular Javascript if you wanted to
Related
Apologies for the bad title, I have a myriad of issues that need work.
I am not a web dev, this is the first time working with Angular, and Typescript, so I am not sure even how to articulate the problems correctly, or even if I am giving you the right information.
So, for starters, my input area should be 15 px by 150px, but it is showing as 108px by 150px.
Here is my css.
.manual-work-entry {
margin-top: 1em;
.entry-row {
height: 40px;
}
.input-small {
width: 100px;
margin: 0;
padding: 1px;
mat-chip {
height: 22px;
font-size: 11px;
width: 85px;
div {
width: 100%;
}
}
}
::ng-deep .lower .mat-form-field-underline {
bottom: 0 !important;
}
::ng-deep .mat-chip-input {
.mat-form-field {
.mat-input-infix,
.mat-form-field-infix,
.mat-chip-input {
width: auto;
height: 15px !important;
}
.mat-chip-input {
flex: 1 1 auto;
}
}
}
}
Second, when I input a value for a chip, it shows above the input box, pushing it down. I want them to show below the box.
Third, when I press enter, I want the value I just typed in to vanish from the input box. I ho idea how to do that.
Fourth, when I hit backspace, I can keep going past the input values, and delete chips. Is this supposed to happen? I don't think it is, but I am not proficient enough in Angular to know.
Here is a chunk of the afflicted HTML code.
<mat-form-field class="input-small">
<mat-chip-list #additionalPartNumberCL
class="mat-chip-list-stacked">
<mat-chip *ngFor="let number of additionalPartNumbers"
[selectable]="true"
[removable]="true"
(removed)="removeMatChip($event, number, 'additionalPartNumbers')">
<div>
{{number}}
</div>
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input placeholder="Additional Part Numbers (optional)"
[matChipInputFor]="additionalPartNumberCL"
(matChipInputTokenEnd)="addMatChip($event, 'additionalPartNumbers')">
</mat-chip-list>
</mat-form-field>
And the corresponding typescript for addMatChip
public addMatChip(event: any, varName: string): void {
const value = (event.value || "").trim();
// this allows us to input the same value multiple times
switch (varName) {
case "additionalPartNumbers": {
this.additionalPartNumbers.push(value);
break;
}
//removing extra code
}
// reset the input value
if (event.value) {
event.value = "";
}
}
and the removeMatChip code
public removeMatChip(event: any, partNumber: string, varName: string): void {
const value = partNumber;
switch (varName) {
case "additionalPartNumbers": {
const index = this.additionalPartNumbers.indexOf(value);
if (index >= 0) {
this.additionalPartNumbers.splice(index, 1);
}
break;
//remove useless code
}
}
}
Any suggestions for improving my code?
I fixed issue 1 and 2 by moving the input to above the mat-chip-list.
Issue 3 was solved by adding an event.input.value = ""; to the if(event.value) in the add function.
I am still working on issue 4.
You can add custom css in the file style.css. first you should try to find out the class from dev tools then you can apply the css to that list.
I have a text input that I want to be specifically for currency. Inside the text field, it should say [$Other CAD]."$Other" should be aligned left and "CAD" should be aligned right, I currently just have a bunch of spaces between the "$Other" and the "CAD". This isn't ideal for different browsers, etc. Is there an easy way to get only the "CAD" portion of the placeholder to align right so it'll always fit regardless of the browser? Also, can I set two different text colors for the placeholder? For example, have the "$" and "CAD" in grey and the "Other" in black
<style>
.donation-amount-input {
height: 65px;
font-size: 34px;
}
.form-control::placeholder {
font-size: 34px;
}
#S {
color: #aaaaaa;
position: absolute;
font-size: 36px;
padding-left: 10px
}
#Other {
position: absolute;
font-size: 36px;
padding-left: 35px;
}
#CAD {
color: #aaaaaa;
position: absolute;
font-size: 36px;
padding-left: 40%;
}
</style>
<body>
<p onclick="fakePlaceholder()" id="S">$</p>
<p onclick="fakePlaceholder()" id="Other">Other</p>
<p onclick="fakePlaceholder()" id="CAD">CAD</p>
<input
type="text"
onselect="fakePlaceholder()"
class="form-control donation-amount-input"
id="other-amount"
/>
</body>
<script>
function fakePlaceholder() {
var S = document.querySelector('S');
S.style.display = 'none';
var Other = document.querySelector('Other');
Other.style.display = 'none';
var CAD = document.querySelector('CAD');
CAD.style.display = 'none';
}
</script>
You can't do that with a placeholder, you will have to create a fake one with javascript for the effect. You have to add three elements : one for the $, one for Other and one for CAD. Then you can styles them and positioning them with position: absolute; in the input to create a fake placeholder. ( Don't forget: you can't put html elements in an input, so you will have to wrap the input and the three elements into another element so you position everything according to it ).
After that, you will have to use javascript to hide this fake placeholder when someone clicks or moves with keyboard on it.
Try something, and if you need help, come back here and show us your code.
I have the following HTML:
<h4 id="myModalLabel"></h4>
I set the content in CSS:
#myModalLabel::after {
content: "gebeurtenis";
}
jsFiddle
This way, Behat can't seem to find the text when running this for example:
Scenario: Viewing gebeurtenis
Given I am on "hrm/calendar"
Then I should see "gebeurtenis"
The result:
Then I should see "gebeurtenis" # HRMContext::assertPageContainsText()
The text "gebeurtenis" was not found anywhere in the text of the current page. (Behat\Mink\Exception\ResponseTextException)
How can I make it so this test will be successfull?
May I suggest a little trick, css att(), to use a text in a pseudo and at the same time have it accessible in the DOM
h4:after {
content: attr(data-txt);
}
<h4 id="myModalLabel" data-txt="gebeurtenis">Here we go ... </h4>
If you still need to look for a text that might be (or you know) in a css rule, then you can do like this, though to scan all elements looking for "text hidden in pseudo css" might not be that speedy.
var element = document.getElementById('div_1'),
style = window.getComputedStyle(element,':after'),
value = style.getPropertyValue('content').replace(/^\"|\"$/gm,''),
result = document.getElementById('result');
if(value.length > 0) {
result.innerHTML = 'Found in css: ' + value;
}
#div_1 {
color: red;
}
#div_1:after {
content: 'world';
color: blue;
}
#result {
margin-top: 20px;
}
<div id="div_1">hello </div>
<div id="result"></div>
I need to create an HTML text input element that features multicolored placeholder text. All of the text should be gray except, but a closing asterisk should be red, as in:
This strikes me as a seemingly simple task that is actually a lot more complicated because of how browsers restrict our ability to style native input elements.
I have heard of people using CSS to override native input styles so they can use custom fonts, etc., but is there away to have two special text styles (gray and red)? Or do I need to use an alternative (non-native) input?
Try something like this: http://jsfiddle.net/vmuJm/
The trick: address the placeholder text, add a "required" class to required inputs, and use the :after pseudo element to add an appropriately colored asterisk.
[EDIT] It looks like this is only working for Webkit browsers.
I have a rather fun way to do this and seems to work great in all browsers.
(Works fine in IE 8+, chrome, and Firefox.)
What I am doing is using the spans I put inside of the label to act as the value text.
Here is the html structure,
<label><span class="title">Name<span class="symbol">*</span></span>
<input type="text" />
</label>
The css,
label {
position: relative;
}
label:hover span {
display: none;
}
input[type="text"]:focus, input[type="text"]:active {
z-index: 2;
}
label input[type="text"] {
position: relative;
}
.title {
color: gray;
position: absolute;
left: 5px;
top: 1px;
z-index: 1;
}
.symbol {
color: red;
}
Last here is the jQuery I wrote to not allow the span to hover over your input if the input is filled in.
$('input[type="text"]').blur(function() {
if( $(this).val().length >= 1) {
$(this).toggleClass('active');
}
else {
$(this).removeClass('active');
}
});
Here is a JSFIDDLE to play with.
Is there a freely available jQuery plugin that changes placeholder behavior to match HTML5 spec?
Before Focus
On Focus Good (Safari)
On Focus Bad (Chrome, Firefox)
You can what your browser does with this simple fiddle.
HTML5 draft spec says:
User agents should present this hint to the user, after having stripped line breaks from it, when the element's value is the empty string and/or the control is not focused (e.g. by displaying it inside a blank unfocused control and hiding it otherwise).
The "/or" is new in current draft so I suppose that's why Chrome and Firefox don't support it yet. See WebKit bug #73629, Chromium bug #103025.
Stefano J. Attardi wrote a nice jQuery plugin that just does that.
It is more stable than Robert's and also fades to a lighter grey when the field gets focused.
See the demo page
Grab it on GitHub
Play with the fiddle
I modified his plugin to read placeholder attribute as opposed to manually creating a span.
This fiddle has complete code:
HTML
<input type="text" placeholder="Hello, world!">
JS
// Original code by Stefano J. Attardi, MIT license
(function($) {
function toggleLabel() {
var input = $(this);
if (!input.parent().hasClass('placeholder')) {
var label = $('<label>').addClass('placeholder');
input.wrap(label);
var span = $('<span>');
span.text(input.attr('placeholder'))
input.removeAttr('placeholder');
span.insertBefore(input);
}
setTimeout(function() {
var def = input.attr('title');
if (!input.val() || (input.val() == def)) {
input.prev('span').css('visibility', '');
if (def) {
var dummy = $('<label></label>').text(def).css('visibility','hidden').appendTo('body');
input.prev('span').css('margin-left', dummy.width() + 3 + 'px');
dummy.remove();
}
} else {
input.prev('span').css('visibility', 'hidden');
}
}, 0);
};
function resetField() {
var def = $(this).attr('title');
if (!$(this).val() || ($(this).val() == def)) {
$(this).val(def);
$(this).prev('span').css('visibility', '');
}
};
var fields = $('input, textarea');
fields.live('mouseup', toggleLabel); // needed for IE reset icon [X]
fields.live('keydown', toggleLabel);
fields.live('paste', toggleLabel);
fields.live('focusin', function() {
$(this).prev('span').css('color', '#ccc');
});
fields.live('focusout', function() {
$(this).prev('span').css('color', '#999');
});
$(function() {
$('input[placeholder], textarea[placeholder]').each(
function() { toggleLabel.call(this); }
);
});
})(jQuery);
CSS
.placeholder {
background: white;
float: left;
clear: both;
}
.placeholder span {
position: absolute;
padding: 5px;
margin-left: 3px;
color: #999;
}
.placeholder input, .placeholder textarea {
position: relative;
margin: 0;
border-width: 1px;
padding: 6px;
background: transparent;
font: inherit;
}
/* Hack to remove Safari's extra padding. Remove if you don't care about pixel-perfection. */
#media screen and (-webkit-min-device-pixel-ratio:0) {
.placeholder input, .placeholder textarea { padding: 4px; }
}
Robert Nyman discusses the problem and documents his approach in his blog.
This fiddle that has all the neccessary HTML, CSS and JS.
Unfortunately, he solves the problem by changing value.
This will not work by definition if placeholder text is itself a valid input.
I found this question by googling out the solution to the same problem. It seems that existing plugins either don't work in elder browsers or hide placeholder on focus.
So I decided to roll on my own solution while trying to combine best parts from existing plugins.
You may check it out here and open an issue if you face any problems.
How about something simple like this? On focus save out the placeholder attribute value and remove the attribute entirely; on blur, put the attribute back:
$('input[type="text"]').focus( function(){
$(this).attr("data-placeholder",$(this).attr('placeholder')).removeAttr("placeholder");
});
$('input[type="text"]').blur( function(){
$(this).attr("placeholder",$(this).attr('data-placeholder'));
});
I wrote my own css3 only solution. See if that fullfills all your needs.
http://codepen.io/fabiandarga/pen/MayNWm
This is my solution:
the input element is set to "required"
an aditional span element for the placeholder is needed. This element is moved on top of the input element (position: absolute;)
with css selectors the input element is tested for validity (required fields are invalid as long as there is no input) and the placeholder is then hidden.
Pitfall: The placeholder is blocking mouseevents to the input! This problem is circumvented by hiding the placeholder element when the mouse is inside the parent (wrapper).
<div class="wrapper">
<input txpe="text" autofocus="autofocus" required/>
<span class="placeholder">Hier text</span>
</div>
.placeholder {
display: none;
position: absolute;
left: 0px;
right: 0;
top: 0px;
color: #A1A1A1;
}
input:invalid + .placeholder {
display: block; /* show the placeholder as long as the "required" field is empty */
}
.wrapper:hover .placeholder {
display: none; /* required to guarantee the input is clickable */
}
.wrapper{
position: relative;
display: inline-block;
}
Maybe you can try with Float Label Pattern :)
See Float labels in CSS