I have a div which I called quote_div and is the parentElement. It contains two input type="number" elements, a <label> element which I called r_lbl (variable name) and another <label> element called r_position (so that's four elements in one div).
I put an event listener on the div so that when either input type="number" element is changed I can perform a calculation.
quote_div.addEventListener("change", calculateCost);
Now I'm trying to access the r_position element on the div using the event trigger e (which is parsed to calculateCost(e) function) but i get an undefined error which is strange because I've predefined the value for r_position.
console.log("li element position: " + e.target.parentElement.r_position.value);
Is it not possible to do things this way? If so, what have I not understood?
Depending on your HTML structure, you could use NonDocumentTypeChildNode.previousElementSibling or NonDocumentTypeChildNode.nextElementSibling:
const div = document.getElementById('quote_div');
div.addEventListener('change', (e) => {
const target = e.target;
const label = target.previousElementSibling;
console.log(label.innerText);
});
<div id="quote_div">
<label class="r_lbl" for="input1">Label 1</label>
<input id="input1" type="number" />
<label class="r_position" for="input2">Label 2</label>
<input id="input2" type="number" />
</div>
Otherwise, you could use Element.querySelector() from the parent <div> using an id, class, name or any other selector:
const div = document.getElementById('quote_div');
div.addEventListener('change', (e) => {
const div = e.target.parentElement;
const label1 = div.querySelector('.r_lbl');
const label2 = div.querySelector('.r_position');
console.log(label1.innerText, label2.innerText);
});
<div id="quote_div">
<label class="r_lbl" for="input1">Label 1</label>
<input id="input1" type="number" />
<label class="r_position" for="input2">Label 2</label>
<input id="input2" type="number" />
</div>
Related
<div class="search-input" onclick="getSearch()">
<input
oninput="getPorts(value)"
type="text"
id="pick"
name="pick"
placeholder="Enter Pickup Location"
required
/>
<div class="autocom-box">
<!-- dynamic portsData map box -->
</div>
</div>
<div class="search-input" onclick="getSearch()">
<input
oninput="getPorts(value)"
type="text"
id="dest"
name="dest"
placeholder="Enter Destination"
required
/>
<div class="autocom-box">
<!-- dynamic portsData map box -->
</div>
</div>
This is Js
let searchWrapper;
let inputBox;
let suggBox;
const getSearch = () => {
searchWrapper = document.querySelector(".search-input");
console.log(searchWrapper);
inputBox = searchWrapper.querySelector("input");
console.log(inputBox);
suggBox = searchWrapper.querySelector(".autocom-box");
console.log(suggBox);
};
I am trying to get class selected based click as the class name is same (search-input) but here whichever div i click it always gets selected the 1st one. (In searchWrapper console.log it gives 1st div and its elements)
Can anyone tell me What am i doing wrong here so that i can get 2nd div and its elements if i click on 2nd div.
Two answers for you.
Using modern event handling
I suggest you don't use onxyz-attribute-style event handlers. There are multiple issues with them, but probably the most significant two are:
They can only call global functions.
The generated context for them is very complex, making it very easy to run into conflicts (for instance, if your function had the name removeChild or appendChild or in some cases submit, you wouldn't end up calling your function, you'd call a method on a DOM element instead).
Instead, look at using addEventListener. Here's an example where the event handlers are directly attached to your div elements:
<div class="search-input">
<input
oninput="getPorts(value)"
type="text"
id="pick"
name="pick"
placeholder="Enter Pickup Location"
required
/>
<div class="autocom-box">
<!-- dynamic portsData map box -->
</div>
</div>
<div class="search-input">
<input
oninput="getPorts(value)"
type="text"
id="dest"
name="dest"
placeholder="Enter Destination"
required
/>
<div class="autocom-box">
<!-- dynamic portsData map box -->
</div>
</div>
const getSearch = (event) => {
const searchWrapper = event.currentTarget;
const inputBox = searchWrapper.querySelector("input");
const suggBox = searchWrapper.querySelector(".autocom-box");
// ...
};
for (const element of document.querySelectorAll(".search-input")) {
element.addEventListener("click", getSearch);
}
I only did the div elements there, but you'd want to do the input elements as well.
You might also look at delegated event handling.
Continuing with onclick attribute
If you really want to keep using the onclick attribute, pass this into it:
<div class="search-input" onclick="getSearch(this)">
<!-- −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^ -->
this in the context generated for onxyz-attribute-style event handlers is the element the onclick attribute is on (the .search-input div in this case).
Then, in getSearch, search within that div:
const getSearch = (searchWrapper) => {
const inputBox = searchWrapper.querySelector("input");
const suggBox = searchWrapper.querySelector(".autocom-box");
// ...
};
First of all stop using inline event listeners. Use addEventListener instead. To do so, grab a list of all search input wrappers and iterate over the list, adding a click listener to each and every one.
When you have done so, the handler function automatically gets passed the event object, which contains the currentTarget property holding a reference to the element the event listener is bound to. This then allows you to find descendants of that element using querySelector on it instead of document.
To access the event object, you need to define a parameter name in your handler function. I've used event in below example, but you can name it anything you like.
let searchWrapper;
let inputBox;
let suggBox;
const getSearch = (event) => {
searchWrapper = event.currentTarget;
console.log(searchWrapper);
inputBox = searchWrapper.querySelector("input");
console.log(inputBox);
suggBox = searchWrapper.querySelector(".autocom-box");
console.log(suggBox);
};
for (const searchInput of document.querySelectorAll('.search-input')) {
searchInput.addEventListener('click', getSearch);
}
<div class="search-input">
<input type="text" id="pick" name="pick" placeholder="Enter Pickup Location" required />
<div class="autocom-box">
1. abc
</div>
</div>
<div class="search-input">
<input type="text" id="dest" name="dest" placeholder="Enter Destination" required />
<div class="autocom-box">
2. def
</div>
</div>
I have a problem with my JavaScript Code...
I'm developing a "ToDo-List", where you can add and remove Elements all of these things are already working but I also like to have an "counter" which shows the number (length) of all unchecked checkboxes.
I have created a button with JS:
let btn = document.createElement("button");
btn.classList.add("destroy");
and I already have saved the right place for show the number (length) for the unchecked checkboxes:
let counter = document.getElementsByClassName("todo-count");
and then i wrote code to show me the unclicked boxes:
for(let btn of buttons) {
if(btn.classList.contains("destroy")) {
btn.addEventListener("click", function() {
btn.parentElement.parentElement.remove();
for(let counts of counter) {
let parsed = parseInt(counts.innerText);
counts.innerText = parsed - 1;
}
})
}
}
As already mentioned, adding elements already works, but as soon as I add e.g. 5 elements and the first element (which, like all other elements, also has a checkbox) is calculated as minus 5 instead of minus 1...
Just count the checked checkboxes, do not try to maintain the state.
function updateCounts() {
const allCheckboxes = document.querySelectorAll(".my-class");
const checkedCheckboxes = document.querySelectorAll(".my-class:checked");
console.log("Checked count:", checkedCheckboxes.length);
console.log("Unchecked count:", allCheckboxes.length - checkedCheckboxes.length);
}
updateCounts();
document.querySelector("form").addEventListener("change", updateCounts);
<form>
<input type="checkbox" class="my-class">
<input type="checkbox" class="my-class">
<input type="checkbox" class="my-class">
<input type="checkbox" class="my-class">
</form>
"...but when I click a checkbox, the counter should subtract by one."
You'll need another event listener for the change event. The change event fires off when the user changes the value of a form control and then clicks elsewhere (which is another event like blur or focusout).
If you haven't already, wrap everything in a <form> so you can use the HTMLFormElement interface. It's very terse and specialized for forms and form controls. Bind your event handler to the form so you can have the advantages Event Delegation will give you like listening for events for an unlimited number of elements whether they are static or dynamically added.
const uncheckedCount = e => {
const io = e.currentTarget.elements;
const out = io.out;
if (e.target.name === 'btn' || e.type === 'change') {
const unchecked = [...io].filter(inp => inp.checked === false)
out.value = unchecked.length;
}
};
const ui = document.forms[0];
ui.addEventListener('change', uncheckedCount);
ui.addEventListener('click', uncheckedCount);
<form>
<input type='checkbox' checked>
<input type='checkbox' checked>
<input type='checkbox'>
<input type='checkbox' checked>
<input type='checkbox'>
<input type='checkbox' checked>
<input type='checkbox'>
<input type='checkbox'>
<input type='checkbox'>
<input type='checkbox'>
<input type='checkbox' checked>
<br>
<button name='btn' type='button'>GO</button>
<output name='out'></output>
</form>
I want to get the id of input using it's name,and to empty the input field.But it's not working.Is it possible?
html:
<input type="text" id="1" name="Color" maxlength="2" />
jQuery:
var myId="#";
myId=myId + $('[name="Color"]').attr('id');
$($myId).var('');
You can do this:
let id = $('input[name$="Color"]').val('').attr('id');
console.log(id);
$(`#${id}`).val('');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="1" name="Color" maxlength="2" />
You can set the input value using the val() function.
<input type="text" id="1" name="Color" maxlength="2"/>
var myId='#' + $('[name="Color"]').attr('id');
$(myId).val('');
To get the input value use it like this:
$(myId).val();
Try this code.
const myId = $('input[name="Color"]').attr('id');
$("#"+myId).val(''); // you can set any value here or you can perform any other operations on this element -> $("#"+myId)
On first line of this JS code, we are getting id attribute and then on second line, we're using to manipulate element.
Now, if you want id only for performing some operations on that input element, you don't need to get id. You can also do like this.
let elem = $('input[name="Color"]');
elem.val(''); // only if same name is not used anywhere else.
I hope this helps you.
You can use attr directly to set a value. Moreover there is no need to append #.
let element = $('[name="Color"]');
console.log("before", element.attr('id'));
element.attr('id', null);
console.log("after", element.attr('id'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="1" name="Color" maxlength="2" />
I'd like to get the source code of a div, so example if a div contains some tags I'd like to get them as they are in html format and update it on a textfield.
JsFiddle : https://jsfiddle.net/Lindow/g1sp1ms3/2/
HTML :
<form>
<label class="tp_box_1">
<input type="radio" name="selected_layout" class="selected_layout" value="layout_1">
<div class="box_1">
<h3>box_one</h3>
<p>1</p>
</div>
</label>
<br><hr><br>
<label class="tp_box_2">
<input type="radio" name="selected_layout" class="selected_layout" value="layout_2">
<div class="box_2">
<h3>box_two</h3>
<p>2</p>
</div>
</label>
<textarea id="mytextarea"></textarea>
<input id="submit_form" type="button" value="Send">
</form>
JavaScript :
$('input[type="radio"][name="selected_layout"]').change(function() {
if(this.checked) {
// get the specific div children of $this
var selected_layout = $(this).find('.selected_layout');
// get source code of what's inside the selected_layout
/* example :
<h3>box_two</h3>
<p>2</p>
and put it in someVariable.
*/
// and put in into textarea (all this need to happens when a radio is changed with the source code of the checked div)
var someVariable = ...
$('textarea').val(someVariable);
}
});
How can I achieve this ? How can I get the source code inside a specific div ?
First, you don't want selected_layout to be equal to: $(this).find('.selected_layout') because this already points to that element. You want it to point to the next element that comes after it.
I think this is what you are looking for:
$('input[type="radio"][name="selected_layout"]').change(function() {
if(this.checked) {
// get the index within the set of radio buttons for the radio button that was clicked
var idx = $("[type=radio][class=selected_layout]").index(this);
// Get the div structure that corresponds to the same index
var test = $("[class^='box_']")[idx];
// Now, just make that the value of the textarea
$('textarea').val(test.innerHTML);
}
});
textarea { width:100%; height:75px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<label class="tp_box_1">
<input type="radio" name="selected_layout" id="sl1" class="selected_layout" value="layout_1">
<div class="box_1">
<h3>box_one</h3>
<p>1</p>
</div>
</label>
<label class="tp_box_2">
<input type="radio" name="selected_layout" id="sl2" class="selected_layout" value="layout_2">
<div class="box_2">
<h3>box_two</h3>
<p>2</p>
</div>
</label>
<textarea id="mytextarea"></textarea>
<input id="submit_form" type="button" value="Send">
</form>
Create div element with:
Template inside
class or id for identifying
Set inputs' value to desired template class/id, then on input change find the template element base on input's value and extract the innerHTML of it by using jQuery's .html() method. Then put this HTML as an new value of textarea using also the.html() method on textarea element.
HTML:
<div id="template1" style="display:none;">
<h1>Hi!</h1>
</div>
<input type="radio" onchange="findTemplate(event)" value="template1" />
<textarea class="texta"></textarea>
jQuery:
var findTemplate = function(event) {
var target = $(event.target);
var templateName = target.val();
var template = $("#"+templateName);
var template = template.html();
var textarea = $(".texta");
textarea.html(template);
};
Working fiddle: https://jsfiddle.net/rsvvx6da/1/
i have multi div with same class name and each div have multi element(input,select and ...). Now i want to add event to input element. how to find the div index when input event run?
<div class="container">
<div class='item'>
<input type="text" ng-click='test()'>
<input type="text" >
<input type="text" ng-click='test()'>
</div>
<div class='item'>
<input type="text" ng-click='test()'>
<input type="text" >
<input type="text" ng-click='test()'>
</div>
<div class='item'>
<input type="text" ng-click='test()'>
<input type="text" >
<input type="text" ng-click='test()'>
</div>
</div>
Given the comments on your original post, my understanding of your desired functionality is this: when a user types into an input element, identify the div element that is the input's container, and alert() the div element's class attribute.
In order to do this, as I said in the comment on your post, you can use jQuery's parent() method, which will return an element's parent as a jQuery object, and then use jQuery's attr() method to inspect the parent's class attribute.
JSFiddle
If you are using jQuery:
$(document).on('keyup', '.container input', function() {
var $inputElement = $(this); // `this` is the event target
var $parentDiv = $inputElement.parent();
var parentClassName = $parentDiv.attr('class');
alert(parentClassName);
});
If you are not using jQuery:
var inputElements = document.querySelectorAll('.container input');
for(var i = 0; i < inputElements.length; i++) {
inputElements[i].addEventListener('onkeyup', function(evt) {
var inputElement = evt.target; // access event target using `evt.target`
var parentDiv = inputElement.parentNode; // get the event target's parent element
alert(parentDiv.className);
});
}