I'm making an address book of a company's tech support contacts and the admin gets access to all addresses in a form of a table. In this table, he can add, delete and make changes to data in the same page.
I have set up the add and delete functions successfully, but I struggle a lot with the edit. I'm using node, express, mongodb and vanilla javascript.
I'm still a newbie in web developement and there is are words I may use wrong, so sorry in advance!
(Excuse my french, but most of the words mean the same in english.)
My HTML
<div>
<input id="edit" type="button" value="Editer" onclick="return edit()">
<input id="valider" type="hidden" value="Valider" onclick="return valider()">
</div>
<table id='myTable'>
<thead>
<tr class="header">
<th>Nom de l'entreprise</th>
<th>Téléphone 1</th>
<th>Téléphone 2</th>
<th>Mail</th>
</tr>
</thead>
<tbody>
<% companies.forEach(function(company){ %> //I loop through my db
<tr class="compName">
<td hidden id='_id' > <%= company._id %> </td>
<td> <input id="name" class="readonly" type="text" value=" <%= company.name %>" readonly style="border: none" onblur="change(this)"> </td>
<td> <input id="phone" class="readonly" type="text" value=" <%= company.phone %>" readonly style="border: none" onblur="change(this)"> </td>
<td> <input id="phone2" class="readonly" type="text" value=" <%= company.phone2 %>" readonly style="border: none" onblur="change(this)"> </td>
<td> <input id="mail" class="readonly" type="text" value=" <%= company.mail %>" readonly style="border: none" onblur="change(this)"> </td>
</tr>
<% }) %>
</tbody>
</table>
My Script
<script>
function edit() {
var editComp = document.getElementsByClassName("readonly");
var edit = document.getElementById('edit').type = 'hidden'; //get the edit button and hide it
var valider = document.getElementById('valider').type = 'button'; //then unhide the validate button so I can use it
for (var i = 0; i < editComp.length; i++) { //remove the readonly for each td so I can edit it
editComp[i].removeAttribute('readonly');
editComp[i].setAttribute("style", "border: 1px solid red;");
};
}
function valider() {
var editComp = document.getElementsByClassName("readonly");
var edit = document.getElementById('edit').type = 'button'; //unhide the edit button
var valider = document.getElementById('valider').type = 'hidden' //hide my validate button
for (var i = 0; i < editComp.length; i++) { //put back the readonly for each td so its uneditable
editComp[i].setAttribute('readonly', true);
editComp[i].setAttribute("style", "border: none;");
};
}
function change(element) { //when the input gets unfocused, I assume that's because changes happened
var setChanged = element.setAttribute("class", "readonly changed"); //I mark all changed element
/*I want to udapte my database with the changed elements
I was thing of getting the hidden company._id and the id of the changed element so I can update them specifically*/
}
</script>
So I was think of getting the col[0] of the changed row, which is the _id of my changed element, so I can target it for updating in my database, but I don't know how I should do it.
Thanks!
Related
guys, I am going to develop a simple primary code to get data from the user and add to the table. I have already done the mission but there is some problem I need to ask.
I want to put my operation element (Edit | Delete) also in a cell just like entered first name and last name.
I know how to use "td" for first and last name but I dunno how to add "td" element to put (Edit | Delete) also in a cell of my table
function AddStudents(event){
var x = document.getElementById('fname').value ;
var y = document.getElementById('lname').value ;
console.log("LINE 1");
var ftd = document.createElement('tr');
var ft = document.createElement('td');
var text = document.createTextNode(fname.value);
ft.appendChild(text);
console.log("LINE 2");
var nt = document.createElement('td') ;
var text2 = document.createTextNode(lname.value);
nt.appendChild(text2);
var ot = document.createElement('a');
var neu = document.createElement('td') ;
var od = document.createElement('a');
var sp = document.createElement('a');
ot.innerHTML = ' Edit' ;
od.innerHTML = ' Delete';
sp.innerHTML = ' | ' ;
ot.href = "#" ;
od.href = "#" ;
console.log("LINE 3");
ftd.appendChild(ft)
ftd.appendChild(nt)
ftd.appendChild(ot)
ftd.appendChild(sp)
ftd.appendChild(od)
console.log("LINE 4");
document.getElementById("students").appendChild(ftd);
}
and this my html code :
<input type="text" id="fname" placeholder="First Name">
<input type="text" id="lname" placeholder="Last Name">
</br>
</br>
<button id="add" onclick="AddStudents(this)">Add Student</button>
<h3>List Of Students</h3>
<table id="students" cellpadding = "7px" text-align = "center" border="1">
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
<td>Operation</td>
</tr>
<tbody></tbody>
</table>
You will need to add the edit and delete links to a td and then append the td to your table.
To do this create a td element, create the links, create a span for the bar and then append the links and span to your td. Now you have a proper table cell which you can append to the table.
As an aside, I recommend you use more descriptive variable names so other people can understand your code easier. It looks like this is likely an assignment your professor would also be able to give you help.
var td = document.createElement('td');
var editLink = document.createElement('a');
var deleteLink = document.createElement('a');
var span = document.createElement('span');
editLink.innerHTML = 'Edit';
editLink.href="#";
deleteLink.innerHTML = 'Delete';
deleteLink.href = "#";
span.innerHTML = '|';
td.appendChild(editLink);
td.appendChild(span);
td.appendChild(deleteLink);
Here is some code which does that, but ensure you understand why this creates a table cell instead of just copy pasting it.
You can simply put a <button> in a <td> element directly:
<input type="text" id="fname" placeholder="First Name">
<input type="text" id="lname" placeholder="Last Name">
</br>
</br>
<button id="add" onclick="AddStudents(this)">Add Student</button>
<h3>List Of Students</h3>
<table id="students" cellpadding = "7px" text-align = "center" border="1">
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
<td>Operation</td>
<td><button class="" id="btnEdit">Edit</button></td>
<td><button class="" id="btnDelete">Delete</button></td>
</tr>
<tbody></tbody>
</table>
If you're using something like Bootstrap then you can also enter classes where I left empty quotation marks to style the button how you'd like.
You can do this in a better way using jQuery
function AddStudents(){
$("#notification").html('');
var fname= $("#fname").val();
var lname=$("#lname").val();
if(fname!='' && lname!=''){
$("#students tbody").append("<tr>");
$("#students tbody").append("<td>"+fname+"</td>");
$("#students tbody").append("<td>"+lname+"</td>");
$("#students tbody").append("<td><a href='#' class='btnedit'>Edit</a> | <a href='#' class='btndelete'>Delete </a></td>");
$("#students tbody").append("</tr>");
}
else{
$("#notification").html('Please enter First Name and Last Name');
}
}
$(document).on("click",".btnedit",function(){
//Implement Edit functionality here
alert('edit');
});
$(document).on ("click",".btndelete",function(){
//Implement delete functionality here
alert('delete');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='notification'></div>
<input type="text" id="fname" placeholder="First Name">
<input type="text" id="lname" placeholder="Last Name">
</br>
</br>
<button id="add" onclick="AddStudents()">Add Student</button>
<h3>List Of Students</h3>
<table id="students" cellpadding = "7px" text-align = "center" border="1">
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
<td>Operation</td>
</tr></thead>
<tbody></tbody>
</table>
I added event handling for your Edit and Delete links since it is created runtime.
Below in the example, I want that each time when the add button is clicked to take the element inside the template div and append it to the landingzone class element. But at the same time I need the NEWID to change for the new element. Of course this is just an example, the table stuff can be a div or anything else.
the form:
<form method="post">
<input type="text" name="title">
<input type="text" name="number">
<table>
<thead>
<tr> <th>Parts</th> </tr>
</thead>
<tbody class="landingzone">
</tbody>
</table>
<input type="submit" value="Save">
<input type="button" name"add" class="add" value="Save">
</form>
the template:
<div class="template" style="display: hidden">
<tr id="NEWID">
<td>
<input type="text" name="part_NEWID">
</td>
</tr>
</div>
What would be the best way to accomplish this?
Here's an example for your need. The javascript will work without changing any html except in place of name"add" should be name="add"
What i have done here is i'm getting the id of the template tr and setting it with increment and also the input field name.
var $landingzone = $('.landingzone');
var $add = $('.add');
var desiredId = 'id';
$add.on('click', function() {
var $template = $('.template').find('tr');
var id = $template.attr('id');
var idArr = id.split('-');
if (!idArr[1]) {
id = desiredId + '-1';
} else {
id = desiredId + '-' + (parseInt(idArr[1]) + 1);
}
$template.attr('id', id);
$template.find('input').attr('name', 'part_'+id);
console.log('input id--->'+id, 'input name--->'+'part_'+id);
$landingzone.append($template.clone());
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form method="post">
<input type="text" name="title">
<input type="text" name="number">
<table>
<thead>
<tr>
<th>Parts</th>
</tr>
</thead>
<tbody class="landingzone">
</tbody>
</table>
<input type="submit" value="Save">
<input type="button" name="add" class="add" value="Add">
</form>
<table class="template" style="display: none">
<tr id="NEWID">
<td>
<input type="text" name="part_NEWID">
</td>
</tr>
</table>
Like #Andrea said in her comment, some more details would be appreciated ...
I think what you are after is:
const $template = $('.template').clone()
$template.attr('id', 'someId')
$template.find('input[name="part_NEWID"]').attr('name', 'part_someId')
$('.landingzone').append($template)
And if you need it in a function:
function appendTemplateToLandingZone (newId) {
const $template = $('.template').clone()
$template.attr('id', newId)
$template.find('input[name="part_NEWID"]').attr('name', 'part_' + newId)
$('.landingzone').append($template)
}
I haven't tested this, so it might need a slight adjustment. If you'll provide a basic jsbin I'll make it work there.
I have the table:
<table id="form_Dependentes" width="100%" cellpadding="0" cellspacing="0" class="form">
<tr>
<th colspan="4" valign="middle" scope="col">Dependentes</th>
</tr>
<tr>
<td colspan="2"><label>Nome</label><input type="text" name="depNome_01" maxlength="128" /></td>
<td width="20%"><label>Parentesco</label><input type="text" name="depParentesco_01" maxlength="16" /></td>
<td width="20%"><label>Data Nasc.</label><input type="text" name="depDataNasc_01" maxlength="10" /></td>
</tr>
<tr>
<td colspan="2"><label>Nome</label><input type="text" name="depNome_02" maxlength="128" /></td>
<td width="20%"><label>Parentesco</label><input type="text" name="depParentesco_02" maxlength="16" /></td>
<td width="20%"><label>Data Nasc.</label><input type="text" name="depDataNasc_02" maxlength="10" /></td>
</tr>
... etc.
</table>
This table is formatted to be printed and used online. Online, I wish to put buttons to add and remove those lines with input tags above the header. Is not complicate to format the html, but I was thinking about removing and adding tr lines using xml javascript capabilities, but don't know exactly how...
Edit: I don't get what so wrong with this question that is getting negative. Whatever... I'm working in this code:
var cadFormTableRow;
var cadFormTable;
function cadFormAtivar(){
document.getElementById("form_FotoUpload").innerHTML = 'Foto (máximo 1MB): <input name="foto" type="file" accept="image/*;capture=camera">';
document.getElementById("form_Assinatura").innerHTML = '';
document.getElementById("form_Dados").innerHTML = 'Dependentes: <button type="button" onclick="cadFormDep(1);"> + </button> <button type="button" onclick="cadFormDep(-1);"> - </button><br /><button type="button" onclick="cadFormTestar();">Enviar</button>';
cadFormTable = document.getElementById("form_Dependentes");
var nr = cadFormTable.rows.length;
cadFormTableRow = cadFormTable.rows[1];
console.log("Rows: "+nr);
//console.log("Row: "+cadFormTableRow.outerHTML);
for(i=0; i<nr-1; i++){
cadFormTable.deleteRow(1);
}
}
function cadFormDep(a){
if(a>0){
cadFormTable.appendChild(cadFormTableRow);
} else {
var nr = cadFormTable.rows.length;
cadFormTable.deleteRow(nr-1);
}
}
The problem seams to be appendChild is not good, I should go deep in HTMLTableElement, I guess, that's what I like to choose the better approach first... If I could make it work, I'll answer myself, I don't mind you don't like it, it's a free world, right?
It seams HTMLTableElement is the best approach for inserting and deleting rows. HTMLTableElement.insertRow creates a row linked with the original object. Here is the same code with HTMLTableElement corrections needed:
var cadFormTableRow;
var cadFormTable;
function cadFormAtivar(){
document.getElementById("form_FotoUpload").innerHTML = 'Foto (máximo 1MB): <input name="foto" type="file" accept="image/*;capture=camera">';
document.getElementById("form_Assinatura").innerHTML = '';
document.getElementById("form_Dados").innerHTML = 'Dependentes: <button type="button" onclick="cadFormDep(1);"> + </button> <button type="button" onclick="cadFormDep(-1);"> - </button><br /><button type="button" onclick="cadFormTestar();">Enviar</button>';
cadFormTable = document.getElementById("form_Dependentes");
var nr = cadFormTable.rows.length;
cadFormTableRow = cadFormTable.rows[1];
for(i=0; i<nr-1; i++){
cadFormTable.deleteRow(1);
}
}
function cadFormDep(a){
if(a>0){
var row = cadFormTable.insertRow(-1);
var html = cadFormTableRow.innerHTML.replace(/{n}/g, String(cadFormTable.rows.length-1));
row.innerHTML = html;
console.log("Row: "+html);
} else {
var nr = cadFormTable.rows.length;
cadFormTable.deleteRow(nr-1);
}
}
I think working with the cells and inputs as string were easier in this case - I'd pick a sample (as below) and add a number replacing {n} by a numbering:
<tr>
<td colspan="2"><label>Nome</label><input type="text" name="depNome_{n}" maxlength="128" /></td>
<td width="20%"><label>Parentesco</label><input type="text" name="depParentesco_{n}" maxlength="16" /></td>
<td width="20%"><label>Data Nasc.</label><input type="text" name="depDataNasc_{n}" maxlength="10" /></td>
</tr>
This way, every the information will have an unique name.
I know this is proboly the most asked question out there but I have scoured the net and tried several examples and none of them have worked. Here is my issue.
First I have no control over the TR TD structure, can't use DIV.
I need to be able to display certain TD's based on the select dropdown menu value. I have 4 different id's I am using "to", "to_field", "from", "from_field". The script I have shown is not working. Can someone help me out?
Example: If someone selects "In Use" in the dropdown then I just want all the elementID that have "from" and "from_field" to display only. If someone selects a different value then I would like to change that around.
<script type="text/javascript">
function showstuff(element){
document.getElementById("from").style.display = element=="in_use"?"visibility":"visible";
document.getElementById("to").style.display = element=="in_use"?"visibility":"hidden";
document.getElementById("from_field").style.display = element=="in_use"?"visibility":"visible";
document.getElementById("to_field").style.display = element=="in_use"?"visibility":"hidden";
document.getElementById("from").style.display = element=="relocated"?"visibility":"visible";
document.getElementById("to").style.display = element=="relocated"?"visibility":"visible";
document.getElementById("from_field").style.display = element=="relocated"?"visibility":"visible";
document.getElementById("to_field").style.display = element=="relocated"?"visibility":"visible";
}
</script>
<table>
<tr>
<td><h2>Add/Edit Parts</h2></td>
</tr>
</table>
<form action="includes/inventory_parts.php" method="post" name="myform">
<table cellpadding="10" style="border:solid 1px #000000">
<tr>
<td colspan="20"><h3>Add New Part</h3></td>
</tr>
<tr>
<td style="font-weight:bold">Printer Man Part#</td>
<td style="font-weight:bold">Part#</td>
<td style="font-weight:bold">Title</td>
<td style="font-weight:bold">Serial#</td>
<td style="font-weight:bold">Status</td>
<td id="from" style="font-weight:bold;visibility:hidden">From Printer Serial#</td>
<td id="to" style="font-weight:bold;visibility:hidden;">To Printer Serial#</td>
<td style="font-weight:bold">Submit</td>
</tr>
<tr>
<td><input type="text" name="printer_man_part_number" /></td>
<td><input type="text" name="part_number" /></td>
<td><input type="text" name="title" /></td>
<td><input type="text" name="this_part_serial_number" /></td>
<td>
<select name="status" onchange="showstuff(this.value);">
<option></option>
<option value="in_use">In Use</option>
<option value="relocated">Relocated</option>
<option value="disposed">Disposed</option>
<option value="selling">Selling</option>
</select>
</td>
<td id="from_field"><input type="text" name="from" style="visibility:hidden" /></td>
<td id="to_field"><input type="text" name="to" style="visibility:hidden" /></td>
<td><input type="submit" name="submit" value="Add Part" /></td>
</tr>
</table>
</form>
function showstuff(element) {
// first hide everything
document.getElementById("from").style.visibility = 'hidden';
document.getElementById("to").style.visibility = 'hidden';
document.getElementById("from_field").style.visibility = 'hidden';
document.getElementById("to_field").style.visibility = 'hidden';
var targets;
// select the IDs that should be unhidden based on element
switch (element) {
case 'in_use': targets = ['from', 'from_field']; break;
case 'relocated': targets = ['to', 'to_field']; break;
...
}
// now unhide the selected IDs.
for (var i = 0; i < targets.length; i++) {
document.getElementById(targets[i]).style.visibility = 'visible';
}
}
This problem seems to be odd to me and I can't seem to fix it. I do have a simple HTML form; inside, I do have a textbox and a button as shown down here:
<form id="form1" method="get"> <!-- Note: No Action property -->
<div>
<h1>
Simple Test Form</h1>
<table border="0" width="400">
<tr>
<td align="right">
All of these words
</td>
<td>
<input name="txtAll" id="txtAll" type="text" value="testing keyword" />
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" name="Submit" value="Submit" onclick="myJS(this);" />
</td>
</tr>
</table>
</div>
</form>
MyJS file is as:
<script type="text/javascript">
function myJS(which) {
var CONSTANT_SITE_TARGET = "http://servername/redirect/target.aspx?text=";
//capture all values from the form
var allWords = document.getElementById("txtAll").value;
var morestring = ""; //More data manipulation here.....
var url = CONSTANT_SITE_TARGET + allWords + morestring;
window.open(url);
//window.location = url; //Doesn't work
//window.location.href = url; //Doesn't work
//self.location = url; //Doesn't work
//top.location = url; //Doesn't work
}
</script>
As you can see, it doesn't redirect to the designated URL in the javascript. When I use the window.open then it works. Note that in the < form... > tag, I don't put the action property in it. I don't want to open a new browser, just redirect to the new url within the same browser.
Is there a way to redirect it?
Don't use the form tags. Or, set the "type" attribute of your button to be "button", not "submit". The form submits when you click the button, but you don't want that to happen. Either removing the form or changing the button should fix improper redirection. When you don't specify an action, I'm pretty sure the default is the current URL.
Ok, just an idea. As you haven't set the action parameter, the default behaviour of a submit button is to reload the same page. You alter that behaviour by handling its onclick. Maybe there is a conflict that can be resolved by having return false; at the end of the click handler, which prevents the default action for that event.
Here
function myJS(which) {
var CONSTANT_SITE_TARGET = "http://servername/redirect/target.aspx?text=";
//capture all values from the form
var allWords = which.txtAll.value;
var morestring = ""; //More data manipulation here.....
return CONSTANT_SITE_TARGET + allWords + morestring;
}
<form id="form1" method="get" onsubmit="this.action=myJs(this)">
<div>
<h1>
Simple Test Form</h1>
<table border="0" width="400">
<tr>
<td align="right">
All of these words
</td>
<td>
<input name="txtAll" id="txtAll" type="text" value="testing keyword" />
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" name="Submit" value="Submit" />
</td>
</tr>
</table>
</div>
</form>
to elaborate on a comment:
<script>
window.onload=function() {
document.getElementById("Submit").onclick=function() {
var CONSTANT_SITE_TARGET = "http://servername/redirect/target.aspx?text=";
//capture all values from the form
var allWords = document.getElementById("txtAll".value;
var morestring = ""; //More data manipulation here.....
location = CONSTANT_SITE_TARGET + allWords + morestring;
}
}
</script>
<div>
<h1>
Simple Test Form</h1>
<table border="0" width="400">
<tr>
<td align="right">
All of these words
</td>
<td>
<input name="txtAll" id="txtAll" type="text" value="testing keyword" />
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="button" id="Submit" value="Submit" />
</td>
</tr>
</table>
</div>
Try one the options for redirection below. I commented out three of them so that the code stays valid, but you may play around with either and see if it suits your needs.
var CONSTANT_SITE_TARGET = "http://servername/redirect/target.aspx?text=";
//capture all values from the form
var allWords = document.getElementById("txtAll").value;
var morestring = ""; //More data manipulation here.....
var url = CONSTANT_SITE_TARGET + allWords + morestring;
window.location.href= url;
//window.navigate(url);
//self.location(url);
//top.location(url);