On input focus change color of label. How? - less

On input focus I want to change the color of the label element. How can I achieve this in less?
.control-label{
color: #gray-light;
}
.controls{
input,
textarea{
background-color:red;
&:focus{
.control-label &{
color: red; //HERE
}
}
}
HTML:
<div class="control-group">
<label class="control-label" for="inputEmail">Firstname</label>
<div class="controls">
<input type="text" id="inputEmail" placeholder="Firstname">
</div>
</div>

One solution would be to use the :focus-within selector.
So, you'd do something like the below. Assuming that you always have an input of some description inside of a control-group, it will style the label whenever the input is focused on.
control-group {
&:focus-within {
control-label {
color: red;
}
}
}
More information can be found here: https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-within

I don't think you can without changing your HTML, see also: Is there any way to hover over one element and affect a different element?, your elements should be direct siblings. (LESS don't help to solve your problem here, LESS generate CSS and it seems impossible to do in CSS)
Possible suggestion:
input:focus + .control-label
{
background-color:purple;
color: red;
}
.controls > input
{
float:right;
}
<div class="controls">
<input type="text" id="inputEmail" placeholder="Firstname">
<label class="control-label" for="inputEmail">Firstname</label>
</div>
Or solve your problem with javascript: https://stackoverflow.com/a/20226218/1596547

Use Flexbox
CSS is cascading, i.e. affected by the order that elements appear in the DOM. To be able to select the label only when the input is focused (input:focus + label), the label needs to come after the input, so;
Put the input before the label in the DOM and then use flexbox to reverse the order that they appear on the page.
.input-group {
display: flex;
flex-direction: column-reverse;
}
input:focus + label {
color: green;
}
<div class="input-group">
<input value="Input" />
<label>Label</label>
</div>

One solution would be to move the label below the input in the DOM but position them absolutely (to the parent) so the label looks to be above the input field:
<div>
<input type="text"/>
<label>Text</label>
</div>
In CSS move the label to the top, the input to the bottom:
label {
position: absolute
top: 0
}
input {
position: absolute
bottom: 0
}
And use the :focus state to change the style of the label:
input:focus + label {
color: red
}
See example:
http://codepen.io/robcampo/pen/zGKLgg
On focus, the label turns red. No JS required.

control-group {
&:focus-within {
control-label {
color: red;
}
}
}
loads of hearts to this person. Nothing was working and this worked in ion-label too . Accepted answer. Stack overflow does not allow to comment (below 50 reputation). So writing seperately <3

I hope I am not too late to answer this. With the new :has psudo-class we can achieve it without changing the HTML,
HTML:
<div class="control-group">
<label class="control-label" for="inputEmail">Firstname</label>
<div class="controls">
<input type="text" id="inputEmail" placeholder="Firstname">
</div>
</div>
CSS:
.control-group:has(input:focus) label{
color: red;
}
This approach is simple and cleaner.
Note: it is not supported by firefox yet.

The easy way is to use :focus-within check developer mozilla
.control-group:focus-within .control-label {
color: red;
}
Or
.control-group:focus-within label {
color: red;
}

Related

How to respond to the name attribute in elm-css

I don't know how to express the CSS code below using elm-css.
input[name="tab_item"] {
display: none;
}
<div>
<input type="radio" name="tab_item">
<label>hoge hoge</label>
</div>

How to add dialog/modal that asks if we want to delete something in vuejs2

So i have been looking on internet for some kinda of dialog/modal in vuejs2 that pops up when exit is clicked, that asks us if we are sure that we want to leave. And when click yes, function is called , and when clicked no, nothing happens just dialog/modal is exited. I was not able to find anything on the vuejs.org.Im not using bootstrap and not using vutify. Any suggestions how this can be done, that popup should blackout the rest of the screen and poput in the middle of the screen.
Its very easy to create your own dialog.
Here is a small component that I created for you.
https://jsfiddle.net/ew1c3z6u/
Im really new to veujs but this should work for you
var component =new Vue({
el: '#dialog-container',
methods:{
show:(event)=> {
component.visibility = true;
// maybe you could ajest the position of the dialog here.
// eg top, center etc
},
onSave:(event)=> {
alert("save clicked")
component.visibility = false;
},
onCancel:(event)=> {
alert("cancel clicked")
component.visibility = false;
}
},
data: {
buttons:[], // you could have a list a dynamic buttons here
content:"this is the content of the dialog",
visibility:false,
title: 'this is the title of the dialog'
}
})
.dimBackground{
background:black;
opacity:0.5;
z-index:90;
position:fixed;
width:100%;
height:100%;
left:0;
top:0;
}
#dialog-container > #dialog
{
background:white;
z-index:100;
min-width:400px;
min-height: 100px;
border:1px black solid;
display:inline-block;
padding:0;
position:fixed;
left:30%;
top:30%;
overflow-x:hidden;
overflow-y:auto;
}
#dialog-container > #dialog > h1{
width:99%;
background:blue;
color:white;
margin:0;
font-size:20px;
padding-top:5px;
padding-bottom:5px;
padding-left:5px;
}
#dialog-container > #dialog > .content{
padding:5px;
}
#dialog-container > #dialog > h1 > div{
display:inline-block;
float:right;
position:relative;
top:-3px;
padding-right:5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.0/vue.js"></script>
<div id="dialog-container">
<input type="button" value="show dialog" v-on:click="show" />
<div class="dimBackground" v-if=visibility> </div>
<div id="dialog" v-if=visibility>
<h1>
{{title}}
<div>
<button v-on:click="onSave" >
Save
</button>
<button v-on:click="onCancel">
Cancel
</button>
</div>
</h1>
<div class="content">
{{content}}
</div>
</div>
</div>

