Event Delegation in identical divs - javascript

I am very new to event delegation and I'm having trouble selecting the correct div to change. I have a partial view that can be displayed multiple times on a webpage. However, when it is displayed multiple times, the JavaScript only works for the first instance of the partial view. So I tried to use event delegation to solve my problem but it still only works on the first instance. I think it might be anytime I select by Id, since they share ids, it is selecting only the first id it sees and thus only working on the first instance of the partial view. Here is my Partial View's HTML:
<div id="AddMedia">
<form>
<div class="container">
<div class="form-row">
<div class="col-6 dropdown my-2 px-0">
<label class="control-label">Source:<span class="text-danger ml-1">*</span></label>
<select id="SourceFromSelect" asp-for="Medias.SourceFrom" asp-items="Html.GetEnumSelectList(typeof(SourceFromEnum))" style="width:85%;" class="btn border-dark" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<option class="dropdown-item" selected>Select</option>
</select>
<span asp-validation-for="Medias.SourceFrom" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<div class="col-5">
<div id="MediaFile" class="form-group">
<label for="exampleFormControlFile1">Pick a File</label>
<input type="file" class="form-control-file" id="exampleFormControlFile1">
</div>
<div id="MediaLink" class="form-group">
<label for="url">Link the Media</label>
<input type="url" class="form-control" id="exampleFormControlFile1">
</div>
</div>
</div>
</div>
</form>
</div>
And here is the script for it:
document.getElementById("MediaFile").style.display = "none";
const addMedia = document.querySelector("#AddMedia")
addMedia.addEventListener('change', function (e) {
if (e.target.getAttribute('id') === 'SourceFromSelect') {
changeFile(e);
}
});
function changeFile(e) {
// $("#SourceFromSelect").change(function () {
console.log(e.target)
var e = document.getElementById("SourceFromSelect");
var strUser = e.options[e.selectedIndex].text;
if (strUser == "Phone or Computer") {
document.getElementById("MediaFile").style.display = "inline-block";
document.getElementById("MediaLink").style.display = "none";
}
else {
document.getElementById("MediaFile").style.display = "none";
document.getElementById("MediaLink").style.display = "inline-block";
}
// })
}
Finally here is where I call the Partial view:
<div id="MediaList">
#for (i = 0; i < MediaCount; ++i)
{
<partial name="_MediaPartial" />
}
</div>

As #AlwaysHelping said in comment, Id selector MUST be unique for element. since you can not change their id, you can use name or class selector.
I made a demo based on your codes which change the id to name in partial. Also, I use jquery, it is much easier.
Partial view:
<div name="AddMedia">
<form>
<div class="container">
<div class="form-row">
<div class="col-6 dropdown my-2 px-0">
<label class="control-label">Source:<span class="text-danger ml-1">*</span></label>
<select name="SourceFromSelect" style="width:85%;" class="btn border-dark">
<option selected>Select</option>
<option value="1">Phone or Computer</option>
<option value="2">Other Media</option>
</select>
</div>
</div>
<div class="form-row">
<div class="col-5">
<div name="MediaFile" class="form-group">
<label for="exampleFormControlFile1">Pick a File</label>
<input type="file" class="form-control-file" name="exampleFormControlFile1">
</div>
<div name="MediaLink" class="form-group">
<label for="url">Link the Media</label>
<input type="url" class="form-control" name="exampleFormControlFile1">
</div>
</div>
</div>
</div>
</form>
</div>
Scripts:
<script>
$("[name = MediaFile]").css("display", "none")
$("[name = SourceFromSelect]").on('change', function () {
var parent = $(this.parentElement.parentElement.nextElementSibling)
if ($(this).find(":selected").text() == "Phone or Computer") {
parent.find("[name = MediaFile]").css("display", "inline-block");
parent.find("[name = MediaLink]").css("display", "none");
}
else {
parent.find("[name = MediaFile]").css("display", "none");
parent.find("[name = MediaLink]").css("display", "inline-block");
}
});
</script>
Result:

Related

