Find the nearest id in javascript - javascript

I have two divs
<div class="maca">
<input type="hidden" value="1">
<div onclick="removeInput(nearest input type hidden)">Remove</div>
</div>
<div class="maca">
<input type="hidden" value="1">
<div onclick="removeInput(nearest input type hidden)">Remove</div>
</div>
I want to send as a parameter the value of nearest input type hidden of that div that we are clicking on

Im not 100% sure what you mean with nearest but with this you get the input hidden inside the div. By the way you could also put the element.parentNode.querySelector into the onclick but personally i like it more to split HTML and JS.
function removeInput(element){
let value = element.parentNode.querySelector("input[type='hidden']").value;
console.log(value);
}
<div class="maca">
<input type="hidden" value="1">
<div onclick="removeInput(this)">Remove</div>
</div>
<div class="maca">
<input type="hidden" value="5">
<div onclick="removeInput(this)">Remove</div>
</div>

You can send the event as a parameter to a javascript function and then find the input via the parentNode. This isn't a literal interpretation of your question since faithfully the "nearest" element is rather complex and probably not what you're looking for.
function removeInput(e) {
const nearestInput = e.target.parentNode.querySelector("input[type='hidden']");
console.log(nearestInput);
}
<div class="maca">
<input type="hidden" value="1" />
<div onclick="javascript:removeInput(event)">Remove</div>
</div>
<div class="maca">
<input type="hidden" value="1" />
<div onclick="javascript:removeInput(event)">Remove</div>
</div>

