I have made contact list app which displays contact details. By Default it shows 2 contact details.
In index.html I have made 2 functions called showContacts() and editContact(id).
I am dynamically populating div tags i.e editcontact & contactlist in index.html
When I click on edit button it should show 3 input elements to take input from user and one submit button I tried to implement it (see code below) but only search bar disappear's and only default contacts are shown which should not be shown and it should display editing form.
var array = [];
function Person(fullName, number, group) {
this.fullName = fullName;
this.number = number;
this.group = group;
array.push(this);
}
Person.prototype.getFullName = function() {
return this.fullName + ' ' + this.number + ' ' + this.group;
}
var p1 = new Person("Jonathan Buell", 5804337551, "family");
var p2 = new Person("Patrick Daniel", 8186934432, "work");
console.log(array);
document.getElementById("contactlist").innerHTML = '';
function showContacts() {
for (var i in array) {
var id = i;
contactlist.innerHTML +=
`
<ul>
<div>
<p>Name: ` + p1.fullName + `</p>
<p>Number: ` + p1.number + `</p>
<p>Group: ` + p1.group + `</p>
<button type="button" class="btn btn-warning" onclick="editContact(` + id + `)">Edit</button>
<button type="button" class="btn btn-danger">Delete</button>
</div>
`
}
}
showContacts();
function editContact(id) {
document.getElementById("search").style.display = 'none';
document.getElementById("contactList").style.display = 'none';
document.getElementById("editcontact").style.display = '';
document.getElementById("editcontact").innerHTML =
`<div>
<input type="text" placeholder="Name here" id="nameInput2" value="` + array[id].fullName + `">
<input type="tel" placeholder="Number here" id="numberInput2" value="` + array[id].number + `">
<input type="text" placeholder="Group Here" id="groupInput2" value="` + array[id].group + `">
<button type="button" class="btn btn-success">Submit</button>
</div>`;
}
<div class="header">
<div id="dropdown">
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Sort by Group
<span class="caret"></span></button>
<ul class="dropdown-menu">
<li>All</li>
<li>Work</li>
<li>Family</li>
</ul>
</div>
</div>
<div class="title">
<h2>All Contacts</h2>
</div>
<div class="button" id="addButton">
<p>
<a href="#">
<span class="glyphicon glyphicon-plus-sign"></span>
</a>
</p>
</div>
</div>
<div id="search">
<form>
<div class="input-group">
<input type="text" class="form-control" placeholder="Search">
<div class="input-group-btn">
<button class="btn btn-default" type="submit">
<i class="glyphicon glyphicon-search"></i>
</button>
</div>
</div>
</form>
</div>
<div id="contactlist">
</div>
<div id="editcontact">
</div>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="index.css">
screenshots :
1) Before on click editContact :
2) After onclick editContact :
Live demo can be seen here :
https://jsfiddle.net/w2hoqmts/
A couple of things.
You made a typo with your contactlist in your html (should be contactList).
In your loop for showContacts you are setting id as index and should be like
function showContacts() {
for (var i in array) {
var id = array[i].number;
document.getElementById("contactList").innerHTML +=
'<ul><div><p>Name: ' + array[i].fullName + '</p><p>Number: ' + array[i].number + '</p><p>Group: ' + array[i].group + '</p>' +
'<button type="button" class="btn btn-warning" onclick="editContact(' + id + ')">Edit</button>' +
'<button type="button" class="btn btn-danger">Delete</button>' +
'</div>';
}
}
Your editContact method is using the id as an index (as previous), which is wrong. You could do something like this instead (see code below). I filter the array with people based on the unique id provided from the link when you click edit.
function editContact(id) {
var obj = array.filter(function (ele) {
console.dir(ele);
if (ele.number === id) return ele;
});
console.dir(obj);
document.getElementById("search").style.display = 'none';
document.getElementById("contactList").style.display = 'none';
document.getElementById("editcontact").style.display = '';
document.getElementById("editcontact").innerHTML =
'<div>'+
'<input type="text" placeholder="Name here" id="nameInput2" value="'+ obj[0].fullName + '">'+
'<input type="tel" placeholder="Number here" id="numberInput2" value="' + obj[0].number + '">' +
'<input type="text" placeholder="Group Here" id="groupInput2" value="' + obj[0].group + '">' +
'<button type="button" class="btn btn-success">Submit</button>'+
'</div>';
}
I've made a updated fiddle based on your own
https://jsfiddle.net/w2hoqmts/3/
Following changes should be made in editContact() and showContacts() function.
function showContacts(){
for(var i in array){
var id = i;
contactlist.innerHTML +=
`
<ul>
<div>
<p>Name: `+ p1.fullName +`</p>
<p>Number: `+ p1.number +`</p>
<p>Group: `+ p1.group +`</p>
<button type="button" class="btn btn-warning" onclick="editContact(`+ id +`)">Edit</button>
<button type="button" class="btn btn-danger">Delete</button>
</div>
`
}
}
showContacts();
function editContact(id) {
document.getElementById("search").style.display = 'none';
document.getElementById("contactlist").style.display = 'none';
document.getElementById("editcontact").style.display = '';
document.getElementById("editcontact").innerHTML =
`<div>
<input type="text" placeholder="Name here" id="nameInput2" value="`+array[id].fullName+`">
<input type="tel" placeholder="Number here" id="numberInput2" value="`+array[id].number+`">
<input type="text" placeholder="Group Here" id="groupInput2" value="`+array[id].group+`">
<button type="button" class="btn btn-success">Submit</button>
</div>`;
}
Related
Codepen https://codepen.io/mehmetmasa-the-selector/pen/RwBQbOr
When I click the button, I add a new field. One of the added fields (radio button) needs to be selected. But since the user can add/delete, I can't give the value value.
HTML Code
<div id="answer">
<div class="form-group d-flex">
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input trueAnswer" type="radio" name="trueAnswer">Doğru Cevap </label>
</div>
<input class="form-control answer" type="text" placeholder="Cevabı Yazınız">
<button class="btn btn-primary ml-3 col-md-1" type="button" id="addAnswer">Yeni Cevap</button>
</div>
</div>
JS Code
$('#addAnswer').on('click', function() {
$('<div class="form-group d-flex">' +
'<div class="form-check">' +
'<label class="form-check-label">' +
'<input class="form-check-input trueAnswer" type="radio" name="trueAnswer">Doğru Cevap' +
'</label>' +
'</div>' +
'<input class="form-control answer" type="text" placeholder="Cevabı Yazınız">' +
'<button class="btn btn-danger ml-3 col-md-1 deleteAnswer" type="button" >Cevabı Sil</button>' +
'</div>').appendTo('#answer');
});
$('#addQuestion').on('click', function() {
let answer = [];
$('#answer .form-group').map(function(i, val) {
if ($(val).find('.answer').val().length > 0)
answer.push({
name: $(val).find('.answer').val(),
trueAnswer: $(val).find('.trueAnswer').val()
});
});
let categoryID = $('#category').val();
let question = $('#question').val();
let questionNo = $('#questionNo').val();
let colorpicker = $('#colorpicker').val();
let formData = new FormData();
formData.append("categoryID", categoryID);
formData.append("question", question);
formData.append("questionNo", questionNo);
formData.append("colorpicker", colorpicker);
for (var i = 0; i < answer.length; i++) {
formData.append('answer' + [i], answer[i].name);
formData.append('answer' + [i], answer[i].trueAnswer);
}
How can I find which answer the user chose?
I have tried numerous ways of editing a task added to the task list, but the code is not functioning. Any clue where the error is or if there is a simpler way to add an edit task button? I want to avoid simply making all the list items contenteditable=true, but rather want to be able to click an edit button to edit first. When I try to add an edit button to the '//call append method on $todoList' line, the button functions as a done/remove from list button, instead of working as an edit button to alter the list item.
var $addButton = $(".btn-primary");
var $removeButton = $(".btn-danger");
var $editButton = $(".btn-primary");
var $todoList = $(".uncomplete");
var $doneList = $(".completed");
//Take Text Input and Add <li> to To Do List
$addButton.on("click", function(){
//Creating object Variables
var $sort = $(".sort").val();
var $newTask = $(".newTask").val();
var $taskDescr = $(".taskDescr").val();
var $taskDate = $(".taskDate").val();
// var $category= $(".category").val();
var $category= $("input[type='radio'][name='category']:checked").val();
//var $importance = $("input[type='checkbox'][name='importance']:checked").val();
var $importance = $('<input type="checkbox" name="importance"/>').val();
var $newTaskString = $sort + ", " + $taskDescr + ", " + $newTask + ", " + $taskDate + ", " + $category + ", " + $importance + " ";
var $todoList = $(".uncompleted");
//call append method on $todoList
$todoList.append("<li>" + $newTaskString + "<button><span> Done</span></button><button><span> Remove</span></button></li>").addClass("todo");
//add styles to button added to DOM by append
var $span = $(".todo button span");
var $button = $(".todo button");
$button.addClass("btn btn-success");
$span.addClass("glyphicon glyphicon-ok");
$("input").val("");
})
//Edit existing task
//var id_counter
//var $task = $("<tr class='taskList' id='"+ id_counter +"'>")
//function myEdit(){
//}
$(function(){
$(document).on('click','.my-row .col-a3',function(){
let editable = $(this).prev('.col-a2').attr('contenteditable');
if(editable){
$(this).text('Edit');
$('.col-a2').css({'border': ''});
$(this).prev('.col-a2').removeAttr('contenteditable');
}
else{
$(this).text('Save');
$('.col-a2').css({'border': '1px solid'});
$(this).prev('.col-a2').attr('contenteditable','true');
}
})
});
<div class="list-wrap" contenteditable="false">
<div class="list-inner-wrap">
<h2 class="title">ToDo List</h2>
<h3 class="title">Add Task</h2>
<!--<h4>Task Name</h4>-->
<label for="sort">Sort Order:</label><input type="text" class="sort" name="sort" id="sort" value="" placeholder="A,B,C,etc.">
<br>
<label for="task-name">Task Name:</label><input type="text" class="newTask" name="task-name" id="task-name" value="" placeholder="My task...">
<br>
</form>
<br>
<button class="btn btn-primary">
<span class="glyphicon glyphicon-plus"> Add</span>
</button>
<!--Edit task button-->
<button class="edit" onclick="myEdit()">Edit Task</button>
<p id="demoedit"></p>
<br>
<div class="my-row">
<h3 class="title">To Do</h2>
<h6><i>Click task item to edit or modify</i></h6>
<!--Change color of editable task -->
<div id='div' contenteditable='false' oninput='change()'>
<ul class="uncompleted" contenteditable="false" id="id01">
<div class="col-a2">
<li>Need to be completed task
<button class="btn btn-success" a href="#" onclick="allUsersDiv()">
<span class="glyphicon glyphicon-ok"> Done</span>
</button>
<button class="btn btn-danger">
<span class="glyphicon glyphicon-remove"> Remove</span></button>
<!-- <div class="col-a3"><button>Edit</button>
</div>-->
<br>
</li></ul></div></div>
</div></div></div>
<br><br><br><br><br><br><br><br><br>
<h3 class="title">Completed Tasks</h2>
<ul class="completed" contenteditable="false">
<li>Completed Task<button class="btn btn-danger">
<span class="glyphicon glyphicon-remove"> Remove</span>
</button></li>
</ul>
</div>
<br>
<br>
Below is my code for cloning the timepicker.
I have tried to remove hasDatepicker class on click and tried to call timepicker again but its not working. Below is my code
$(document).ready(function() {
var clone_index = 0;
console.log(max_value);
$("#add_period_break").click(function() {
$(".start_time").removeClass('hasDatepicker');
$('.start_time').timepicker({});
clone_index = clone_index + 1;
//$("#countform").val(clone_index);
console.log("add" + clone_index);
$(this).parent().before($("#clone").clone().attr("id", "clone" + clone_index));
$("#clone" + clone_index).css("display", "inline");
$("#clone" + clone_index + " :input").each(function() {
$(this).attr("name", $(this).attr("name") + clone_index);
$(this).attr("id", $(this).attr("id") + clone_index);
$("#countform").val(clone_index);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<div id='clone'>
<div class="form-group">
<label for="exampleInputEmail1">Start Time</label>
<input type="text" name="start_time" id="start_time" class="form-control start_time" readonly="readonly" value="" placeholder="Start Time">
</div>
</div>
<div id="box-footer">
<button type="button" class="btn btn-success" name="add_period_break" id="add_period_break"><i class="glyphicon glyphicon-plus"></i> Add Periods/ Breaks</button>
<button type="submit" class="btn btn-primary"> Submit</button>
</div>
You want to use jQuery timepicker
You don't need to remove hasDatepicker class, because its will never assigned to it.
Also there is a variable max_value which is not assigned. so please remove it.
Please check below code:
$(document).ready(function () {
var clone_index = 0;
$('.start_time').timepicker({});//For first time on page load
$("#add_period_break").click(function () {
clone_index = clone_index + 1;
$(this).parent().before($("#clone").clone().attr("id", "clone" + clone_index));
$("#clone" + clone_index).css("display", "inline");
$("#clone" + clone_index + " :input").each(function () {
$(this).attr("name", $(this).attr("name") + clone_index);
$(this).attr("id", $(this).attr("id") + clone_index);
$("#countform").val(clone_index);
});
$('.start_time').timepicker({});///to apply timepicker on newly added textbox
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/timepicker/1.3.5/jquery.timepicker.js"></script>
<div id='clone'>
<div class="form-group">
<label for="exampleInputEmail1">Start Time</label>
<input type="text" name="start_time" id="start_time" class="form-control start_time" readonly="readonly" value="" placeholder="Start Time">
</div>
</div>
<div id="box-footer">
<button type="button" class="btn btn-success" name="add_period_break" id="add_period_break"><i class="glyphicon glyphicon-plus"></i> Add Periods/ Breaks</button>
<button type="submit" class="btn btn-primary"> Submit</button>
</div>
I am looking to post back using Jquery (Java, Spring-Data Server side). I am looking to pass back multiple objects while using dynamic input fields on client side.
Server side service can handle saving multiple TimeOffRequests as an Itterable List. However, With having 2 input fields tied to the object I am struggling to format the data properly. Currently will return 4 objects in the array vs 2 Any help would be greatly appreciated
HTML:
<div class="widget-body no-padding">
<div class="smart-form">
<fieldset>
<div id = wrapper>
<div class="row" id="addInput" >
<section class="col col-4">
<label class="input"> <i class="icon-append fa fa-calendar"></i>
<input type="date" name="startDate" id="startDate" placeholder="Request Date" class="hasDatepicker">
</label>
</section>
<section class="col col-2">
<label class="input"><i class="icon-append fa fa-clock-o"></i>
<input min="0" max="8" type="number" name="hour" id="hour" placeholder="Hours">
</label>
</section>
<section class="col col-2">
<a id="addField" title="Add More Fields" class="btn btn-primary" onclick="addInput('wrapper');"> + </a>
</section>
</div>
</div>
<section>
<label class="textarea"> <i class="icon-append fa fa-comment"></i>
<textarea rows="5" name="comment" placeholder="Notes"></textarea>
</label>
</section>
</fieldset>
<footer>
<button onclick="submitTimeOffRequest()" class="btn btn-primary">
Submit
</button>
</footer>
</div>
JS Submit
function submitTimeOffRequest(){
var timeoffRequests = [];
$("input[class = ptoDate ]").each(function () {
var date = $(this).val();
$("input[class= ptoHours]").each(function () {
var hours = $(this).val();
item = {};
item ["date"] = date;
item ["hours"] = hours;
timeoffRequests.push(item);
});
});
$.ajax({
contentType: 'application/json',
type: "post",
data: JSON.stringify(timeOffRequests),
url: "/api/timeoff/" + masterEngId,
async: true,
dataType: "json",
success: function() {
location.reload(true);
},
error: function(){
}
})}
}
JS Dynamically add input fields
var counter = 1;
function addInput(divName) {
var dateIdString = "startDate" + counter;
var hourIdString = "hour" + counter;
console.log(dateIdString);
var newdiv = document.createElement('div');
newdiv.innerHTML = "<div class='row'>" +
"<section class='col col-4'> " +
"<label class='input'><i class='icon-append fa fa-calender'>" +
"</i> <input class = 'ptoDate' type='date' name="+dateIdString+" id="+dateIdString+" placeholder='Request Date'</input> " +
"</label> " +
"</section>" +
"<section class='col col-2'>" +
"<label class='input'><i class='icon-append fa fa-clock-o'></i>" +
"<input type='number' class='ptoHours' name="+hourIdString+" id="+hourIdString+" placeholder='Hours'>" +
"</label>" +
"</section>" +
"<section class='col col-2'><a id='removeField' title='Remove Field' class='btn btn-danger' onclick='removeDiv()'> x </a> " +
"</section> " +
"</div>";
document.getElementById(divName).appendChild(newdiv);
counter++;
}
I'm trying to implement an extend form function in two places on the same page. The first place works fine, but the second place does not even call the function apparently.
The html and js of the first place:
<span id="readroot" style="display: none">
<input class="btn btn-default" type="button" value="Remove review" onclick="this.parentNode.parentNode.removeChild(this.parentNode);" /><br /><br />
<div class="row">
<!-- Content not displayed for simplicity purpose -->
</div>
</span>
<span id="writeroot"></span>
<input class="btn btn-default" type="button" onclick="moreFields()" value="Give me more fields!" />
<script>
var counter = 1;
function moreFields() {
counter++;
var newField = document.getElementById('readroot').cloneNode(true);
newField.id = '';
newField.style.display = 'block';
var newFields = newField.querySelectorAll('[name], [id], [for]');
for (var i=0;i<newFields.length;i++) {
var theNames = newFields[i].name
if (theNames)
newFields[i].name = "data[Student][" + counter + "][" + theNames + "]";
var theNames2 = newFields[i].id;
if (theNames2)
newFields[i].id = theNames2 + counter;
var theNames3 = newFields[i].htmlFor;
if (theNames3)
newFields[i].htmlFor = theNames3 + counter;
//console.log(newFields[i].htmlFor);
}
var insertHere = document.getElementById('writeroot');
insertHere.parentNode.insertBefore(newField,insertHere);
}
</script>
The second:
<span id="readroot2" style="display: none">
<input class="btn btn-default" type="button" value="Remove review" onclick="this.parentNode.parentNode.removeChild(this.parentNode);" /><br /><br />
<div class="row">
<!-- Content not displayed for simplicity purpose -->
</div>
</span>
<span id="writeroot2"></span>
<input class="btn btn-default" type="button" onChange="moreFields2()" value="Give me more fields!" />
<script>
var counter = 1;
function moreFields2() {
counter++;
var newField = document.getElementById('readroot2').cloneNode(true);
newField.id = '';
newField.style.display = 'block';
var newFields = newField.querySelectorAll('[name], [id], [for]');
for (var i=0;i<newFields.length;i++) {
var theNames = newFields[i].name
if (theNames)
newFields[i].name = "data[Condition][" + counter + "][" + theNames + "]";
var theNames2 = newFields[i].id;
if (theNames2)
newFields[i].id = theNames2 + counter;
var theNames3 = newFields[i].htmlFor;
if (theNames3)
newFields[i].htmlFor = theNames3 + counter;
}
var insertHere = document.getElementById('writeroot2');
insertHere.parentNode.insertBefore(newField,insertHere);
}
</script>
I have tried by naming all the variables in the second function differently. But it seems irrelevant..
First you have use two different events on both input
<input class="btn btn-default" type="button" onclick="moreFields()"
<input class="btn btn-default" type="button" onChange="moreFields2()"
So make sure that you are looking for same functionality on both than they will not..
onChange will fire after element change not while you type here check for code so be clear what you wanted. Because onChange will fire on blur in this case
The second function is not firing on onChange event. If you try to design the function accordingly you could have to reduce the effort to writing too many java script.
<span id="readroot" style="display: none">
<input class="btn btn-default" type="button" value="Remove review" onclick="this.parentNode.parentNode.removeChild(this.parentNode);" /><br /><br />
<div class="row">
<!-- Content not displayed for simplicity purpose -->
</div>
</span>
<span id="writeroot"></span>
<input class="btn btn-default" type="button" onclick="moreFields('readroot','writeroot')" value="Give me more fields!" />
<span id="readroot2" style="display: none">
<input class="btn btn-default" type="button" value="Remove review" onclick="this.parentNode.parentNode.removeChild(this.parentNode);" /><br /><br />
<div class="row">
<!-- Content not displayed for simplicity purpose -->
</div>
</span>
<span id="writeroot2"></span>
<input class="btn btn-default" type="button" onClick="moreFields('readroot2','writeroot2')" value="Give me more fields!" />
<script>
var counter = 1;
function moreFields(node, insertNode) {
counter++;
var newField = document.getElementById(node).cloneNode(true);
newField.id = '';
newField.style.display = 'block';
var newFields = newField.querySelectorAll('[name], [id], [for]');
for (var i = 0; i < newFields.length; i++) {
var theNames = newFields[i].name
if (theNames)
newFields[i].name = "data[Condition][" + counter + "][" + theNames + "]";
var theNames2 = newFields[i].id;
if (theNames2)
newFields[i].id = theNames2 + counter;
var theNames3 = newFields[i].htmlFor;
if (theNames3)
newFields[i].htmlFor = theNames3 + counter;
}
var insertHere = document.getElementById(insertNode);
insertHere.parentNode.insertBefore(newField, insertHere);
}
</script>
Please counter check it again for the functionality. And you may please optimize the code.