I've got a table-like structure with text inputs in which I am trying to make an entire row to be removed with all their children, but first passing the values of cells up one by one
in the rows below to keep IDs numbering structure.
The table structure is like this:
<table cellpadding=0>
<tr id="myRow1">
<td id="#R1C1">
<input class="myCell">
</td>
<td id="#R1C2">
<input class="myCell">
</td>
<td id="#R1C3">
<input class="myCell">
</td>
<td id="#R1C4">
<input class="myCell">
</td>
</tr>
<tr id="myRow2">
<td id="#R2C1">
<input class="myCell">
</td>
<td id="#R2C2">
<input class="myCell">
</td>
<td id="#R2C3">
<input class="myCell">
</td>
<td id="#R2C4">
<input class="myCell">
</td>
</tr>
<!-- ...and so on. -->
</table>
Having this table, when some event is triggered,I make this code run:
var rows = 1; // This value is updated when adding/removing a line
//This code runs from any <tr> by event keyup
if (event.altKey) { // I define here all Alt+someKey actions.
// Getting position values
var currentId = $(this).attr('id');
var row = Number(currentId.split('C')[0].substring(1));
var column = Number(currentId.split('C')[1]);
var belowVal;
if (event.which == 66) { //Case Ctrl+B
// If not the last row, start looping
if (rows > row) {
var diff = rows - row;
// Iteration over rows below
for (var i = 0; i < diff; i++) {
// Iteration over each column
for (var c = 1; c <= 4; c++) {
// here I try to get the value from column below
belowVal = $('#R'+(row+1+i).toString() +
'C'+c.toString()).val();
$('#R'+(row+i).toString()+'C' +
c.toString()).find('.myCell').val(belowVal);
}
}
}
$('#myRow'+rows.toString()).empty();
$('#myRow'+rows.toString()).remove();
rows--;
}
}
It works fine for removing the last row, but, when trying to remove an upper row, the values of current row and the ones below become blank instead of moving up. I made this code for each row below to pass it's values to the upper row, but it isn't doing what I wanted.
Why is this happening? I couldn't figure it out.
The problem seem to be, that the ids you are using to access the values are not the ids of the input elements, but rather the ids of the containing table cells.
Here an approach, which doesnt use the ids, but relies on the nodes structure instead, code not tested:
if (event.which == 66) {
var currentrow = $(this);
var currentinputs = currentrow.find('input.myCell');
while(var nextrow = currentrow.next('tr')) {
var nextinputs = nextrow.find('input.myCell');
currentinputs.each(function(index,element){
element.val(nextinputs.get(index).val());
});
currentrow = nextrow;
currentinputs = nextinputs;
}
currentrow.remove();
}
RESOLVED
Thanks to #JHoffmann, I was able to resolve my problem like this:
for (var c = 1; c <= 4; c++) {
// here I try to get the value from column below
belowVal = $('#R'+(row+1+i).toString()+'C'+c.toString())
.find('.myCell').val();
$('#R'+(row+i).toString()+'C'+c.toString())
.find('.myCell').val(belowVal);
}
In the line that assigns a value to belowVal, I forgot to call the method .find('.myCell') before calling .val(). That was the mistake that caused my code to fail, as #JHoffmann commented in his answer.
Related
I need to create a Javascript function (using a loop) that receives a value as a parameter from a function call in HTML and in response passes back the image of the back of a playing card however many times the value of the parameter is.
For example, if I pass the value 5 to the function, I should get back 5 images of the back of the card from the function displayed on the HTML page inside an existing table.
Here is what I have so far. Can someone please point me in the right direction as to where I'm going wrong (Thank you in advance for any help).
JS
function showCards(numcards) {
var data = "";
while (numcards < 5) {
data += "<td><img src="http://www.college1.com/images/cards/gbCard52.gif" NAME="card0"></td>";
numcards +=;
}
document.writeln(data);
}
HTML
<table border=0 style='margin:auto'>
<tr>
<td>
<form>
<input type="BUTTON" onClick="Javascript:alert('Dummy Link')" value="Deal > > >">
</form>
</td>
<script type="text/javascript">showCards(5)</script>
<td>
<form>
<input type="BUTTON" onClick="Javascript:alert('Dummy Link')" value="< < < Hit Me">
</form>
</td>
</tr>
</table>
There are mainly syntax errors in your code.
Either escape the double quote inside a string (ie. "\"") or use single quotes to declare your string.
You were trying to increment numcards using a wrong syntax. The correct syntax is numcards++.
But that's not what you want, you want to decrement it to 0 (ie. numcard--) to get your number of cards or count up to numcards using a for loop for example.
function showCards(numcards) {
var data = "";
for (var i = 0; i < numcards; i++) {
data += '<td><img src="http://www.college1.com/images/cards/gbCard52.gif" NAME="card0"></td>';
}
document.writeln(data);
}
showCards(5);
<table border=0 style='margin:auto'>
<tr>
<td>
<form><input type="BUTTON" onClick="Javascript:alert('Dummy Link')" value="Deal > > >"></form>
</td>
<td>
<form><input type="BUTTON" onClick="Javascript:alert('Dummy Link')" value="< < < Hit Me"></form>
</td>
</tr>
</table>
// where you want to append images tag
var table = document.querySelector('tbody');
// you can call this method on click event
function show(elem , param) {
var i = 0;
var data = document.createElement("tr");
var td = "";
while (param != i) {
td += "<td><img src='http://www.college1.com/images/cards/gbCard52.gif' NAME='card"+i+"'></td>";
i++;
}
data.innerHTML = td;
// append html tr node
elem.appendChild(data);
}
// calling when the script is loaded
show(table, 5);
<table>
<tbody>
</tbody>
</table>
I have a MVC web app in which I show a table.
Some of my rows can have a similar id, on which I need to show only one checkbox for all those rows, and individual checkboxes for the rows which don't have a matching id. Something like below:
row1 and row2 have the same id, hence the checkbox is in between them (denoted by red checkbox).
row3, row4 have different ids, hence they need to have their individual checkboxes (denoted by green).
I know I need to play on the rowspan property, but I am unable to visualize how to get on it.
Below is the sample code:
[Route("Search")]
[HttpGet]
public async Task<IActionResult> Search()
{
//Some API call
return View("Search", model);
}
View Code:
<table id="tblsearch">
#if (Model.HasRecords)
{
var counter = 0;
<tbody>
#foreach (var item in Model.SearchResults)
{
<tr>
<td>
<input type="checkbox" id="Dummy_#counter" name="chkSearch" data-id="#item.Id"/>
<label for="Dummy_#counter"></label>
</td>
<td>#item.FullAddress</td>
<td>#item.Price</td>
<td>#item.OfficeName</td>
}
else
{
<tr><td>Data Not Found</td></tr>
}
</table>
I am trying to first hide all the checkboxes, then trying to match the id's in each row, and then if the ids of 2 rows are same, I am trying to increase the rowspan by 2.
js code:
function pageLoad()
{
var rowCount = $('#tblSearch >tbody >tr').length;
for(var i=0;i<rowCount-1;i++)
{
$('#Dummy_' + i).hide();
}
var searchArray= [];
for (var i = 0; i < rowCount - 1; i++) {
searchArray[i]= $('#tblSearch >tbody >tr')[i].attr('data-id');
}
}
Please guide how to proceed.
You should control the layout of the page in this instance from your View, please forgive my syntax as I primarily work in vbhtml these days.
Important things are to order your search results (in case they aren't already)
Remember and update the last processed Id.
<table id="tblsearch">
#if (Model.HasRecords)
{
var counter = 0;
var lastId = -1;
<tbody>
#foreach (var item in Model.SearchResults.OrderBy(x=>x.Id))
{
<tr>
#if(lastId!= item.Id){
<td rowspan="#(Model.SearchResults.Count(x=>x.Id == item.Id) > 0 ? Model.SearchResults.Count(x=>x.Id == item.Id) : 1 )">
<input type="checkbox" id="Dummy_#counter" name="chkSearch" data-id="#item.Id"/>
<label for="Dummy_#counter"></label>
</td>
}
<td>#item.FullAddress</td>
<td>#item.Price</td>
<td>#item.OfficeName</td>
#lastId = item.Id;
//I assume there was code snipped here...
}
else
{
<tr><td>Data Not Found</td></tr>
}
</table>
There is no need for any javascript. You can simply group your items by the Id property and conditionally render the checkbox column with a rowspan attribute if its the first item in the group.
<tbody>
#foreach (var group in Model.SearchResults.GroupBy(x => x.Id))
{
bool isFirstRow = true;
foreach (var item in group)
{
<tr>
#if (isFirstRow)
{
<td rowspan="#group.Count()">
#Html.CheckBox("chkSearch")
</td>
isFirstRow = false;
}
<td>#item.FullAddress</td>
<td>#item.Price</td>
<td>#item.OfficeName</td>
</tr>
}
}
</tbody>
I have a table that makes automatically 2 calculations:
Calculation of numbers of days after the selection of arrived and departed date from two input date field with calendar, result is stored is field (nbjours)
Multiplication of 3 fields (nbcheveaux * days* price), result is stored ind field (total)
There is a button that when we click on it a new row is added. How can i reproduce the same automatic calculations on the news rows added after click ?
1- my add rows function
window. addRow = function addRow(btn) {
var parentRow = btn.parentNode.parentNode;
var table = parentRow.parentNode;
var tr = document.createElement("tr");
var tdNbC = document.createElement("td");
var tdDateArrive = document.createElement("td");
var tdDateDepart = document.createElement("td");
var tdNbJour = document.createElement("td");
var tdPrix = document.createElement("td");
var tdTotal = document.createElement("td");
var td3 = document.createElement("td");
var inputDateArrive = document.createElement("input");
var inputDateDepart = document.createElement("input");
inputDateArrive.type = "text";
inputDateDepart.type = "text";
inputDateArrive.setAttribute("class", "date");
inputDateDepart.setAttribute("class", "date1");
var inputNbrC = document.createElement("input");
var inputNbrJour = document.createElement("input");
var inputPrix = document.createElement("input");
var inputTotal = document.createElement("input");
var inputButton = document.createElement("button");
inputButton.type = "button";
inputButton.innerHTML = "+";
inputButton.onclick = function(){
addRow(this);
};
tdNbC.appendChild(inputNbrC);
tdDateArrive.appendChild(inputDateArrive);
tdDateDepart.appendChild(inputDateDepart);
tdNbJour.appendChild(inputNbrJour);
tdPrix.appendChild(inputPrix);
tdTotal.appendChild(inputTotal);
td3.appendChild(inputButton);
tr.appendChild(tdNbC);
tr.appendChild(tdDateArrive);
tr.appendChild(tdDateDepart);
tr.appendChild(tdNbJour);
tr.appendChild(tdPrix);
tr.appendChild(tdTotal);
tr.appendChild(td3);
table.appendChild(tr);
$(inputDateDepart).mask("99/99/9999");
$(inputDateArrive).mask("99/99/9999");
}
2- function that calculate numbers of days
$(document).ready(function() {
$('.date1').change(function() {
var start = $('.date').datepicker('getDate');
var end = $('.date1').datepicker('getDate');
if (start<end) {
var days = (end - start)/1000/60/60/24;
$('.days').val(days);
}
else {
alert ("Depated date must be greater that arrived date!");
$('.date').val("");
$('.date1').val("");
$('.days').val("");
}
}); //end change function
}); //end ready
3- Function that operate the multiplication
$('.nbrcevaux,.days,.price').keyup(function() {
var nbrcevaux = parseInt($('.nbrcevaux').val());
var days = parseInt($('.days').val());
var prix = parseInt($('.price').val());
$('.total').val(nbrcevaux * days * prix );
});
4- HTML Table
<table>
<tr>
<td class="centrer">Nbr de chevaux</td>
<td class="centrer">Arrived Date</td>
<td class="center">Departed Date</td>
<td class="centrer">Nb/Days</td>
<td class="centrer">Prix/jr/ cheval/boxe</td>
<td class="centrer"> Total</td>
</tr>
<tr>
<td><input type="text" name="nbrcevaux" class="nbrcevaux" /></td>
<td><input type="text" name="datearrive" class ="date"/> </td>
<td><input type="text" name="datedepart" class ="date1" /></td>
<td><input type="text" name="nbrjours" class ="days" /></td>
<td><input type="text" name="prix" class="price" /></td>
<td><input type="text" name="total" class="total" /></td>
<td><button type="button" onClick ="addRow(this)">+</button> </td>
</tr>
How can i integrate the functions calculate numbers of days and multiplication in the added new row displyed after click ?
So, I was bored and tackled your question, by rewriting it because you had quite a bit of superfluous code.
Your main issue (with the calculations on the added rows) stems from the fact that you were relying on classes to uniquely identify elements, but that won't cut it. Each new row and element within the row needs to have its own unique id.
I also took the liberty of making sure that there will only ever be one "Add row" button, as you'll see.
This working example has comments inline to help follow what's going on.
$(function() {
// Declare & initialize module wide variables to store DOM elements:
var $txtnbrcevaux = $("#nbrcevaux"), $txtDateArrive = $("#dateArrive"),
$txtDepart = $("#datedepart"), $txtnbrjours = $("#nbrjours"), $txtPrix = $("#prix"),
$txtTotal = $("#total"), $btnAdd = $("#btnAddRow"), $masterRow = $("#master1");
// Unique value that will identify new elements
var count = 1;
// Establish the date picker fields
$txtDateArrive.datepicker();
$txtDepart.datepicker();
// Wire up the button's click event:
$btnAdd.on("click", function(){
// Make a copy of the last row
var newTR = $("tr[id=master" + count + "]").clone(true);
// Update the new row's id to be unique
newTR[0].id = "master" + (count + 1);
// Loop through the child elements and modify their id's so that they are unique
newTR.children().each(function(index){
if(this.children.length > 0){
// Wipe out old (copied values)
this.firstChild.value = "";
var oldID = this.firstChild.id;
this.firstChild.id = oldID.substring(0, oldID.length) + (count + 1);
// Cloning datepickers creates problems because the clones remain bound to the
// original input element. Here, we'll create a new input element and then
// insert it where the current one is, then we'll remove the current one:
if($(this.firstChild).is(".date, .date1")){
var newPicker = document.createElement("input");
newPicker.id = this.firstChild.id;
newPicker.name = this.firstChild.name;
newPicker.setAttribute("class", this.firstChild.className.replace(" hasDatepicker", ""));
newPicker.style.width = "80px";
// Set up the new datepicker:
$(newPicker).insertAfter(this.firstChild);
$(this.firstChild).remove();
$(newPicker).datepicker();
}
}
});
// Increment the count so the next row will use the next number for its id's
count++;
// Hide the last row's button
this.style.display = "none";
// Add the new row to the table
$("table").append(newTR);
// Commented due to not having plugin available
// $(inputDateDepart).mask("99/99/9999");
// $(inputDateArrive).mask("99/99/9999");
});
$('.nbrcevaux, .days, .price').on("keyup", function() {
var nbrCevaux = this.parentElement.parentElement.querySelector(".nbrcevaux").value;
var days = this.parentElement.parentElement.querySelector(".days").value;
var prix = this.parentElement.parentElement.querySelector(".price").value;
// Your problem was that you were trying to work with values from
// classes and not specific elements. Changing the function to expect
// the data to be passed to it and having it return the answer allow
// you to control what goes in and where to put what comes out
this.parentElement.parentElement.querySelector(".total").value = nbrCevaux * days * prix;
});
$txtDepart.change(function() {
var start = $txtDateArrive.datepicker('getDate');
var end = $txtDepart.datepicker('getDate');
if (start < end) {
var days = (end - start)/1000/60/60/24;
$txtnbrjours.val(days);
} else {
alert ("Depated date must be greater that arrived date!");
$txtDateArrive.val("");
$txtDepart.val("");
$txtnbrjours.val("");
}
}); //end change function
}); //end ready
/* This is only added to shrink things down so they appear within the space allotted */
input[type=text] {width:80px;}
body {font-size:.5em;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>
<table>
<tr>
<td class="centrer">Nbr de chevaux</td>
<td class="centrer">Arrived Date</td>
<td class="center">Departed Date</td>
<td class="centrer">Nb/Days</td>
<td class="centrer">Prix/jr/ cheval/boxe</td>
<td class="centrer"> Total</td>
</tr>
<tr id="master1">
<td><input type="text" id="nbrcevaux" name="nbrcevaux" class="nbrcevaux"></td>
<td><input type="text" id="dateArrive" name="dateArrive" class ="date"></td>
<td><input type="text" id="datedepart" name="dateDepart" class ="date1"></td>
<td><input type="text" id="nbrjours" name="nbrjours" class ="days"></td>
<td><input type="text" id="prix" name="prix" class="price"></td>
<td><input type="text" id="total" name="total" class="total"></td>
<td><button type="button" id="btnAddRow">+</button> </td>
</tr>
</table>
Right now I'm learning nodes. before that I'm sorry if my question isn't specific please let me know how to state it better.
This code is for deleting element attributes.
There's a color in the table column and when I press button the attribute bgcolor in td tag is gone.
When I run it, it always show tdelement is null? while I already use for statement to loop and check it.
And please answer it using Javascript.
function removeColor(color)
{
var table = document.getElementById("multi");
var tdList = table.getElementsByTagName("td");
// Loop through list <td> elements.
for (var i = 0; i <= tdList.length; i++)
{
var tdElement = tdList.item(i);
// Get the attribute.
var colorAtt = tdElement.getAttribute("value");
//If the attribute matches the color then delete attributes
if (colorAtt == color)
{
tdElement.removeAttributeNode(colorAtt);
}
}
}
// the end for javascript -----------------
<table id="multi" border="1">
<tr>
<td></td>
<td bgcolor="#ff0000">1</td>
<td bgcolor="#008000">2</td>
<td bgcolor="#ffff00">3</td>
</tr>
<tr>
<td bgcolor="#ff0000">1</td>
<td bgcolor="#ff0000">1</td>
<td bgcolor="#008000">2</td>
<td bgcolor="#ffff00">3</td>
</tr>
<tr>
<td bgcolor="#008000">2</td>
<td bgcolor="#008000">2</td>
<td bgcolor="#008000">4</td>
<td bgcolor="#ffff00">6</td>
</tr>
<tr>
<td bgcolor="#ffff00">3</td>
<td bgcolor="#ffff00">3</td>
<td bgcolor="#ffff00">6</td>
<td bgcolor="#ffff00">9</td>
</tr>
</table>
<button onclick="removeColor('#ff0000')">Remove Red Background</button><br>
try this
function removeColor(color)
{
var table = document.getElementById("multi");
var tdList = table.getElementsByTagName("td");
// Loop through list <td> elements.
for (var i = 0; i <= tdList.length; i++)
{
var tdElement = tdList.item(i);
// Get the attribute.
var colorAtt = tdElement.getAttributeNode("bgcolor");
//If the attribute matches the color then delete attributes
if (colorAtt && (colorAtt.value == color))
{
tdElement.removeAttributeNode(colorAtt);
}
}
}
using .getAttribute("value"); would try to get the attribute 'value' from the element. where you need to get the node .getAttributeNode("bgcolor");.
Fiddle
I have a form which displays multiple rows from database with 4 columns. From these record I need to write a new value in 4th column and update database record. But whenever I try, only First Row value can be updated/read. But not the other rows!! This can be due to the same "name=redirection" as it is given to each from "for loop". So, how can I get the values from other rows too??
for (int i=0; i<domains.size(); i++) {
domainprops = (String[]) domains.get(i);
%>
<table cellspacing="0" cellpadding="10" border="0" class="tableview" width="100%">
<td width="150"><input type="text" id="domains" name="domains" value="<%=domainprops[0]%>"></td>
<td width="160"><input type="text" name="defaulturl" value="<%=domainprops[1]%>" size="30"></td>
<td width="160"><input type="text" name="redirecturl" value="<%=domainprops[2]%>" size="30"></td>
<td width="160"> <input type="text" id="redirection" name="redirection"></td>
<td align="right"><a href="javascript:win2('recordUpdate.jsp?domains=<%=domainprops[0]%>
')">[Update]</a></td>
</tr>
</table>
<% } %>
Javascript Code :
function win2(urlPath) {
var winl = (screen.width-200)/2;
var wint = (screen.height-100)/2;
var settings = 'height=100,width=200,directories=no,resizable=no,status=no,scrollbars=no,menubar=no,location=no,top=' + wint + ',left=' + winl;
var changeurls=document.getElementById("redirection").value;
urlPath+='&rdirect='+changeurls
editWin.focus();
}
An ID in the DOM is supposed to be unique. If any element in the DOM has an ID, it should not be shared by any other element.
What I would suggest doing is appending your loop counter on to the end of the ID. This will ensure that every element you create in the DOM has its own unique ID.
for (int i=0; i<domains.size(); i++) {
domainprops = (String[]) domains.get(i);
...
<input type="text" id="domains_<%= i %>" name="domains" value="<%=domainprops[0]%>">
...
<input type="text" id="redirection_<%= i %>" name="redirection"></td>
</tr>
</table>
}
Next, pass the loop counter to the win2 function call:
<td align="right"><a href="javascript:win2('recordUpdate.jsp?domains=<%=domainprops[0]%>
', <%= i %>)">[Update]</a></td>
Finally, adjust the function itself...
function win2(urlPath, loopID) {
...
var changeurls=document.getElementById("redirection_" + loopID).value;
urlPath+='&rdirect='+changeurls
...
}
EDIT: Please read the answer referring to having multiple elements with the same ID. You should not be using multiple of the same ID.
You could use Javascript to iterate over redirection form elements.
function loopThroughRedirection(form) {
var result = "";
for (var i = 0; i < form.elements.length; i++) {
if (form.elements[i].name == 'redirection') {
// Do something to retrieve the value of redirection
result += form.elements[i].value
}
}
return result;
}