How to set focus on input field in Vuejs when field loads conditionally with v-if

My form has a first name and last name that initially appear as one compact string, but split into two input fields when the user clicks on the string. I need these two input fields to disappear and revert back to the compact string format when the user clicks elsewhere on the page (anywhere other than inside those two input fields). In order to achieve this, I use a v-on directive with the blur attribute. This works well, but only if the user first clicks into one of the input fields to trigger focus. This is because blur only triggers on an input field that is already in focus. Is there either a way for me to automatically put the first input field in focus when the input element conditionally renders? Is there a better approach?
Cheers.
Here is my HTML:
<a v-if="!eitherNameSelected" #click="firstNameSelected">
{{person.firstname}} {{person.lastname}}</a>
<div class="row" v-else-if="eitherNameSelected" v-enter="focusOnFirstChild($event)">
<div class="col-md-3">
<input
#focus="firstnameselected=true"
#blur="firstnameselected=false"
type="text"
class="form-control"
name="example-text-input-invalid is-invalid"
id="firstname"
placeholder="First Name"
v-model="person.firstname"
>
<div class="invalid-feedback">
Invalid feedback
</div>
</div>
<div class="col-md-3">
<input
#focus="lastnameselected=true"
#blur="lastnameselected=false"
type="text"
class="form-control"
name="example-text-input-invalid is-invalid"
placeholder="Last Name"
v-model="person.lastname"
>
<div class="invalid-feedback">
Invalid feedback
</div>
And in my Javascript ...
data() {
return {
listid: 0,
listname: "",
personid: 0,
person: {},
nameselected: false,
activetab1: "main",
activetab2: "notes",
firstnameselected: false,
lastnameselected: false,
....
methods: {
firstNameSelected() {
var elem = vm.$el.getElementById('firstname');
elem.focus();
this.firstnameselected="true";
}
},
computed: {
eitherNameSelected() {
return (this.firstnameselected || this.lastnameselected);
}
},
It may not be the best solution but you could use a #click($event) in order to know where you clicked to hide or not the inputs.
This post about checking event targets can be a good start I guess.
I also coded a minimal example to help you get through your issue. I hope it will help you.
new Vue({
el: "#app",
data: {
person: {
firstname: 'PersonFirstname',
lastname: 'PersonLastname'
},
showCompactString: true
},
methods: {
onCompactStringClicked() {
this.showCompactString = false
},
// Hide the inputs if a click is triggered outside of them
onAppClicked(event) {
// Do nothing if compact string is being shown
if (this.showCompactString)
return
const fistnameInputClickedOn = event.target.matches('#firstname')
const lastnameInputClickedOn = event.target.matches('#lastname')
const anyInputClickedOn = fistnameInputClickedOn || lastnameInputClickedOn
if (!anyInputClickedOn)
this.showCompactString = true
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" #click="onAppClicked($event)">
<a v-if="showCompactString" #click.stop="onCompactStringClicked">{{person.firstname}} {{person.lastname}}</a>
<div class="row" v-else>
<div>
<input type="text" id="firstname" placeholder="First Name" v-model="person.firstname">
</div>
<div>
<input type="text" id="lastname" placeholder="Last Name" v-model="person.lastname">
</div>
</div>
</div>
Don't hesitate to leave a comment if you have trouble. I'll answer you back as fast as I can.
put an #click=someFunction (or computed) on the root element (i.e. the whole body of HTML) and then have that change the text.

use vue and v-model with a css specific checkbox

I am migrating some jQuery code to Vue. We have a part that is like the following:
<td>
<p>
<input class="select-one checkbox-default-input" type="checkbox" :value="placement.id" v-model="checkedPlacements">
<label for="select-clicks" class="checkbox-default" #click="setValue"></label>
</p>
</td>
ie I am using a label to adjust the UI of an input similar to this: Pure CSS Checkbox Image replacement
how would I associate my v-model with the correct input value?
<td>
<p>
<input id="select-clicks" class="select-one checkbox-default-input" type="checkbox" :checked="placement.id" #input="toggleCheckbox">
<label for="select-clicks" class="checkbox-default"></label>
</p>
</td>
I have added an id attribute to the input tag which corresponds to the label for attribute.
:checked="placement.id" - Here placement.id should correspond to a boolean value stored on your vue component's data property.
#input="toggleCheckbox" - this should be a simple method on your vue component that toggles the value. Something like this:
toggleCheckbox() {
this.placement.id = !this.placement.id;
},
You can then apply conditional classes to the element using the :class bindings. You can read more about them here: https://v2.vuejs.org/v2/guide/class-and-style.html
As #GustavMahler pointed out, Vue Guide: Form Input binding shows how to reach the goal.
#GustavMahler already provided the solution by v-bind and v-on (actually v-model is one syntax sugar which does similar things. one simple explanation at here),
Below is the steps uses v-model:
add attr=id for the checkbox, so label know which checkbox it links.
v-model to one data property which is one Array. (if default value is one Boolean, the value will be one Boolean value (true/false), it ignores the value it binds (please check the third checkbox).)
click the checkbox(label), it will toggle the values to the array.
Below is one demo (the CSS part is copied from the link in the question).
new Vue({
el: '#app',
data() {
return {
placement: {id: 'value1'},
checkedPlacements: [], // default is one Array
checkedPlacement: false // default is one Boolean
}
},
watch: {
checkedPlacements: function (newVal) {
console.log('changed', newVal)
},
checkedPlacement: function (newVal) {
console.log('changed', newVal)
}
}
})
input[type=checkbox] {
display:none;
}
input[type=checkbox] + label
{
background: #999;
height: 16px;
width: 16px;
display:inline-block;
padding: 0 0 0 0px;
}
input[type=checkbox]:checked + label
{
background: #0080FF;
height: 16px;
width: 16px;
display:inline-block;
padding: 0 0 0 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<p>
<input class="select-one checkbox-default-input" type="checkbox" :value="placement.id" v-model="checkedPlacements" id="select-clicks1">
<label for="select-clicks1" class="checkbox-default"></label>
<input class="select-one checkbox-default-input" type="checkbox" :value="'value2'" v-model="checkedPlacements" id="select-clicks2">
<label for="select-clicks2" class="checkbox-default"></label>
</p>
<p>
<input class="select-one checkbox-default-input" type="checkbox" :value="placement.id" v-model="checkedPlacement" id="select-clicks3">
<label for="select-clicks3" class="checkbox-default"></label>
</p>
</div>

get error when showing dojo simple dialog

I've written a on click function to show a simple dojo dialog, but instead it shows
NO_FAST_DRAW = false
This actually works in Nexus 4, 5 and other devices - but not in Samsung Galaxy S2.
on(dojo.byId("send_email"), "click", function()
{
console.log("emailClicked1");
dijit.registry.byId("emailDialog").show();
dojo.byId("emailsText").value="";
dojo.byId("dialogFlag").value="emailDialog";
console.log("emailClicked2");
});
I can see the console email Clicked1 and 2 but not able to see the dialog as well in UI.
<div id="emailDialog" data-dojo-type="dojox.mobile.SimpleDialog">
<form id="emailDialogForm">
<div id="emailDialogText">
<p class="blue_text" style="text-align: left;">To:</p>
<input id="emailsText" type="email"
style="line-height: 2em; width: 95%; margin: 3px; border: none; padding: 2px; font-size: 0.65em;"
placeholder="Enter email ID (Separate multiple IDs by ,)" />
</div>
<div class="button_grid">
<input type="submit" id="submitEmail" value="Send" /> <input
type="button" id="cancelEmail" value="Cancel" />
</div>
</form>
</div>
In the onclick function handler, "show()" action of dialog is asynchronous. So, any code that deals with the content of the dialog, needs to be done only after the show() is completed. i.e, the deferred action needs to be handled.
console.log("emailClicked1");
var def = dijit.registry.byId("emailDialog").show();
if(def) {
def.then(function(success) {
dojo.byId("emailsText").value="";
});
}
dojo.byId("dialogFlag").value="emailDialog";
console.log("emailClicked2");