You should not use inline event listeners, which are widely considered bad practice.
Instead, use addEventListener to add the click listeners, and find the input (given your markup structure is fix like you've shown) using previousElementSibling:
for (const remover of document.querySelectorAll('.remove-input')) {
remover.addEventListener('click', () => remover.previousElementSibling.remove(), { once: true });
}
<div class="maca">
<input type="hidden" value="1" />
<div class="remove-input">Remove</div>
</div>
<div class="maca">
<input type="hidden" value="1" />
<div class="remove-input">Remove</div>
</div>

Related

Prevent input to get cleared when the parend is modified

Can I have some inputs on this ?
Issue
When a form or a parent element of a form is modified, the text that was typed inside the inputs of the form get cleared. As this snipper show :
function modifyParent() {
document.getElementById("parent").innerHTML += "<br>a line get added";
}
<div id="parent">
<form>
<input type="text" id="child">
</form>
<button type="button" onclick="modifyParent()">click</button>
</div>
Hello everyone,
Solution 1
I found a first esay way to prevent it if I know where the parent is modified. As this snipper show
function modifyParent() {
var child = document.getElementById("child");
child.setAttribute("value", child.value)
document.getElementById("parent").innerHTML += "<br>a line get added";
}
<div id="parent">
<form>
<input type="text" id="child" value="">
</form>
<button type="button" onclick="modifyParent()">click</button>
</div>
This solution look great, but only if i know where ans when the parent is modified. Also if i have a multiple inputs i need to loop on document.getElementsByTagName("input").
Solution 2
Since i dont know how many buttons i have and how many inputs, this is my best solution so far :
function modifyParent() {
setInputValues();
document.getElementById("parent").innerHTML += "<br>a line get added";
}
function setInputValues() {
for (var c of document.getElementsByTagName("input"))
c.setAttribute("value", c.value);
}
<div id="parent">
<form>
<input type="text" value="">
<input type="text" value="">
<input type="text" value="">
<input type="text" value="">
</form>
<button type="button" onclick="modifyParent()">click</button>
</div>
It work well for multiple inputs but i have to call the setInputValues() function before i modify any parent everytime. I started to consider to add setInterval on this function but I stop here because i'm starting to go a bit far and it's very likely that their is a better way.
Any help will be apreciated
A cleaner solution is to use a new element for the messages. This way you can set the messages inside a container without messing with the inputs.
const messageBox = document.querySelector(".messages");
function modifyParent() {
messageBox.innerHTML += "<br>a line get added";
}
<div id="parent">
<form>
<input type="text" value="">
<input type="text" value="">
<input type="text" value="">
<input type="text" value="">
</form>
<button type="button" onclick="modifyParent()">click</button>
<div class="messages"></div>
</div>
Another quick notice, innerHTML is vulnerable for XSS attacks Try using createElement and appendChild if possible.
const parent = document.getElementById("parent");
function modifyParent() {
const br = document.createElement("br");
const text = document.createTextNode("a line get added");
parent.appendChild(br);
parent.appendChild(text);
}
<div id="parent">
<form>
<input type="text" value="">
<input type="text" value="">
<input type="text" value="">
<input type="text" value="">
</form>
<button type="button" onclick="modifyParent()">click</button>
<div class="messages"></div>
</div>

Why is my checkbox on change not working (AJAX)

This is how my razor code looks like
<form asp-action="Save" asp-controller="ClassesHeld" method="post">
<input asp-for="ClassHeldId" value="#Model.ClassHeldId" hidden />
<div class="form-group">
<label>Student</label>
<input asp-for="#Model.Student" value="#Model.Student" class="form-control" readonly />
</div>
<div class="form-group">
<label>Grade</label>
<input id="Grade"asp-for="Grade" type="number" value="#Model.Grade" class="form-control" min="0" max="5" />
</div>
<div class="form-group">
<label>Attendance</label>
<input id="Attendance" class="form-check-input" asp-for="Attendance" type="checkbox"/>
</div>
<button class="btn btn-primary" type="submit" value="Save">Save</button>
</form>
<script>
$("#Attendance").on("change", function () {
$("#Grade").attr("disabled", this.checked);
});
</script>
Yet for some reason, clicking on the checkbox does nothing at all. I have tried this with simple script as well, and that didn't work either.
document.getElementById('Attendance').onchange = function () {
document.getElementById('Grade').disabled = this.checked;
};
Neither of these worked.
I have even copied some solutions from here (one of them is that last simple scrip with document.getElementbyId, and none of it worked. I have to be missing something simple, but I've been looking at this for the past hour and I still can't figure it out.
I apologize if the question is stupid or noob-level. But I am getting desperate.
EDIT: Simply to add more information, this form works perfectly fine when submitting data, controller saves the stuff to the database... Everything works fine, just not the part where it disables the ability to edit the Grade if the student has not attended.
So the objective, is to disable the input field when the checkbox for "attendance" is checked
The .attr() method only manage string; So if you want to change an attribut like disabled or even checked with a boolean or something else, you have to use the prop method.
For more information check this post :
.prop() vs .attr()
You can execute the snippet below.
$("#Attendance").on("change", function () {
$("#Grade").prop("disabled", this.checked)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form asp-action="Save" asp-controller="ClassesHeld" method="post">
<input asp-for="ClassHeldId" value="#Model.ClassHeldId" hidden />
<div class="form-group">
<label>Student</label>
<input asp-for="#Model.Student" value="#Model.Student" class="form-control" readonly />
</div>
<div class="form-group">
<label>Grade</label>
<input id="Grade"asp-for="Grade" type="number" value="#Model.Grade" class="form-control" min="0" max="5" />
</div>
<div class="form-group">
<label>Attendance</label>
<input id="Attendance" class="form-check-input" asp-for="Attendance" type="checkbox"/>
</div>
<button class="btn btn-primary" type="submit" value="Save">Save</button>
</form>
<script>
</script>
I think you actually need to remove the disabled attribute when you don't want it. Maybe try this:
$(document).ready(function() {
$("#Attendance").on("change", function () {
if (this.checked) {
$("#Grade").attr("disabled", true);
} else {
$("#Grade").removeAttr("disabled");
}
});
});

How can I add a div around two elements yourself using JQuery? [duplicate]

How would I go about using wrap() to wrap multiple elements (with different classes) inside a <div>?
For example, on the form I'm working on there is a big list of checkbox inputs and labels in the form of:
<input>
<label>
<input>
<label>
etc
I'm wanting to wrap a <div> around the input and label, so the result would be:
<div>
<input>
<label>
</div>
<div>
<input>
<label>
</div>
Thanks!
You can use the .wrapAll() method.
$('form > input').each(function(){
$(this).next('label').andSelf().wrapAll('<div class="test"/>');
});
If your markup has always the exact same order, I'd prefer to use:
var $set = $('form').children();
for(var i=0, len = $set.length; i < len; i+=2){
$set.slice(i, i+2).wrapAll('<div class="test"/>');
}
Should be significant faster.
Ref.: .wrapAll(), .andSelf(), .slice()
$('input+label').each(function(){
$(this).prev().andSelf().wrapAll('<div>');
});​
If you have something like this:
<input id="input1">
<label id="label1">
<input id="input2">
<label id="label2">
Then you can use jQuery:
jQuery("#input1").next().andSelf().wrapAll('<div id="newDiv" />');
jQuery("#input2").next().andSelf().wrapAll('<div id="newDiv" />');
and get this:
<div id="newDiv">
<input id="input1">
<label id="label1">
</div>
<div id="newDiv">
<input id="input2">
<label id="label2">
</div>
Worked for me :-)
jQuery function wrapAll allows you to wrap multiple elements but if you have a DOM like you wrote then it won't work too well as you can't easily match a part of label and input with a selector. I suggest adding some classes to each part and then using wrapAll.
<input class="i1"/>
<label class="i1"/>
<input class="i2"/>
<label class="i2"/>
$('.i1').wrapAll('<div/>');
$('.i2').wrapAll('<div/>');
This will give you
<div>
<input class="i1"/>
<label class="i1"/>
</div>
<div>
<input class="i2"/>
<label class="i2"/>
<div>

jQuery remove selected element, dynamically generated

I have a form and I can dynamically add more lines but if I try to remove a specific line it does not work, however the first line gets removed with no problem.
Here is the html:
<form class="order-form">
<div class="product-lines">
<!-- Product Line Section -->
<div class="product-line">
<img alt="remove" src="img/close.png" />
<input class="input-text" name="product-code" type="text" placeholder="Product Code" ></input>
<input class="input-text" name="product-quantity" type="text" placeholder="Quantity"></input>
<input class="input-text" name="product-discript" type="text" placeholder="Discription of Product"></input>
<label class="label-sign">£</label>
<input class="input-text" name="product-price" type="text" placeholder="RRP Price"></input>
<br>
</div>
</div>
<div id="product-btn">
<input name="btn-add-line" type="button" value="Add new line"></input>
<input name="btn-update" type="button" value="Update"></input>
<input name="btn-submit" type="submit" value="Submit Order"></input>
<label class="label-sign">£</label>
<input class="input-text" name="order-info" type="text" placeholder="Order total" ></input>
</div>
</form>
The jQuery code I have tried:
$(".btn-close").on("click", function(e){
$(e.currentTarget).parent().remove();
});
I've also Tried
$(e.currentTarget).parents("div.product-lines).next("div.product-line).remove();
Any help would be most appreciated, also a explanation would be very helpful for me to learn.
Try something like
$(".product-lines").on("click", ".btn-close", function(e){
$(e.currentTarget).parent().remove();
});
You cannot attach events to objects that are not currently on page (lines).
You have to attach click event on product-lines object and when it is clicked you delegate event to "closest" product-line object!
You will need to changed the jQuery slightly to allow for Event Delegation. This means all elements added in future will get the event attached to them too.
$(document).on("click", ".btn-close", function(e){
$(e.currentTarget).parent().remove();
});
$('body').on('click','button id/class',function(){
$(e.currentTarget).parent().remove();
});
but if u use this code it will remove <div class="product-line">...</div>
why you want to remove this div.
i dont get your question very well. Explain in details and step by step .

Jquery how to check checkbox on div click, change class and show div

I am trying to checkbox when the div.menuitem is clicked and then it should change class and show the content in the div with class of hidediv. When the div.menuitem is again clicked it should remove the class and hide the div again and uncheck the checkbox.
Want I want to do:
Only show the content of the hidediv when the menuitem is pressed. (checkbox should be checked)
When the menuitem is pressed the checkbox should be checked
When the menuitem is clicked again the hidediv should be hidden again. (checkbox unchecked)
And the checkbox should be uncheched
Illustration of my menu form:
<div class="menuitem">
1.Company1
</div>
<div class="hidediv">
1.1 Company 1.1
1.2 Company 1.2
</div>
<div class="menuitem">
1.Company2
</div>
<div class="hidediv">
1.1 Company 2.1
1.2 Company 2.2
</div>
My previous Jquery code, which only is trigger when the checkbox is clicked. I want pretty
similar function to this, the checkbox should also be trigghed when the div is clicked:
$('.menuitem input:checkbox').change(function(){
if($(this).is(':checked')) {
$('div.hidediv').addClass('someclass').show(200); // not needed it there is another way of identifying the div later to add to hidediv class again.
$('div.hidediv').removeClass('hidediv');
} else {
$('div.someclass').addClass('hidediv').hide(200);
}
});
});
My Jquery so far(not working):
$('.menuitem').click(function(e){
$(this).addClass('menuclicked');
$('div.hidediv').addClass('clicked').show(200);
$('div.hidediv').removeClass('hidediv');
} else {
$('div.someclass').addClass('hidediv').hide(200);
}
$('.menuclicked').click(function(e){
$('div.someclass').addClass('hidediv').hide(200);
});
My HTML:
<form accept-charset="UTF-8" action="/" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div>
<div class="menuitem">
<label for="search_company1">company1</label>
<input name="search[company1_is_true]" type="hidden" value="0" /><input id="search_company1_is_true" name="search[company1_is_true]" type="checkbox" value="1" />
</div>
<div class="menuitem">
<label for="search_company3">company3</label>
<input name="search[company3_is_true]" type="hidden" value="0" /><input id="search_company3_is_true" name="search[company3_is_true]" type="checkbox" value="1" />
</div>
<div class="hidediv">
<div class="menuitem">
<label for="search_company2">company2</label>
<input name="search[company2_is_true]" type="hidden" value="0" /><input id="search_company2_is_true" name="search[company2_is_true]" type="checkbox" value="1" />
<div>
</div>
<input id="search_submit" name="commit" style="display:none;" type="submit" value="Submit" />
</form>
I can help. I think you are structuring this wrong. You have three fields in your html, with the third being hidden. I assume when you fill in the first one you want nothing to happen, but clicking the second one should show the third field?
Try this:
//Use toggle instead of .click()
$('.menuitem').toggle(function(){
$('div.hidediv').addClass('clicked').show(200);
}, function(){
$('div.hidediv').removeClass('clicked').hide(200);
});
This will effect all divs with the "menuitem" class, meaning when you click on any of the three it will toggle showing/hiding the div with the "hidediv" class.
edit you have a couple valid answers here, but I think you're approaching this wrong. If you go try the jsfiddle posted by another user, whos' javascript does the same as mine - it reveals the problem I talked about above. You cannot select all three boxes without some clever clicking. Each click will toggle showing/hiding the third check box. Might I suggest modifying your code like so:
//Use toggle instead of .click()
$('.toggleMenuItem').toggle(function(){
$('div.hidediv').addClass('clicked').show(200);
}, function(){
$('div.hidediv').removeClass('clicked').hide(200);
});
<form accept-charset="UTF-8" action="/" method="get">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
</div>
<div class="menuitem">
<label for="search_company1">company1</label>
<input name="search[company1_is_true]" type="hidden" value="0" />
<input id="search_company1_is_true" name="search[company1_is_true]" type="checkbox" value="1" />
</div>
<div class="menuitem toggleMenuItem">
<label for="search_company3">company3</label>
<input name="search[company3_is_true]" type="hidden" value="0" />
<input id="search_company3_is_true" name="search[company3_is_true]" type="checkbox" value="1" />
</div>
<div class="hidediv">
<div class="menuitem">
<label for="search_company2">company2</label>
<input name="search[company2_is_true]" type="hidden" value="0" />
<input id="search_company2_is_true" name="search[company2_is_true]" type="checkbox" value="1" />
<div>
</div>
<input id="search_submit" name="commit" style="display:none;" type="submit" value="Submit" />
</form>
This will make it so only clicking the checkboxes with the class ".toggleMenuItem" will show the third checkbox.
try something like this:
$('.menuitem').click(function(e){
if($(this).hasClass('menuClicked')){
// Already clicked
$(this)
.removeClass('menuclicked')
.html("");
}else{
// First click
$(this)
.addClass('menuclicked');
.html($('#hidediv').html());
}
})
This may do what you're looking for:
$('.menuitem').click(function(e){
$(this).toggleClass('clicked');
$('div.hidediv').toggle(200);
});
Let me know if it is missing a feature.
http://jsfiddle.net/citizenconn/2bCdR/

Categories

Resources