Jquery : Find only one nearest matching element - javascript

i am adding form fields dynamically using Below code
$(document).ready(function () {
var add_fields = "" +
"<div class='col-md-3 form-group pull-right'>" +
"<label>Please select a field type</label>" +
"<select name='add_fields' class='form-control' id='add_fields'>" +
"<option value=''>Please Select a value</option>" +
"<option value='text'>Text Field</option>" +
"<option value='select'>Select List</option>" +
"<option value='radio'>Radio Buttons</option>" +
"<option value='checkboxes'> Checkboxes</option>" +
"<option value='file'> File Upload</option>" +
"</select></div>";
var text_field_append= "" +
"<div class='row'>" +
"<div class='col-md-3 '>" +
"<div class='form-group'>" +
"<label>Add Field Label</label>" +
"<input type='text' name='textfield_label' class='form-control'>" +
"</div>" +
"</div>" +
"<div class='col-md-3'> " +
"<label></label><input type='text' placeholder='' name='' class='form-control field' disabled >" +
"</div>" +
"</div>";
$('#add_form').on('click',function (e) {
$('#form_holder').append(add_fields);
$('#add_fields').on('change',function () {
if($(this).val()=='text'){
$('#form_holder').append(text_field_append);
var nearest_field= $("[name='textfield_label']").closest('.row').find('.field');
$("[name='textfield_label']").on('input',function(e){
$(nearest_field).attr("placeholder", $(this).val());
var field_name =$(this).val().replace(/ /g,"_");
$(nearest_field).attr("name", field_name);
});
}
})
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col-md-12">
<h1>Please use Following wizard to generate your form </h1>
<p>Click on Add Fields to get started </p>
<a id="add_form" class="btn btn-primary pull-right">Add Fields</a>
</div>
<form id="myform">
<div id="form_holder">
</div>
</form>
now upon adding a text field i am selecting nearest added element as below:
var nearest_field= $("[name='textfield_label']").closest('.row').find('.field');
Problem with this is i want only latest added(nearest) element to be selected while it selects all the elements, Can someone please advise how can i fix it

The issue is partly due to the repeated id attributes in the dynamic content, which need to be replaced with common class attributes, and also with the nested event handlers.
To both fix the issue and improve the logic, remove all the HTML from the JS and place it within 'templates' in the HTML. Your JS should ideally contain no HTML at all as it's a violation of the Separation of Concerns principle
From there you can use delegated event handlers, bound at runtime, to handle the events on all dynamic elements. These event handlers can use DOM traversal to relate the 'label' to the relevant 'placeholder'.
Finally, note that the template for the field types uses a pattern whereby the first part of its id matches the value of the option used to append it. This way the code is extensible, and your logic can be simplified.
Try this:
jQuery($ => {
let $add_form = $('#add_form');
let $form_holder = $('#form_holder');
let add_fields = $('#fields').html();
$add_form.on('click', function(e) {
$form_holder.append(add_fields);
});
$form_holder.on('change', '.add_fields', e => {
let fieldHtml = $(`#${e.target.value}_field`).html();
$form_holder.append(fieldHtml);
});
$form_holder.on('input', '.text-field-label', e => {
let $label = $(e.target);
let labelValue = $label.val();
let $placeholder = $label.closest('.row').find('.text-field');
$placeholder.prop({
placeholder: labelValue,
name: labelValue,
value: labelValue.replace(/ /g, '_')
});
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col-md-12">
<h1>Please use Following wizard to generate your form </h1>
<p>Click on Add form to get started </p>
<a id="add_form" class="btn btn-primary pull-right">Add Form</a>
</div>
<form id="myform">
<div id="form_holder"></div>
</form>
<script type="text/html" id="fields">
<div class="col-md-3 form-group pull-right"><label>Please select a field type</label>
<select name="add_fields" class="form-control add_fields">
<option value="">Please Select a value</option>
<option value="text">Text Field</option>
<option value="select">Select List</option>
<option value="radio">Radio Buttons</option>
<option value="checkboxes">Checkboxes</option>
<option value="file">File Upload</option>
</select>
</div>
</script>
<script type="text/html" id="text_field">
<div class="row">
<div class="col-md-3">
<div class="form-group">
<label>Add Field Label</label>
<input type="text" name="textfield_label" class="form-control text-field-label" />
</div>
</div>
<div class="col-md-3">
<label></label>
<input type="text" placeholder="" name="" class="form-control text-field" disabled />
</div>
</div>
</script>

Related

How do I create list the intended way I want

I have the following scripts:
Does calculation for me and lists them
function fromPortIdChange() {
fromportid = $('#fromPortId').val();
console.log(fromportid);
portIdRange(fromportid,toportid);
listOfNumbers=[];
}
function toPortIdChange() {
toportid = $('#toPortId').val();
console.log(toportid);
portIdRange(fromportid,toportid);
listOfNumbers=[];
}
function portIdRange(fromportid, toportid) {
fromportid = $('#fromPortId').val();
toportid = $('#toPortId').val();
fromportidlastvalueSliced = fromportid.slice(-5);
interfaceNameLength = fromportid.length-1;
interfaceName = fromportid.substring(0, interfaceNameLength);
console.log("length: " +interfaceNameLength);
console.log("interface name: " +interfaceName);
fromportidlastvalue = fromportidlastvalueSliced.split('/')[2]
console.log(fromportidlastvalue+ " FROM port id");
console.log("range is " +fromportid+ " to " +toportid);
toportidlastvalueSliced = toportid.slice(-5);
toportidlastvalue = toportidlastvalueSliced.split('/')[2]
console.log(toportidlastvalue+ " TO port id");
console.log(typeof(toportidlastvalue));
calculateRange(fromportidlastvalue, toportidlastvalue, interfaceName);
}
function calculateRange(fromportidlastvalue, toportidlastvalue, interfaceName) {
fromportidlastvalue = parseInt(fromportidlastvalue);
toportidlastvalue = parseInt(toportidlastvalue);
console.log(fromportidlastvalue + " type is " + typeof(fromportidlastvalue));
console.log(toportidlastvalue + " type is " + typeof(toportidlastvalue));
currentValue = fromportidlastvalue;
while(currentValue<=toportidlastvalue)
{
console.log(currentValue);
listOfNumbers.push(interfaceName+currentValue);
currentValue++;
}
$('#port_range').val(listOfNumbers);
}
Here is the html involved:
The part it is on the page and the one I am going to clone
<div id = first>
<div class="port">
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label for="subnet_bit">From Port ID</label>
<select id="fromPortId" class="custom-select mb-3" onchange="fromPortIdChange();">
<option selected>Select</option>
{% for items in righttable %}
<option value={{items.0}}>{{items.0}}</option>
{%endfor%}
</select>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="subnet_bit">To Port ID</label>
<select id="toPortId" class="custom-select mb-3" onchange="toPortIdChange();">
<option selected>Select</option>
{%for items in righttable%}
<option value={{items.0}}>{{items.0}}</option>
{%endfor%}
</select>
</div>
</div>
<div class="col-md-1">
<div class="form-group">
<div class="text-sm-center">
<br />
<button type="button" class="btn btn-outline-success btn-rounded"><i class="dripicons-plus" onclick="addButton();"></i></button>
</div>
</div>
</div>
</div>
</div>
</div>
The additional div i created for the clone to be in
<div id="morerows"></div>
This part is for the textarea
<p style="color:red;">If certain interface not needed, delete it</p>
<div class="row">
<div class="col-md-10">
<div class="form-group">
<label for="port_range">Port range</label>
<textarea class="form-control" id="port_range" rows="5"></textarea>
</div>
</div>
</div>
righttable comes from my django view
This script does the following: User choose FortyGigabitEthernet2/0/1 from the drop down of From Port ID and FortyGigabitEthernet2/0/5 from the drop down of To Port ID, it will list all the possible interface in portrange such as shown in the diagram, it lists FortyGigabitEthernet2/0/1, FortyGigabitEthernet2/0/2,FortyGigabitEthernet2/0/3,FortyGigabitEthernet2/0/4,FortyGigabitEthernet2/0/5
As you can see, there is a add button at the side. This is intended to to clone the drop down box for user to select other ports. Such as TenGigabitEthernet1/0/1 for a cloned From Port ID and TenGigabitEthernet1/0/3. So the following TenGigabitEthernet1/0/1, TenGigabitEthernet1/0/2, TenGigabitEthernet1/0/3 is add on to the existing FortyGigabitEthernet2/0/1, FortyGigabitEthernet2/0/2,FortyGigabitEthernet2/0/3,FortyGigabitEthernet2/0/4,FortyGigabitEthernet2/0/5 in the text area of Port Range
For the cloning of the drop down box:
function addButton(){
$('#first .port').clone().appendTo('#morerows')
}
Here comes the issues:
1. The add button works but i dont know is it lag or what. Sometime i have to click the add button multiple times before the cloned dropdown box appear.
2. The cloned drop down box are not working out like i want it to be. Like in the below picture. In 1st row we have FortyGigabitEthernet2/0/1 and Forty GigabitEthernet2/0/2. This is listed in the Port Range. But for the 2nd row of FortyGigabitEthernet2/0/4 and FortyGigabitEthernet2/0/5, it is not listed in the Port Range
Sorry for a very long post but is there anyway for me to achieve what I need. Appreciate if someone can help. Thanks in advance!

Selected Item in Without using the method "change" in dropdown list in Jquery and Asp.Net Core?

I have this code that works well but ...
$("#maincategory").change(function () {
$("#ParentId").empty();
$.getJSON("/AdminPanel/Category/GetSubCategory/" + $("#maincategory :selected").val(),
function (data) {
$.each(data,
function () {
$("#ParentId").append('<option value= ' + this.value + '>' + this.text + '</option>');
})
}
)
});
Html code :
<div class="form-group">
<label class="control-label">choose main category</label>
<select class="form-control" id="maincategory" asp-items="ViewBag.maincategory">
</select>
</div>
<div class="form-group">
<label class="control-label">choose first category</label>
<select class="form-control" asp-for="ParentId">
</select>
<span asp-validation-for="ParentId" class="text-danger"></span>
</div>
I want to give maincategory a value And get ParentId automatically from controller ?

Button click function not working in jQuery

So I'm developing a website for a medical clinic and they asked me to add a button beneath every doctor to make an appointment.
this is what i have for the doctors section
for (var i = 0; i < 3; i++) {
$('#get_medicos').append(
'<div class="col-md-3 dummy">' +
'<div class="text-box">' +
'<img src="assets/images/corpo-clinico/' + medico[i].ficheiro + '" alt="" class="img-responsive"/>' +
'<div class="clearfix"></div>' +
'<div class="text-box white padding-3">' +
'<h5 class="less-mar1 text-blue">' + medico[i].nome +'</h5>' +
'<p>' + medico[i].especialidade + '</p>' +
'<a id="marcar" type="button" class="btn btn-primary">Marcar consulta</a>' +
'</div>' +
'</div>' +
'</div>'
);
}
The then code for the click function (that doesn't work):
$('#marcar').click(function() {
var offset = $('#marcacao').offset();
$('html, body').animate({
scrollTop: offset.top-100,
scrollLeft: offset.left
}, 1000);
$('#marcacao-consulta').find('#especialidade-marcacao option[id="default"]').text(medico[i].especialidade);
$('#marcacao-consulta').find('#corpo-clinico option[id="default"]').text(medico[i].nome);
console.log('test');
});
This is all inside a $(document).ready(function() {}); and what should do is when i click that button beneath the doctor, should go up to the form and fill the doctor's name and specialty... but it seems it's not working for some reason... this is a copy of other click functions in the code, but they seem to work fine.
HTML form:
<div id="marcacao-consulta" data-target="#marcacao-consulta">
<div class="row">
<div class="col-md-6 col-lg-6 col-sm-12">
<div class="section">
<label class="field select prepend-icon">
<select id="especialidade-marcacao" class="gui-input">
<option id="especialiade-default" value="default">Escolha a especialidade</option>
<?
$query = $dbHandle->prepare("
SELECT `especialidade`
FROM `especialidade`
ORDER BY `especialidade` ASC
");
$query->execute();
if ($query->rowCount() > 0) {
while ($row = $query->fetch(PDO::FETCH_ASSOC)) { ?>
<option value="<?=$row["especialidade"]; ?>"><?=$row["especialidade"]; ?></option>
<? }
} else { ?>
<option value="">Nenhum resultado</option>
<? }
?>
</select>
<span class="field-icon"><i class="fas fa-heartbeat"></i></span>
</label>
</div>
</div>
<div class="col-md-6 col-lg-6 col-sm-12">
<div class="section">
<label class="field select prepend-icon">
<select id="corpo-clinico-marcacao" class="gui-input">
<option id="corpo-clinico-default" value="default">Escolha o médico</option>
<?
$query = $dbHandle->prepare("
SELECT `nome`
FROM `medico`
ORDER BY `nome` ASC
");
$query->execute();
if ($query->rowCount() > 0) {
while ($row = $query->fetch(PDO::FETCH_ASSOC)) { ?>
<option value="<?=$row["nome"]; ?>"><?=$row["nome"]; ?></option>
<? }
} else { ?>
<option value="">Nenhum resultado</option>
<? }
?>
</select>
<span class="field-icon"><i class="fas fa-user-md"></i></span>
</label>
</div>
</div>
<div class="col-md-12 col-lg-12 col-sm-12">
<div class="section">
<label class="field prepend-icon">
<input id="nome" class="gui-input" type="text" placeholder="Nome Completo">
<span class="field-icon"><i class="fas fa-user"></i></span>
</label>
</div>
<div class="section">
<label class="field prepend-icon">
<input id="email" class="gui-input" type="text" placeholder="Endereço de correio eletrónico">
<span class="field-icon"><i class="fas fa-envelope"></i></span>
</label>
</div>
<div class="section">
<label class="field prepend-icon">
<input id="telefone" class="gui-input" type="text" placeholder="Telefone/Télemovel">
<span class="field-icon"><i class="fas fa-phone-square"></i></span>
</label>
</div>
<div class="section">
<label class="field prepend-icon">
<input id="tipo" class="gui-input" type="text" value="consulta" disabled>
</label>
</div>
</div>
</div>
</div>
You have to add the element and register the event for the element. Here is the fiddle which works for you
https://jsfiddle.net/0q3kpyfv/
Your sample HTML
<div id="get_medicos">
</div>
Sample jquery code
Notice I have added the data-val attribute to the added anchor tag which will help you to get the information and perform the logic based on which button is clicked. you can pass dynamic data to data-val attribute and use it in click event.
$(document).ready(function() {
var sampleString = "";
var medico = [{'especialidade':'speciality 0','nome':'Doctor 0'},{'especialidade':'speciality 1','nome':'Doctor 1'},{'especialidade':'speciality 2','nome':'Doctor 2'}]
for (var i = 0; i < 3; i++) {
var doctorData = medico[i];
$('#get_medicos').append(
'<div class="col-md-3 dummy">' +
'<div class="text-box">' +
'<img src="assets/images/corpo-clinico/' + medico[i].especialidade + '" alt="" class="img-responsive"/>' +
'<div class="clearfix"></div>' +
'<div class="text-box white padding-3">' +
'<h5 class="less-mar1 text-blue">' + medico[i].nome +'</h5>' +
'<p>' + medico[i].especialidade + '</p>' +
'<a id="marcar" data-doctor-especialiadade="'+medico[i].especialidade+'" data-doctor-nome="'+medico[i].nome+'" type="button" class="btn btn-primary">Marcar consulta'+i+'</a>' +
'</div>' +
'</div>' +
'</div>'
);
};
$('#get_medicos').on('click','a',function(event){
var elementClicked = event.target;
var doctorEspecialiadade = $(elementClicked).data('doctor-especialiadade');
var doctorName = $(elementClicked).data('doctor-nome');
$('#marcacao-consulta').find('#especialidade-marcacao option[id="default"]').text(doctorEspecialiadade);
$('#marcacao-consulta').find('#corpo-clinico option[id="default"]').text(doctorName);
})
});
if you create the button after your event, you could have problem so, use the delegate version of click:
$('div').on('click', 'a', (function()....
and better put an id on the ancestor div:
'<div class="text-box white padding-3" id="mydiv"'
:
$('#mydiv').on('click', 'a', (function()....
another thing, with the loop you will have same id more time in your html??its no good.
so you'll have to rebuild your program logic...and bind the event with the right button (use a common class) it will be better than an id
If you bind the event to the parent element, and filter by the children, you can listen to any new elements that are added, doesn't matter how many.
<div class="container"></div>
<button class="js-add-new">Add new</button>
const $addNew = $('.js-add-new')
const $container = $('.container')
let count = 0
$addNew.on("click", () => {
count += 1
$container.append(`
<div>
<button>log me ${count}</button>
</div>
`)
})
$container.on("click", "button", (event) => {
console.log(event.currentTarget)
})
A working example: https://codepen.io/alexmccabe/pen/jOrXZxj?editors=1111
The button click is working. Here is a fiddle showing it does:
https://jsfiddle.net/bradberkobien/qL4m10y6/3/
There must be an issue with the code that comes before the console.log("test") line within the click. I would use the debugger to help you with that.

jQuery - Event delegation only targeting first newly-created element

I'm trying to create a simple reddit-like system where a user can add a post and then interact with the voting system (which pastes along with the form).
While I have utilized event delegation, it only seems to be affecting my first newly-created element. Thus, on the first newly-created element, the voting system works.
On the latter ones, however, what seems to happen is that the event does get attached, but it updates the first voting system (every post gets a little voting system attached to it).
Any help is appreciated! Thank you.
$("#subbtn").on("click", function(event){
event.preventDefault();
var postTitle = $("#title").val(),
postBody = $("#content").val();
$("#title").val("");
$("#content").val("");
var html = "<div class='wrapper'><div class='panel panel-default'><p class='button' id='plus'>+</p><p id='count'>0</p><p class='button' id='minus'>-</p><h3>'" + postTitle + "</h3><p>" + postBody + "</p></div></div>";
$("body").append(html);
});
var counter = 0;
$(document).on("click", "#plus", function() {
counter++;
$("#count").text(counter);
});
$(document).on("click","#minus", function() {
counter--;
$("#count").text(counter);
});
My HTML is:
<body>
<div class="panel panel-default" id="formStuff">
<div class="form-group">
<label for="title">Title </label> </label>
<input type="title" id="title" class="form-control">
</div>
<div class="form-group">
<label for="content">Content </label>
<textArea rows="5" type="content" id="content" class="form-control"></textArea>
</div>
<input type="submit" class="btn btn-success" id="subbtn">
</div>
</body>
You are adding multiple voting systems with same IDs plus,count and minus. But Ids should be unique. Instead use classes with same classes and make the selector work on the classes. Please check below snippet for more understanding.
$("#subbtn").on("click", function(event){
event.preventDefault();
var postTitle = $("#title").val(),
postBody = $("#content").val();
$("#title").val("");
$("#content").val("");
var html = "<div class='wrapper'><div class='panel panel-default'><p class='button plus'>+</p><p class='count'>0</p><p class='button minus'>-</p><h3>'" + postTitle + "</h3><p>" + postBody + "</p></div></div>";
$("body").append(html);
});
$(document).on("click", ".plus", function() {
var counter = $(this).siblings(".count").text();
counter++;
$(this).siblings(".count").text(counter);
});
$(document).on("click",".minus", function() {
counter--;
var counter = $(this).siblings(".count").text();
counter--;
$(this).siblings(".count").text(counter);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="panel panel-default" id="formStuff">
<div class="form-group">
<label for="title">Title </label> </label>
<input type="title" id="title" class="form-control">
</div>
<div class="form-group">
<label for="content">Content </label>
<textArea rows="5" type="content" id="content" class="form-control"></textArea>
</div>
<input type="submit" class="btn btn-success" id="subbtn" />
</div>
This is happening because of the following line:
$(document).on("click", "#plus", function() {...});
// here you are using id selector which are unique.

How not to overwrite your variables

I've been stuck on this problem without a clear way around it for a while now. https://jsfiddle.net/brendanjackson/4ajs7czo/3/
Here's the scenario. I have two functions that send one set of data to different areas of my page. So if you enter some text in the main field, hit submit, it sends that text to 'set1' and creates a button and select menu.
<body>
<div class="container-fluid">
<div class="start">
<form class="form-inline">
<h1><strong>Start</strong></h1>
<div class="row">
<div class="col-xs-4">
Task:<input type="text" class= "task form-control" id="input_text" >
</div>
</div>
<!--***********************************************************************************************************-->
<div class="row">
<div class="col-md-4">
Send to:
<select class="set1_menu">
<option value="set1table0">set1table0</option>
</select>
</div>
<div class="col-md-4">
<input type="button" id='submit_button' class="btn btn-primary" value="Submit!" />
</div>
</div>
</form>
</div>
<!--***********************************************************************************************************-->
<div>
<h1 class="label label-default">Set1</h1>
<div class="set1 row">
<div class="set1_table0 column ">
<h3>set1table0</h3>
<ul class="set1_text0"></ul>
</div>
</div>
<!--**********************************************************************************************************-->
<div>
<h1 class="label label-default set2">Set2</h1>
</div>
<!--*********************************************************************************************************-->
<div>
<div class="set2_table0 column">
<h3>set2table0</h3>
<ul class="set2_text0"></ul>
</div>
</div>
</div>
$('#submit_button').on("click",function() {
/*==========================================
variabes
===========================================*/
task = $(".task").val();
set1_menu = $(".set1_menu option:selected");
set1_index = set1_menu.index() //switch arg
set2_menu = '<select class="set2_menu"> <option value="set2_table0">set2table0</option> </select>';
set2_button = '<input type="button" class="set2_button" data-set1_data="'+set1_index+'" value="set2_button" />'
$('.set1_table0').append("<li>" + task + " " + set2_menu + " " + set2_button + "</li>" );
})
$("div.set1.row").on("click", "input.set2_button", function(){
/*==========================================
variabes
===========================================*/
var set2_index = $(this).closest('li').find('select.set2_menu option:selected').index();
var set1_data = $(this).data('set1_data');
var set2_data = $(this).data('set2_data');
/*=========================================
TEST
=========================================*/
console.log( "IT WORKS" + " " + set2_index );
switch(set2_index){
case 0:
$('.set2_table0').append("<li>" + task + " " + " (from Table " +set1_data+ " )" + " " /*+ datetimepicker + " "*/ + "</li>" );
break;
}
});
Problem:
If the user follows the data sent to set1 and sends it to set2 all is well and the jedi win!
However, if the user decides to go back to the start, enter new information, and send it to set1, the previous variable has of course been overwritten and can no longer be sent to set2. It will now send whatever the newest variable's information is.
Something was suggested to me like adding var i=0++, task and then adding i++ on my 1st function so it gives each variable its own easy to find # like task0, task1, task(n) as well as turning it into an array. Both of these solutions I'm just not understanding how to implement, maybe for the lack of how to express my problem to research it?
Question
How do I cleanly save each set of data that is submitted so that it can be sent from set1 to set2 whenever the user decides they're ready.

Categories

Resources