How can i put a form inside a div and see question by questions

i have a form with 13 questions but i would like to put it inside a small div, so i can see first the question 1, with an right arrow go to question 2, then to question 3. With a left arrow go back to last question.
I am new with this so i would appreciate your help. Thanks
This is a piece of my form and my sad try
Iam using back-1 back-2 to exchange background images
$(".right-arrow").on('click', () => {
$("#interview-map").attr("hidden", "")
$(".titulo").attr("hidden", "")
$(".fuentestyle").removeAttr('hidden')
$(".container").removeClass("back-1").addClass("back-2")
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container back-1 py-3 h-100">
<div class="location-container col-12">
<label for="inputAddress2" class="titulo form-label">¿Whats your address? </label>
<div id="interview-map" class="row">
<div class="locate">
<p>show my position</p>
<input id="track" type="checkbox" />
</div>
</div>
<img class="right-arrow" src="assets/img/right_arrow.png" alt="">
</div>
<div class="col-md-12">
<form id="form_interview" class="col-lg-12 row g-3 mx-10 my-10">
<div id="interview-address" class="fuentestyle col-12" hidden>
<label for="referencia" class="form-label">Add your address: </label>
<input type="text" class="form-control" id="referencia" placeholder="Reference">
</div>
<div class="mb-3" hidden>
<label for="disabledSelect" class="form-label">¿Question fuente?</label>
<select id="fuente" class="form-select form-select-sm" aria-label=".form-select-sm example">
<option id="fuente-0" selected class="form-control"></option>
<option id="fuente-1" value="1"></option>
<option id="fuente-2" value="2"></option>
<option id="fuente-3" value="3"></option>
<option id="fuente-4" value="4"></option>
</select>
</div>
<div class="mb-3" hidden>
<label for="disabledSelect" class="form-label">Question construido</label>
<select id="construido" class="form-select form-select-sm" aria-label=".form-select-sm example">
<option id="construido-0" selected class="form-control"></option>
<option id="construido-1" value="1"></option>
<option id="construido-2" value="2"></option>
</select>
</div>
<div class="col-12" hidden>
<label for="dias_agua" class="form-label">Question dias_agua </label>
<input type="text" class="form-control" id="dias_agua" placeholder="Enter a number">
</div>
<div class="col-12" hidden>
<label for="horas_agua" class="form-label">Question horas_agua </label>
<input type="text" class="form-control" id="horas_agua" placeholder="Enter a number to 24">
</div>
Personally I would try to make my application more data driven, but if you cannot change the form itself, then you could do something like this...
let index = 1;
function back() {
index--;
update();
}
function next() {
index++;
update();
}
function update() {
// Find all questions
const questions = document.querySelectorAll("[id^='question-']");
// Hide all questions
questions
.forEach(question => {
question.style.display = "none";
});
// Show the active question
const activeQuestion = document.getElementById("question-" + index);
if (activeQuestion != null)
activeQuestion.style.display = "block";
// Hide/Show the buttons according to which question is being shown
document.getElementById("back").style.display = index <= 1 ? "none" : "block";
document.getElementById("next").style.display = index >= questions.length ? "none" : "block";
}
update();
<div id="question-1">Question 1</div>
<div id="question-2">Question 2</div>
<div id="question-3">Question 3</div>
<div id="question-4">Question 4</div>
<div id="question-5">Question 5</div>
<button id="back" onclick="back()">Back</button>
<button id="next" onclick="next()">Next</button>
Note:
The solution above uses native javascript (jQuery is not necessary).
This code could be written more efficiently, for example you don't really have to query for all questions on each update. Instead, you could do this once when the page is loaded.

i add show and hide in modal component and it doesn't work

I'm using Asp.NetCore, C#,Ajax javascript and jquery .I created a Model Component in my application.
the model component is shown but the hidden element didn't show. when I choose my option in the Axe option it doesn't show any one of the GRaison / DRaison / PRaison / CRaison. I try it with "show" and doesn't work even I set the option: selected and doesn't work too. I don't have any idea to make this code work
here's the page :
#model Segment
<div class="modal fade" id="addSegment">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-primary text-uppercase text-white" style="height:5%;">
<h5 class="modal-title" id="addSegmentLabel">Create Segment</h5>
<button type="button" class="btn-close" data-dismiss="modal" aria-label="Close">
<span>x</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<label asp-for="SName" class="control-label">Name : </label>
<div class="col-md-12">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<input asp-for="SName" class="form-control" placeholder="Enter segment name" />
<span asp-validation-for="SName" class="text-danger"></span>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group ">
<label asp-for="SRang" class="control-label">Rang</label>
<input asp-for="SRang" class="form-control" />
<span asp-validation-for="SRang" class="text-danger"></span>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label asp-for="SType" class="control-label">Type</label>
<select asp-for="SType" class="form-control" id="SType">
<option selected disabled>Selectionnez type..</option>
<option id="Compte">Compte</option>
<option id="Contact">Contact</option>
</select>
<span asp-validation-for="SType" class="text-danger"></span>
</div>
</div>
<div class="col-md-12">
<div class="form-group ">
<label asp-for="Description" class="control-label"></label>
<textarea class="form-control" rows="3"></textarea>
<span asp-validation-for="Description" class="text-danger"></span>
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<label asp-for="Axe" class="control-label"></label>
<select asp-for="Axe" class="form-control" id="Axeya ij" asp-items="Html.GetEnumSelectList<Axe>()">
<option value="null" selected>Selectionnez Axe..</option>
</select>
<span asp-validation-for="Axe" class="text-danger"></span>
</div>
<div class="form-group" id="g" hidden>
<label asp-for="GRaison" class="control-label">Raison</label>
<select asp-for="GRaison" class="form-control">
<option> Personalité </option>
<option> Soucis</option>
<option> Intérêt</option>
<option>Valeurs</option>
</select>
<span asp-validation-for="GRaison" class="text-danger"></span>
</div>
<div class="form-group" id="d" hidden>
<label asp-for="DRaison" class="control-label">Raison</label>
<select asp-for="DRaison" class="form-control">
<option> Age </option>
<option> Sexe</option>
<option> Education</option>
<option> Revenu</option>
</select>
<span asp-validation-for="DRaison" class="text-danger"></span>
</div>
<div class="form-group" id="p" hidden>
<label asp-for="PRaison" class="control-label">Raison</label>
<select asp-for="PRaison" class="form-control">
<option> Personalité, </option>
<option> Soucis</option>
<option> Intérêt</option>
<option>Valeurs</option>
</select>
<span asp-validation-for="PRaison" class="text-danger"></span>
</div>
<div class="form-group" id="c" hidden>
<label asp-for="CRaison" class="control-label">Raison</label>
<select asp-for="CRaison" class="form-control">
<option> Pays</option>
<option> Ville</option>
<option> Language</option>
<option> Population</option>
</select>
<span asp-validation-for="CRaison" class="text-danger"></span>
</div>
</div>
</div>
</form>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-save="modal">Save changes</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
#section Scripts{
<script src="~/lib/jquery/dist/jquery.js"></script>
<script type="text/javascript">
$(function () {
$("#SType").change('pageload', function () {
if ($(this).val() == "Contact") {
$(function () {
$("#Axe").change('pageload', function () {
if ($(this).val() == 0) {
$("#g").removeAttr('hidden');
$("#p,#c,#d").hide();
} else if ($(this).val() == 1) {
$("#p").removeAttr('hidden');
$("#g,#c,#d").hide();
} else if ($(this).val() == 2) {
$("#c").removeAttr('hidden');
$("#p,#g,#d").hide();
} else {
$("#d").removeAttr('hidden');
$("#p,#c,#g").hide();
}
});
});
} else {
$("#g,#p,#c,#d").hide();
}
});
});
</script>
}
when I choose my option in the Axe option it doesn't show any one of the GRaison / DRaison / PRaison / CRaison. I try it with "show" and doesn't work even I set the option: selected and doesn't work too.
Firstly, we can find that you set id="Axeya ij" for select in your code as below, which would cause you can not get that element using $("#Axe").
<select asp-for="Axe" class="form-control" id="Axeya ij" asp-items="Html.GetEnumSelectList<Axe>()">
Secondly, if you check the source code of your hidden element after you run .hide() method, you can find it would help add style="display: none;" inline style to the element(s), it does not add hidden attribute.
To fix the issue and achieve your requirement, you can try to modify the code like below.
$(function () {
$("#SType").change('pageload', function () {
if ($(this).val() == "Contact") {
$("select[name='Axe']").change('pageload',function () {
if ($(this).val() == 0) {
$("#g").removeAttr('hidden');
$("#g").show();
$("#p,#c,#d").hide();
} else if ($(this).val() == 1) {
$("#p").removeAttr('hidden');
$("#p").show();
$("#g,#c,#d").hide();
} else if ($(this).val() == 2) {
$("#c").removeAttr('hidden');
$("#c").show();
$("#p,#g,#d").hide();
} else {
$("#d").removeAttr('hidden');
$("#d").show();
$("#p,#c,#g").hide();
}
});
} else {
$("#g,#p,#c,#d").hide();
}
});
});

Hide closest row anchor tag jquery

I have multiple div with class rows and in each row there is a dropdown on change of dropdown i want to hide the anchor tag with class "add_marks" which is inside the same row.
I'm using the following code to hide it:
jQuery(document).on('change', '.subject', function(e) {
var nearest_row = $(this).closest('div.row');
var elem = $(nearest_row).closest(".add_marks");
elem.hide();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<div class="row clearfix attr_fields">
<div class="col-sm-3">
<div class="form-group">
<h2 class="card-inside-title">Class</h2>
<div class="form-line focused">
<input type="text" name="name" class="form-control" required="">
</div>
</div>
</div>
<div class="col-sm-3">
<div class="form-group">
<h2 class="card-inside-title">Subject</h2>
<select name="subject_name" class="form-control subject" required="" aria-invalid="false">
<option value="">Select</option>
<option value="1">Maths</option>
<option value="2">Science</option>
</select>
</div>
</div>
</div>
<div class="col-sm-1">
<div class="form-group">
<div class="col-xs-1 col-sm-7 col-md-1"><i class="material-icons">add</i>Add Marks</div>
</div>
</div>
You have to get the next div and find the a link, then hide it.
var nearest_row = $(this).closest('div.row');
gets you the div.row.clearfix.attr_fields but the link is present in the next div, so doing next gets you the next div element, then you find the 'a' element.
You can also do next('div') instead of getting the next element to find the next div.
jQuery(document).on('change', '.subject', function(e) {
var nearest_row = $(this).closest('div.row').next().find('.add_marks').hide();
//console.log(nearest_row);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<div class="row clearfix attr_fields">
<div class="col-sm-3">
<div class="form-group">
<h2 class="card-inside-title">Class</h2>
<div class="form-line focused">
<input type="text" name="name" class="form-control" required="">
</div>
</div>
</div>
<div class="col-sm-3">
<div class="form-group">
<h2 class="card-inside-title">Subject</h2>
<select name="subject_name" class="form-control subject" required="" aria-invalid="false">
<option value="">Select</option>
<option value="1">Maths</option>
<option value="2">Science</option>
</select>
</div>
</div>
</div>
<div class="col-sm-1">
<div class="form-group">
<div class="col-xs-1 col-sm-7 col-md-1"><i class="material-icons">add</i>Add Marks</div>
</div>
</div>
Here is Working code example run it with js (shortcut: ctrl + enter)
...want to hide the anchor tag with class "add_marks" which is inside the same row.
So I have moved that button inside row.
Using .col* as direct child of .row is proper way of using bootstrap grid.
Used the following jQuery considering your requirement.
jQuery(document).on('change', '.subject', function (e) {
$(this)
.parents('.row')
.find('.add_marks')
.hide();
});

javascript - how to fade in div class

I want to fade in a div class when a click action is made. But it's not working.
the picture above is produced by function gotData.
function gotData(data) {
var jobs = data.val();
var keys = Object.keys(jobs);
var container = document.getElementById('Jobcontainer');
var container2 = document.getElementById('jobpackage');
for (var i = 0; i<keys.length; i++) {
var k = keys[i];
var newCard = `
<li class="pos-card" id="Jobcontainer">
<div class="content">
<div class="title">`+jobs[k].JobTitle+`</div>
<div class="date">April 21</div>
<div class="refer">Refer</div>
</div>
<ul class="desc">
<li>`+ jobs[k].JobSummary + `</li>
</ul>
</li>`;
container.innerHTML += newCard;
}
}
in the same file html tag I have this html code
<div class="return">Return to listings </div>
<div class="container refer-card">
<div class="modal confirmed"><span class="close-modal"></span>
<h2>Thank you!</h2>
<p><span id="refer_name" class="focus"></span> has been submitted for the <span id="refer_pos" class="focus"></span> position.</p>
</div>
<div class="sign-up card">
<div class="card__header">
<h1>Employee Referral</h1>
<div class="description">For more information, please consult the employee handbook.</div>
</div>
<div class="card__content">
<form class="referral" method="post">
<div class="field line">
<input class="req" maxlength="240" type="text" name="name" value="" required="required" id="name"/>
<label class="placeholder" for="name">Full Name</label>
</div>
<div class="field line">
<input class="req" maxlength="240" type="email" name="email" value="" required="required" id="email"/>
<label class="placeholder" for="email">Email</label>
</div>
<div class="field line inline">
<input class="req" maxlength="240" type="text" name="position" value="" required="required" id="position"/>
<label class="placeholder" for="position">Position</label>
</div>
<!-- <div class="field inline right"><span class="dropdown-wrapper">
<select class="empty" name="department" id="choice">
<option value="" selected="selected">Department</option>
<option value="1">Development</option>
<option value="2">Sales</option>
<option value="3">QA</option>
<option value="4">Design</option>
<option value="5">HR</option>
<option value="6">Research </option>
</select></span></div> -->
<div>
<input type="submit" value="Submit" disabled="disabled" id="btn"/>
</div><a class="reset" href="#">Reset </a>
</form>
</div>
</div>
</div>
I am attempting to use the JS function below to fade in refer-card in the html tag when "refer" in picture above is clicked but for some unknown reasons nothing is happening and no error is displayed. Can you help figure out what I'm doing wrong or missing?
$('.refer').click(function(e){
e.stopPropagation();
$('.positions').addClass('fadeOut');
$('.refer-card').addClass('show');
$('.return').fadeIn('fast');
});
Try this codepen (http://codepen.io/anon/pen/gmdgmv)
Perhaps you have not defined jQuery, as it seems to work with a sample job block I put in place, and the basic CSS to hide the element you are trying to fade in. Also, bear in mind that if you've hidden it with '!important' in your CSS then the fade in will not work.
I added a console.log('clicked'); to your click handler verify that the block is executing.
It might be because you've called the [gotData] method that would append the html tag with the 'refer' class in play thus by that time, (refer) class didnt register or bind the [click] event handler after loading the DOM
In this case, you need to attach / bind them beforehand using (on) or (delegate) method (If you want to apply this in jQuery)
Using (on) method:
$('.refer').on('click', function(event) {
$('.positions').addClass('fadeOut');
// rest of code
});
Using (delegate) method:
$(document).delegate('.refer', 'click', function(event) {
$('.positions').addClass('fadeOut');
// rest of code
});
Hope this helps for your case.

Add/Remove button not working on duplicated form fields - jquery

I have used the code from the following answer: jquery clone form fields and increment id to created a clone-able area of my form and all is working well except for the "Add another" and "Remove row" button.
Only the original clone-able areas Add / Remove buttons work so the next cloned area's add / remove buttons don't do anything meaning you have use the first row's which is confusing.
I really can't see what is going on. Any help would be greatly appreciated!
The HTML:
<div id="previous-jobs">
<div class="panel-group" id="accordion">
<div id="clonedInput1" class="clonedInput panel panel-default">
<div class="panel-heading clearfix">
<h4 class="panel-title pull-left">
<a class="heading-reference accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse1">
Entry #1
</a>
</h4>
<div id="action-buttons" class="pull-right">
<button type="button" class="btn btn-success clone">Add another</button>
<button type="button" class="btn btn-danger remove">Delete Row</button>
</div>
</div>
<div id="collapse1" class="input-panel panel-collapse collapse">
<div class="panel-body">
<div class="row">
<div class="form-group col-sm-6">
<label class="p-date-from-title input-title" for="p-date-from">Date From</label>
<input type="text" class="ci-df form-control" id="p-date-from1" name="p-date-from" value="[[+!fi.p-date-from]]" placeholder="Date from">
</div>
<div class="form-group col-sm-6">
<label class="p-date-to-title input-title" for="p-date-to">Date To</label>
<input type="text" class="ci-dt form-control" id="p-date-to1" name="p-date-to" value="[[+!fi.p-date-to]]" placeholder="Date to">
</div>
</div>
<div class="form-group">
<label class="p-employer-title input-title" for="p-employer">Employer</label>
<input type="text" class="ci-em form-control" id="p-employer1" name="p-employer" value="[[+!fi.p-employer]]" placeholder="Employer">
</div>
<div class="form-group">
<label class="p-position-title input-title" for="p-position">Position</label>
<input type="text" class="ci-po form-control" id="p-position1" name="p-position" value="[[+!fi.p-position]]" placeholder="Position">
</div>
<div class="form-group">
<label class="p-salary-title input-title" for="p-salary">Salary</label>
<input type="text" class="ci-sa form-control" id="p-salary1" name="p-salary" value="[[+!fi.p-salary]]" placeholder="Salary">
</div>
<div class="form-group">
<label class="p-full-part-time-title input-title" for="p-full-part-time">Full/Part Time</label>
<select class="ci-fpt form-control" id="p-full-part-time1" name="p-full-part-time" value="[[+!fi.p-full-part-time]]">
<option value="Full Time">Full Time</option>
<option value="Part Time">Part Time</option>
</select>
</div>
<div class="form-group">
<label class="p-leaving-reason-title input-title" for="p-leaving-reason">Reason for Leaving</label>
<input type="text" class="ci-rfl form-control" id="p-leaving-reason1" name="p-leaving-reason" value="[[+!fi.p-leaving-reason]]" placeholder="Reason for leaving">
</div>
</div>
</div>
</div>
</div>
The jQuery:
var regex = /^(.*)(\d)+$/i;
var cloneIndex = $(".clonedInput").length;
$("button.clone").click(function(){
cloneIndex++;
$(this).parents(".clonedInput").clone()
.appendTo("#accordion")
.attr("id", "clonedInput" + cloneIndex)
.find("*").each(function() {
var id = this.id || "";
var match = id.match(regex) || [];
if (match.length == 3) {
this.id = match[1] + (cloneIndex);
this.name = match[1] + (cloneIndex);
}
$(this).find('.heading-reference').attr("href", "#collapse" + cloneIndex).html('Entry #' + cloneIndex);
});
});
$("button.remove").click(function(){
$(this).parents(".clonedInput").remove();
});
For dynamically added elements, use .on() jQuery documentation .on() (For jQuery 1.7 and above)
In the example you posted, they used .live() which is for jQuery 1.7 and below.
Add this outside of any $(document).ready() function:
$(document).on('click', 'button.clone', function(){
...
});
By doing this, the event handler gets added to the document so any time an event bubbles up to it that originated from a button.clone element, it will trigger that function. So when buttons get added after the page is loaded, they will still trigger the click event, even when they weren't available when the page initially loaded.
If you just use $('button.clone').click(...) only the buttons that are on the page when it is first loaded will trigger the click event.

Categories