I have a div and a file input box. When we click on the div, the click of file input is to be triggered. How to do this in vue.js?
You will have to access the DOM to trigger the click event for the input.
But Vue can make it pretty convenient with the ref/$refs feature
With it, you can "mark" an element in the template and access it conveniently from within your component's code without relying on selectors.
new Vue({
el: '#app',
methods: {
clickHandler() {
this.$refs.fileInput.click()
}
}
})
.button {
padding: 10px;
border-radius: 5px;
border: 1px solid #CCC;
display: inline-block;
}
<script src="https://unpkg.com/vue#2.3/dist/vue.js"></script>
<div id="app">
<div class="button" #click="clickHandler">Click me!</div>
<input type="file" ref="fileInput">
</div>
Add a ref to you input and a click listener to your wrapper div
<div #click="triggerFileInput" id="wrapper">
<input type="file" ref="myFile">
</div>
methods:{
triggerFileInput(){
this.$refs.myFile.click();
}
}
Related
I have a game where there are balloons and each balloon has an onclick attribute which passes the id into a JS function to change the css.
Example:
<div id="balloon" class="container" onclick="popBalloon(this.id);"></div>
clicking this item will call the function below
function popBalloon(id){
document.getElementById(id).setAttribute("class","pop");
}
Problem is that I have multiples balloons of the same type, and instead of using a unique id for each one, I would like a way to determine the specific balloon being clicked using the same attribute names.
Is this possible?
If you pass event as the function parameter, you can use event.target to get the clicked Element
function popBalloon (event) {
event.target.setAttribute("class", "pop");
}
div {
margin-top: 10px;
height: 30px;
width: 30px;
border: 1px solid;
border-radius: 50%;
}
.container {
background-color: red;
}
.pop {
background-color: blue;
}
<div class="container" onclick="popBalloon(event);"></div>
<div class="container" onclick="popBalloon(event);"></div>
<div class="container" onclick="popBalloon(event);"></div>
<div class="container" onclick="popBalloon(event);"></div>
<div class="container" onclick="popBalloon(event);"></div>
Most of current answers suggest a function that defines click listener to a group of elements however you asked how to omit unique IDs where there are too many elements in a game. The simple answer is to pass OBJECT instead of ID to the function:
<div class="container" onclick="popBalloon(this);"></div>
and in the function:
function popBalloon(myobj){
myobj.setAttribute("class","pop");
}
Thats all.
Instead of manually entering the function signature in each balloon entry, handle it all in the javascript below. Throw all those balloons into a list. As Scott Hunter suggested, place each balloon in a class. Let's call it "balloon". Then add an event listener to each of those balloons. Here's a quick demo.
var balloonArray = document.querySelectorAll(".balloon");
balloonArray.forEach(function(item) {
item.addEventListener('click', function() {
item.innerText = "Clicked";
});
});
.container {
color: white;
height: 80px;
margin: 10px;
text-align: center;
}
<div class="container balloon" style="background-color: blue">Click me</div>
<div class="container balloon" style="background-color: red">Click me</div>
<div class="container balloon" style="background-color: green">Click me</div>
A good way to do it is add some class to all the balloons. Let's modify your code a bit
<div class="balloon"></div>
<div class="balloon"></div>
<div class="balloon"></div>
I have 3 of those divs with a class of balloon here. For the js we can do
Array.from(document.querySelectorAll(".balloon")).forEach(balloon=>{
balloon.addEventListener('click',()=>{
//On click event here
});
});
Here's how you add a click event to each of the balloon.
I have an already existing form in my code which includes 2 text fields and a submit button.
I have also added an “add” button which when clicked should add a new form below.How do I achieve this using Javascript.
How do I add a new form by clicking on the add button?
you could use jquery $.clone() function so when you hit the button the form will be cloned and then $.append() to the parent div
this will clone the form with the data , if you want something without the data you should clone the form in the start of the script.
You could use a templating engine like {{ mustache }} to create a form template and inject an auto-incrementing ID into it.
Note: If you want more logic, customization, or compiled templates, you can use handlebars.
var FORM_ID_INCR = 1; // Ever-increasing couter
document.getElementById('add-form-btn').addEventListener('click', function(e) {
createAndAppendNewContactForm();
});
function createAndAppendNewContactForm() {
let viewModel = { formId : FORM_ID_INCR++ };
let template = document.getElementById('form-template').innerHTML;
let renderedHtml = Mustache.render(template, viewModel);
let node = document.createRange().createContextualFragment(renderedHtml);
document.getElementById('form-container').appendChild(node);
}
.form-field {
margin-bottom: 0.5em;
}
.form-field label {
display: inline-block;
font-weight: bold;
width: 6em;
}
.contact-form {
border: 1px solid #DDD;
padding: 0.5em;
margin-bottom: 0.5em;
}
#form-container {
margin-bottom: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/3.1.0/mustache.min.js"></script>
<script id="form-template" type="text/html">
<form id="form-{{formId}}" class="contact-form">
<h2>Form #{{formId}}</h2>
<div class="form-field">
<label>First Name</label>
<input type="text" name="firstName"/>
</div>
<div class="form-field">
<label>Last Name</label>
<input type="text" name="lastName"/>
</div>
<input type="submit" />
</form>
</script>
<body onload="createAndAppendNewContactForm()">
<h1>Forms</h1>
<div id="form-container"></div>
<button id="add-form-btn">Add Form</button>
</body>
I want to be able to click on a div, but not in the area of another div inside a div inside the outer div.
I tried to select my other div without the inner div using :not() in the selector, but it didn't work.
<div class=outer>
<div class=inner1>
<div class=inner2>
<div class=notClickable>
<div class=alsoNotClickable>
...
</div>
</div>
</div>
</div>
</div>
$("div.outer:not(div.notClickable)").click(function(){
...
});
I expect that I can click inside div class=outer, but not inside div class=notClickable and its childs.
One option is adding stopPropagation() on the non clickable divs.
The stopPropagation() method of the Event interface prevents further
propagation of the current event in the capturing and bubbling phases.
$("div.outer").click(function() {
console.log("click");
});
$("div.notClickable").click(function(e) {
e.stopPropagation();
});
$("div.alsoNotClickable").click(function(e) {
e.stopPropagation();
});
.outer {
width: 300px;
height: 300px;
background-color: green;
}
.notClickable {
width: 100px;
height: 100px;
background-color: red;
}
.alsoNotClickable {
width: 50px;
height: 50px;
background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class=outer>
<div class=inner1>
<div class=inner2>
<div class=notClickable>
<div class=alsoNotClickable>
</div>
</div>
</div>
</div>
</div>
To achieve this you can check the target property of the event. If it matches the element you hooked the event to then you know that the event has not bubbled up from a child. Try this:
$("div.outer").click(function(e) {
if ($(e.target).is('div.outer')) {
console.log('You clicked the outer div');
} else {
console.log('You clicked a child div');
}
});
div.outer,
div.outer div {
padding: 10px;
border: 1px solid #CCC;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="outer">
Outer
<div class="inner1">
Child
<div class="inner2">
Child
<div class="notClickable">
Child
<div class="alsoNotClickable">
Child
</div>
</div>
</div>
</div>
</div>
I think you can stop the propagation by adding this line to your function:
event.stopPropagation();
Eg:
$("div.outer:not(div.notClickable)").click(function(event) {
...
event.stopPropagation();
});
Please check this fiddle where i use the click function. Let me know if that would fits you :)
Assign an ID to the div you want to select. Then select the ID.
I have a list of DIVS that have buttons inside. By default, all buttons are hidden. When I click within a DIV area, the current button inside of this clicked DIV are should show (class='.db') AND all previously clicked/shown buttons should be hidden (class='.dn'). In other words, at any time there should be only one button (currently clicked) shown and all other should be hidden.
I want to use vanilla Javascript and tried this below, but it won't work. I feel there is some small error but don't know where.. Note - the DIVS and buttons don't have their own unique IDs (they only have the same CSS (.posted) classes.
PS - maybe it'd be better not to add this onClick="t();" to each DIV and use an 'addEventListener' function, but this is way too much for me ; )
CSS:
.dn {display:none}
.db {display:block}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
HTML:
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
JAVASCRIPT:
function t()
{
var x=document.getElementsByClassName("posted"),i,y=document.getElementsByTagName("button");
for(i=0;i<x.length;i++)
{
x[i].y[0].className="dn";
};
x.y[0].className='db';//make sure the currently clicked DIV shows this button (?)
}
You might want to read more about selector, how to select class, block level etc.
some link might be helpful:
CSS selector:
https://www.w3schools.com/cssref/css_selectors.asp
jQuery selector:
https://api.jquery.com/category/selectors/
Solution - Using jQuery:
$('.posted').on('click', function() {
//find all class called posted with child called dn, then hide them all
$('.posted .dn').hide();
//find this clicked div, find a child called dn and show it
$(this).find('.dn').show();
});
.dn {
display: none
}
.db {
display: block
}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="posted">
<button class="dn">Reply1</button>
</div>
<div class="posted">
<button class="dn">Reply2</button>
</div>
<div class="posted">
<button class="dn">Reply3</button>
</div>
Solution - Pure js version:
//get list of div block with class="posted"
var divlist = Array.prototype.slice.call(document.getElementsByClassName('posted'));
//for each div
divlist.forEach(function(item) {
//add click event for this div
item.addEventListener("click", function() {
//hide all button first
divlist.forEach(function(el) {
el.getElementsByTagName('button')[0].classList.add('dn');
});
//show button of the div clicked
this.getElementsByTagName('button')[0].classList.remove('dn');
}, false);
});
.dn {
display: none
}
.db {
display: block
}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="posted">
<button class="dn">Reply1</button>
</div>
<div class="posted">
<button class="dn">Reply2</button>
</div>
<div class="posted">
<button class="dn">Reply3</button>
</div>
You can do this with with plain JavaScript using Event Bubbling, querySelector and the element classList attribute like this.
Change your HTML to look like this:
<div class="posts">
<div class="posted">
<button class="dn">Reply</button>
</div>
<div class="posted" >
<button class="dn">Reply</button>
</div>
<div class="posted" >
<button class="dn">Reply</button>
</div>
</div>
Then use JavaScript like this:
var posts = document.querySelector('.posts');
var allPosted = document.querySelectorAll('.posted');
//clicks bubble up into the posts DIV
posts.addEventListener('click', function(evt){
var divClickedIn = evt.target;
//hide all the buttons
allPosted.forEach(function(posted){
var postedBtn = posted.querySelector('button');
postedBtn.classList.remove('db');
});
// show the button in the clicked DIV
divClickedIn.querySelector('button').classList.add('db')
});
You can find a working example here: http://output.jsbin.com/saroyit
Here is very simple example using jQuery .siblings method:
$(function () {
$('.posted').click(function () {
$('button', this).show();
$(this).siblings().find('button').hide();
});
});
https://jsfiddle.net/3tg6o1q7/
Let's say you have something like:
<div class="parent">
<input class="childInput" type="text" />
<div class="sibling"></div>
</div>
I want to change the appearance of the parent/siblings when the child receives focus. Are there any CSS tricks for doing stuff like this?
Edit:
The reason for my question is as follows:
I'm creating an Angular app which needs editable text fields. It should look like a label until it is clicked, at which point it should look like a normal text input. I styled the text field based on :focus to achieve this effect, but the text is cut off by text input's boundaries. I also used ng-show, ng-hide, ng-blur, ng-keypress and ng-click to switch between the label and the text input based on blurs, key presses and clicks. This worked fine except for one thing: After the label's ng-click="setEdit(this, $event)" changes the edit boolean used by ng-show and ng-hide to true, it uses a jQuery call to .select() the text input. However, it isn't until after the completion of the ng-click that everything is $digest'd, so the text input loses focus again. Since the text input never actually receives focus, using ng-blur to revert back to showing the label is buggy: The user has to click in the text input and then click out of it again to revert back to showing the label.
Edit:
Here's an example plunk of the issue: http://plnkr.co/edit/synSIP?p=preview
You can now do this in pure CSS, so no JavaScript needed 😁
The new CSS pseudo-class :focus-within would help for cases like this and will help with accessibility when people use tabbing for navigating, common when using screen readers.
.parent:focus-within {
border: 1px solid #000;
}
The :focus-within pseudo-class matches elements that either themselves
match :focus or that have descendants which match :focus.
Can I use...
You can check which browsers support this by visiting http://caniuse.com/#search=focus-within
Demo
fieldset {
padding: 0 24px 24px !important;
}
fieldset legend {
opacity: 0;
padding: 0 8px;
width: auto;
}
fieldset:focus-within {
border: 1px solid #000;
}
fieldset:focus-within legend {
opacity: 1;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<form>
<fieldset>
<legend>Parent Element</legend>
<div class="form-group">
<label for="name">Name:</label>
<input class="form-control" id="name" placeholder="Enter name">
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" class="form-control" id="email" placeholder="Enter email">
</div>
</fieldset>
</form>
</div>
There is no chance how to do that with CSS. CSS can style only siblings, children, etc. not parents.
You can use simply JS like this:
<style>
.parent {background: green}
.focused {background: red;}
</style>
<div class="parent">
<input class="childInput" type="text" />
<div class="sibling"></div>
</div>
<script>
$('.parent > *')
.focus(function() {
$('.parent').addClass('focused');
})
.blur(function() {
$('.parent').removeClass('focused');
});
</script>
http://jsfiddle.net/C4bZ6/
This code takes all direct children of .parent and if you focus one of them, class focused is added to parent. On blur, this class is removed.
You can use pure CSS to make the text input look like it's not a text input unless it is in focus
http://jsfiddle.net/michaelburtonray/C4bZ6/13/
input[type="text"] {
border-color: transparent;
transition-duration: 600ms;
cursor: pointer;
outline-style: none;
text-overflow: ellipsis;
}
input[type="text"]:focus {
border-color: initial;
cursor: auto;
transition-duration: 300ms;
}
Try the contenteditible attribute. This may require more work to turn it into usable form data however.
http://jsfiddle.net/michaelburtonray/C4bZ6/20/
<span class="parent" contenteditable>Click me</span>
You can style it even for focus-within and not(focus-within) like this (without using JavaScript => more accessible and faster):
.myform:not(:focus-within) button[type="submit"] {
display: none;
}
.myform:focus-within button[type="submit"] {
display: block;
}