Multiple countdown timers comparing a given time and current time? - javascript

Really struggling with this part for some reason.
I'm creating a timer I can use to keep track of bids. I want to be able to compare two times and have the difference (in minutes and seconds) shown in the countdown column. It should be comparing the bid start time and the time right now.
Perhaps when it reaches bid start it could also change to show how long until bid ends. Eventually I want to add background changes once it's getting close to the time, and perhaps the ablility to set alarms with a prompt window.
Here's the code I have so far:
HTML
<table>
<tr>
<td>Item Name</td>
<td><input id="itemNameField" placeholder="" type="text"></td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td>Time of Notice</td>
<td><input id="noticeField" type="time"></td>
</tr>
</table>
<input id="addButton" onclick="insRow()" type="button" value="Add Timer">
<div id="errorMessage"></div>
<hr>
<div id="marketTimerTableDiv">
<table border="1" id="marketTimerTable">
<tr>
<td></td>
<td>Item Name</td>
<td>Time of Notice</td>
<td>Bid Start</td>
<td>Bid End</td>
<td>Countdown</td>
<td></td>
</tr>
<tr>
<td></td>
<td>
<div id="itembox"></div>Example Item
</td>
<td>
<div id="noticebox"></div>12:52
</td>
<td>
<div id="bidstartbox"></div>13:02
</td>
<td>
<div id="bidendbox"></div>13:07
</td>
<td>
<div id="countdownbox"></div>
</td>
<td><input id="delbutton" onclick="deleteRow(this)" type="button" value="X"></td>
</tr>
</table>
</div>
JAVASCRIPT
function deleteRow(row) {
var i = row.parentNode.parentNode.rowIndex;
if (i == 1) {
console.log = "hi";
} else {
document.getElementById('marketTimerTable').deleteRow(i);
}
}
function insRow() {
if (itemNameField.value == "" || noticeField.value == "") {
var div = document.getElementById('errorMessage');
div.innerHTML = "*Please fill in the fields*";
div.style.color = 'red';
document.body.appendChild(div);
} else {
var div = document.getElementById('errorMessage');
div.innerHTML = "";
var x = document.getElementById('marketTimerTable');
var new_row = x.rows[1].cloneNode(true);
var len = x.rows.length;
var inp1 = new_row.cells[1].getElementsByTagName('div')[0];
inp1.id += len;
inp1.innerHTML = itemNameField.value;
itemNameField.value = "";
var inp2 = new_row.cells[2].getElementsByTagName('div')[0];
inp2.id += len;
inp2.innerHTML = noticeField.value;
noticeField.stepUp(10);
var inp3 = new_row.cells[3].getElementsByTagName('div')[0];
inp3.id += len;
inp3.innerHTML = noticeField.value;
noticeField.stepUp(5);
var inp4 = new_row.cells[4].getElementsByTagName('div')[0];
inp4.id += len;
inp4.innerHTML = noticeField.value;
var inp5 = new_row.cells[5].getElementsByTagName('div')[0];
inp5.id += len;
inp5.innerHTML = "";
noticeField.value = "";
x.appendChild(new_row);
}
}
I apologize in advance because my code is probably really messy and badly formatted. Here's a JSFIDDLE as well! Thanks :)

To calculate the difference between the current and given time, you can use setInterval
Example :
var noticeTime = noticeField.value.split(":");
const interval = setInterval(function(){
var currentDate = (new Date());
var diffInHours = currentDate.getHours() - noticeTime[0];
var diffInMinutes = currentDate.getMinutes() - noticeTime[1];
inp5.innerHTML = diffInHours + ":" + diffInMinutes;
if(diffInHours === 0 && diffInMinutes === 0) {
clearInterval(interval);
}
},1000)

I managed to do it with the help of the code from ProgXx.
I added the following code:
var noticeTime = noticeField.value.split(":");
var originalTime = noticeField.value.split(":");
const interval = setInterval(function(){
var currentDate = (new Date());
noticeTime[1] = originalTime[1] - currentDate.getMinutes() + 10;
noticeTime[1] = noticeTime[1] + (originalTime[0] * 60) - (currentDate.getHours() * 60);
Here's a JSFIDDLE of the finihsed code: http://jsfiddle.net/joefj8wb/

Related

How to count the occurrences of specified character sequences while editing a textarea?

I'm looking for a way to automatically count the specified words in the textarea without having to click a button to do so, and in that case, auto update it if there are changes..
Here's my chaotic code so far:
function findWord1() {
var outputDiv = $('#opening-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){ }\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a>');
}
function findWord2() {
var outputDiv = $('#closing-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord3() {
var outputDiv = $('#opening-added-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[A>";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord4() {
var outputDiv = $('#closing-added-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "lt;A]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord5() {
var outputDiv = $('#opening-deleted-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[D>";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord6() {
var outputDiv = $('#closing-deleted-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "lt;D]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<button onclick="findWord1();findWord2();findWord3();findWord4();findWord5();findWord6();">Count</button>
<table>
<thead>
<tr>
<th scope="col">Items</th>
<th scope="col">Count</th>
</tr>
</thead>
<tbody>
<tr>
<td>[A></td>
<td><a id="opening-added-bracket"></a></td>
</tr>
<tr>
<td><A]</td>
<td><a id="closing-added-bracket"></a></td>
</tr>
<tr>
<td>[D></td>
<td><a id="opening-deleted-bracket"></a></td>
</tr>
<tr>
<td><D]</td>
<td><a id="closing-deleted-bracket"></a></td>
</tr>
<tr>
<td>[</td>
<td><a id="opening-bracket"></a></td>
</tr>
<tr>
<td>]</td>
<td><a id="closing-bracket"></a></td>
</tr>
</tbody>
</table>
<textarea id="textarea3" rows="5">
[A>
lt;A]
[D>
lt;D]
</textarea>
Also if possible, I'd like to retain the "Count" button so I can still manually do it in case the other parts of the code fails..
Apologies if my code looks so bad, but thank you in advance for any help.
Use keyup Simply do this way
function countWordFunc() {
let myText = document.getElementById("myText").value;
let wordsArr = myText.trim().split(" ")
let countWords = wordsArr.filter(word => word !== "").length
let counter = document.getElementById("counter");
counter.innerHTML = `Total Words: ${countWords}`;
}
<textarea onkeyup="countWordFunc()" id="myText">Hello, World</textarea>
<div id="counter"></div>
There are following issues with the OP's code ...
code based on specific element ids can never be converted into something generic enough in terms of re-usable code.
counting single brackets is hazardous especially since they are part of other to be matched character sequences (which the OP refers to as words).
Thus, one might consider a configurable and generic as possible, poor-mans, component-like approach similar to the next provided example code, where ...
one e.g. can configure the to be matched items via regex patterns.
one furthermore can configure the component's UI/UX behavior like auto-count.
every configuration is based on data-* attributes and its HTMLElement.dataset counterpart.
due to the above 3rd bullet-point a component is agnostic to it's markup as long as the necessary data-* attributes are getting provided correctly.
The approach also could be summarized like with one of my comments ...
"Initialize a component like structure by reading and computing the config settings, and upon the latter register the count handler with the correct events. The count handler itself then is a straightforward regex based pattern matching (which also works correctly unlike all the other solutions) and count rendering task. Element IDs are not needed, markup is freely selectable, configurations are applied via markup and data attributes. One does not need to touch JS code in order to introduce more to be matched items/words."
function displayItemCount(itemRoot, target) {
const elmPattern =
target && itemRoot?.querySelector('[data-reg-pattern]');
const elmCount =
elmPattern && itemRoot?.querySelector('[data-match-count]');
const regXItem =
elmCount && RegExp(elmPattern.dataset.regPattern, 'g');
if (regXItem) {
elmCount.textContent = (target.value.match(regXItem) ?? []).length;
}
}
function displayItemCountsOfBoundComponentData() {
const { rootNode, countsTarget } = this;
rootNode
.querySelectorAll('[data-item-match]')
.forEach(itemRoot =>
displayItemCount(itemRoot, countsTarget)
);
}
function initializeItemCountsComponent(rootNode) {
const { dataset } = rootNode;
let {
countsTargetSelector = '',
triggerCountsSelector = '',
autoCount = false,
} = dataset;
countsTargetSelector = countsTargetSelector.trim();
triggerCountsSelector = triggerCountsSelector.trim();
const countsTarget = (
rootNode.querySelector(countsTargetSelector || null) ||
document.querySelector(countsTargetSelector || null)
);
if (countsTarget) {
let countsTriggers = rootNode
.querySelectorAll(triggerCountsSelector || null);
if (countsTriggers.length === 0) {
countsTriggers = document
.querySelectorAll(triggerCountsSelector || null);
}
const isAutoCount = (
(countsTriggers.length === 0) || (
(autoCount !== false) && (
(autoCount.trim() === '') ||
(autoCount.trim().toLowerCase() === 'true')
)
)
);
const displayItemCounts =
displayItemCountsOfBoundComponentData.bind({
rootNode,
countsTarget,
});
countsTriggers.forEach(elmNode =>
elmNode
.addEventListener('click', displayItemCounts)
);
if (isAutoCount) {
countsTarget
.addEventListener('input', displayItemCounts);
// trigger component's initial item counts.
displayItemCounts();
}
}
}
function main() {
document
.querySelectorAll('[data-item-counts]')
.forEach(initializeItemCountsComponent);
}
main();
body { margin: 0; }
article { position: relative; display: inline-block; margin: 0 20px 0 0; }
[data-item-counts] { float: left; margin: 0 10px 0 0; }
textarea { margin: 0; }
button { position: absolute; left: 0; top: 175px; }
<article>
<table
data-item-counts
data-counts-target-selector="#textarea3"
data-trigger-counts-selector="#count-textarea3-items"
>
<thead>
<tr>
<th scope="col">Items</th>
<th scope="col">Count</th>
</tr>
</thead>
<tbody>
<tr data-item-match>
<td data-reg-pattern="\[A>" title="Opening Added Bracket">[A></td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="<A]" title="Closing Added Bracket"><A]</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="\[D>" title="Opening Deleted Bracket">[D></td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="<D]" title="Closing Deleted Bracket"><D]</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="\[(?!A|D)" title="Opening Bracket">[</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="(?<!<A|D)]" title="Closing Bracket">]</td>
<td data-match-count>.?.</td>
</tr>
</tbody>
</table>
<textarea
id="textarea3"
cols="16"
rows="12">
[A><A][D><D][[]][]<A][D>
[A><A][D><D][[]][]<A][D>
... explicitly triggered count.</textarea>
<button id="count-textarea3-items">Count Items</button>
</article>
<article>
<table
data-item-counts
data-counts-target-selector="#textarea54"
data-auto-count
>
<thead>
<tr>
<th scope="col">Items</th>
<th scope="col">Count</th>
</tr>
</thead>
<tbody>
<tr data-item-match>
<td data-reg-pattern="\[A>" title="Opening Added Bracket">[A></td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="<A]" title="Closing Added Bracket"><A]</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="\[D>" title="Opening Deleted Bracket">[D></td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="<D]" title="Closing Deleted Bracket"><D]</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="\[(?!A|D)" title="Opening Bracket">[</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="(?<!<A|D)]" title="Closing Bracket">]</td>
<td data-match-count>.?.</td>
</tr>
</tbody>
</table>
<textarea
id="textarea54"
cols="16"
rows="12"
>[[]][]<A][D>[A><A][D><D]
... auto-count while editing.</textarea>
</article>
Create a function to call all your others. This is a step toward simplifying your code. Then, create an event listener for the textarea's input event with the new function as its callback.
This question is essentially a duplicate of many other questions involving events. See https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events for some good information, and search for more answers here if you have further questions.
function findAllWords() {
findWord1();
findWord2();
findWord3();
findWord4();
findWord5();
findWord6();
}
document.getElementById('textarea3').addEventListener('input', findAllWords);
function findWord1() {
var outputDiv = $('#opening-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){ }\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a>');
}
function findWord2() {
var outputDiv = $('#closing-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord3() {
var outputDiv = $('#opening-added-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[A>";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord4() {
var outputDiv = $('#closing-added-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "lt;A]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord5() {
var outputDiv = $('#opening-deleted-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[D>";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord6() {
var outputDiv = $('#closing-deleted-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "lt;D]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<table>
<thead>
<tr>
<th scope="col">Items</th>
<th scope="col">Count</th>
</tr>
</thead>
<tbody>
<tr>
<td>[A></td>
<td>
<a id="opening-added-bracket"></a>
</td>
</tr>
<tr>
<td><A]</td>
<td>
<a id="closing-added-bracket"></a>
</td>
</tr>
<tr>
<td>[D></td>
<td>
<a id="opening-deleted-bracket"></a>
</td>
</tr>
<tr>
<td><D]</td>
<td>
<a id="closing-deleted-bracket"></a>
</td>
</tr>
<tr>
<td>[</td>
<td>
<a id="opening-bracket"></a>
</td>
</tr>
<tr>
<td>]</td>
<td>
<a id="closing-bracket"></a>
</td>
</tr>
</tbody>
</table>
<textarea id="textarea3" rows="5">
[A>
lt;A]
[D>
lt;D]
</textarea>
Try this, combined functions into one:
let textarea = $('#textarea3');
textarea.on('keyup', _ => counting());
function counting() {
var searchText = $('#textarea3').val();
let words = [];
words['[A>'] = '#opening-added-bracket';
words['<A]'] = '#closing-added-bracket';
words['[D>'] = '#opening-deleted-bracket';
words['<D]'] = '#closing-deleted-bracket';
words['['] = '#opening-bracket';
words[']'] = '#closing-bracket';
for (const word in words) {
var outputDiv = $(words[word]);
outputDiv.empty();
let count = searchText.split(word).length - 1;
searchText = searchText.replaceAll(word,'');
outputDiv.append('<a>' + count + '</a>');
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button onclick="counting();">Count</button>
<table>
<thead>
<tr>
<th scope="col">Items</th>
<th scope="col">Count</th>
</tr>
</thead>
<tbody>
<tr>
<td>[A></td>
<td><a id="opening-added-bracket"></a></td>
</tr>
<tr>
<td><A]</td>
<td><a id="closing-added-bracket"></a></td>
</tr>
<tr>
<td>[D></td>
<td><a id="opening-deleted-bracket"></a></td>
</tr>
<tr>
<td><D]</td>
<td><a id="closing-deleted-bracket"></a></td>
</tr>
<tr>
<td>[</td>
<td><a id="opening-bracket"></a></td>
</tr>
<tr>
<td>]</td>
<td><a id="closing-bracket"></a></td>
</tr>
</tbody>
</table>
<textarea id="textarea3" rows="5">
[A>
<A]
[D>
<D]
</textarea>

percentages when converting sterling to euro

Hi I am trying to convert Sterling to Euros. But I can't seem to get the percentages correct. I have tried it several ways without luck. The idea is to get 1% of the sterling price then multiply it by the conversion rate and add it to the sterling price to make the euro total, and then do the same with vat.
Hope someone can help, thanks!
Here is my code.
var input = document.querySelectorAll('input');
var conversionRate = input[0];
var sterling = input[1];
var vat = input[2];
var euro = input[3];
init();
function init() {
calculateKeyUp();
}
function calculateKeyUp() {
for (var i = 0; i < input.length; i++) {
input[i].addEventListener("keyup", function() {
//var totalLessVat = (sterling.value) + (conversionRate.value * (sterling.value / 100));
var sterling1Per = sterling.value / 100;
var convert = sterling1Per * conversionRate.value;
var totalLessVat = convert + sterling.value;
//var total = (totalLessVat) + (vat.value * (totalLessVat / 100));
var euro1Per = totalLessVat / 100;
var addVat = euro1Per * vat.value;
var total = addVat + totalLessVat;
euro.value = Math.floor(total);
});
}
}
<div id="calculator-form">
<table>
<tr>
<td>Conversion Rate: </td>
<td><input type="number" id="conversionRate"> %</td>
</tr>
<tr>
<td>Sterling Price: </td>
<td><input type="number" id="sterling"> £</td>
</tr>
<tr>
<td>Vat: </td>
<td><input type="number" id="vat"> %</td>
</tr>
<tr>
<td>Euro Price is </td>
<td><input type="number" id="euro" disabled> €</td>
</tr>
</table>
</div>
The .value of an input is going to be a String, so you will need to parse the number out of each input you are working with. If it's an int you can use:
var sterling1Per = parseInt(sterling.value, 10) / 100;
If it's a float, you can use:
var sterling1Per = parseFloat(sterling.value) / 100;
Anywhere that you use an input .value that needs to be a number needs to be parsed accordingly

jQuery/Javascript compare two tables against each other

I need to compare two HTML tables' rows assuming that data in first cell can be duplicated but data in second cell is always unique. I need to find whether first cell AND second cell in table1 is the same as data in first cell AND second cell in table2 for instance:
Table1:
<Table>
<tr>
<td>123</td>
<td>321</td>
</tr>
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>0</td>
<td>312</td>
</tr>
<tr>
<td>123</td>
<td>323331</td>
</tr>
</Table>
Second table:
<table>
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>545</td>
<td>3122</td>
</tr>
<tr>
<td>123</td>
<td>321</td>
</tr>
</table>
The result of this should be:
123 321 - good, do nothing
545 345 - good, do nothing
545 3122 - wrong its not in table1 <-
Here's what I've got so far...
$('#runCheck').click(function(){
var firstTable = $('#firstDiv table tr');
var secondTable = $('#secDiv table tr');
$(secondTable).each(function(index){
var $row = $(this);
var secTableCellZero = $row.find('td')[0].innerHTML;
var secTableCellOne = $row.find('td')[1].innerHTML;
$(firstTable).each(function(indexT){
if ($(this).find('td')[0].innerHTML === secTableCellZero){
if ($(this).find('td')[1].innerHTML !== secTableCellOne){
$('#thirdDiv').append("first: " + secTableCellZero + " second: " + secTableCellOne+"<br>");
}
}
});
});
});
Where am I going it wrong?
Just to clarify once again:
2nd table says :
row1 - john|likesCookies
row2 - peter|likesOranges
1st table says :
row1 - john|likesNothing
row2 - john|likesCookies
row3 - steward|likesToTalk
row4 - peter|likesApples
now it should say :
john - value okay
peter - value fail.
a lot alike =VLOOKUP in excel
Check this working fiddle : here
I've created two arrays which store values in each row of tables 1 and 2 as strings. Then I just compare these two arrays and see if each value in array1 has a match in array 2 using a flag variable.
Snippet :
$(document).ready(function() {
var table_one = [];
var table_two = [];
$("#one tr").each(function() {
var temp_string = "";
count = 1;
$(this).find("td").each(function() {
if (count == 2) {
temp_string += "/";
}
temp_string = temp_string + $(this).text();
count++;
});
table_one.push(temp_string);
});
$("#two tr").each(function() {
var temp_string = "";
count = 1;
$(this).find("td").each(function() {
if (count == 2) {
temp_string += "/";
temp_string = temp_string + $(this).text();
} else {
temp_string = temp_string + $(this).text();
}
count++;
});
table_two.push(temp_string);
});
var message = "";
for (i = 0; i < table_two.length; i++) {
var flag = 0;
var temp = 0;
table_two_entry = table_two[i].split("/");
table_two_cell_one = table_two_entry[0];
table_two_cell_two = table_two_entry[1];
for (j = 0; j < table_one.length; j++) {
table_one_entry = table_one[j].split("/");
table_one_cell_one = table_one_entry[0];
table_one_cell_two = table_one_entry[1];
console.log("1)" + table_one_cell_one + ":" + table_one_cell_two);
if (table_two_cell_one == table_one_cell_one) {
flag++;
if (table_one_cell_two == table_two_cell_two) {
flag++;
break;
} else {
temp = table_one_cell_two;
}
} else {}
}
if (flag == 2) {
message += table_two_cell_one + " " + table_two_cell_two + " found in first table<br>";
} else if (flag == 1) {
message += table_two_cell_one + " bad - first table has " + temp + "<br>";
} else if (flag == 0) {
message += table_two_cell_one + " not found in first table<br>";
}
}
$('#message').html(message);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<hr>
<table id="one">
<tr>
<td>123</td>
<td>321</td>
</tr>
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>0</td>
<td>312</td>
</tr>
<tr>
<td>123</td>
<td>323331</td>
</tr>
</table>
<hr>
<table id="two">
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>545</td>
<td>3122</td>
</tr>
<tr>
<td>123</td>
<td>321</td>
</tr>
</table>
<hr>
<div id="message">
</div>
</div>
If I understand your requirements, it would be easier to read the first table and store the couples as strings: 123/321, 545/345, etc...
Than you can read the second table and remove from the first list all the rows found in both.
What remains in the list are couples that do not match.
From purely an efficiency standpoint if you loop through the first table just once and create an object using the first cell value as keys and an array of values for second cells, you won't have to loop through that table numerous times
this then makes the lookup simpler also
var firstTable = $('#firstDiv table tr');
var secondTable = $('#secDiv table tr');
var firstTableData = {}
firstTable.each(function() {
var $tds = $(this).find('td'),
firstCellData = $tds.eq(0).html().trim(),
secondCellData == $tds.eq(1).html().trim();
if (!firstTableData[firstCellData]) {
firstTableData[firstCellData] = []
}
firstTableData[firstCellData].push(secondCellData)
})
$(secondTable).each(function(index) {
var $tds = $(this).find('td');
var secTableCellZero = $tds.eq(0).html().trim();
var secTableCellOne = $tds.eq(1).html().trim();
if (!firstTableData.hasOwnProperty(secTableCellZero)) {
console.log('No match for first cell')
} else if (!firstTableData[secTableCellZero].indexOf(secTableCellOne) == -1) {
console.log('No match for second cell')
}
});
I'm not sure what objective is when matches aren't found

Updating row ID when swapping HTML table rows

I've been messing with manipulating HTML tables for the past few weeks and I've come across a problem I am not sure how to fix. So the collection of rows for a table can be iterated over like an array, but if you've switched out the rows a lot, won't the IDs be mixed and doesn't the browser rely on the IDs as the way to iterate over the row objects? I'm running into a problem (probably due to a lack of understanding) where the rows eventually stop moving or one row gets duplicated on top of another. Should I somehow be updating the row's ID each time it is moved? Here is my source so far for this function.
function swap(rOne, rTwo, tblID) {
tblID.rows[rOne].setAttribute('style', 'background-color:#FFFFFF');
var tBody = tblID.children[0];
var rowOne;
var rowTwo;
if (rOne > rTwo) {
rowOne = rOne;
rowTwo = rTwo;
}
else {
rowOne = rTwo;
rowTwo = rOne;
}
var swapTempOne = tblID.rows[rowOne].cloneNode(true);
var swapTempTwo = tblID.rows[rowTwo].cloneNode(true);
hiddenTable.appendChild(swapTempOne);
hiddenTable.appendChild(swapTempTwo);
tblID.deleteRow(rowOne);
var rowOneInsert = tblID.insertRow(rowOne);
var rowOneCellZero = rowOneInsert.insertCell(0);
var rowOneCellOne = rowOneInsert.insertCell(1);
var rowOneCellTwo = rowOneInsert.insertCell(2);
var rowOneCellThree = rowOneInsert.insertCell(3);
rowOneCellZero.innerHTML = hiddenTable.rows[2].cells[0].innerHTML;
rowOneCellOne.innerHTML = hiddenTable.rows[2].cells[1].innerHTML;
rowOneCellTwo.innerHTML = hiddenTable.rows[2].cells[2].innerHTML;
rowOneCellThree.innerHTML = hiddenTable.rows[2].cells[3].innerHTML;
tblID.deleteRow(rowTwo);
var rowTwoInsert = tblID.insertRow(rowTwo);
var rowTwoCellZero = rowTwoInsert.insertCell(0);
var rowTwoCellOne = rowTwoInsert.insertCell(1);
var rowTwoCellTwo = rowTwoInsert.insertCell(2);
var rowTwoCellThree = rowTwoInsert.insertCell(3);
rowTwoCellZero.innerHTML = hiddenTable.rows[1].cells[0].innerHTML;
rowTwoCellOne.innerHTML = hiddenTable.rows[1].cells[1].innerHTML;
rowTwoCellTwo.innerHTML = hiddenTable.rows[1].cells[2].innerHTML;
rowTwoCellThree.innerHTML = hiddenTable.rows[1].cells[3].innerHTML;
tblID.rows[rowOne].setAttribute('onclick', 'chkThis(event, this)');
tblID.rows[rowTwo].setAttribute('onclick', 'chkThis(event, this)');
for (iHiddenDelete = 2; iHiddenDelete >= 1; iHiddenDelete--) {
hiddenTable.deleteRow(iHiddenDelete);
}
}
EDIT: Adding HTML for page and the function for moving between tables which I suspect is causing the issue.
<body>
<form>
<input value="0" type="text" id="cubesum" size="5"/>
<input value="0" type="text" id="wgtsum" size="5"/>
</form>
<form>
<table id="tblSource">
<thead>
<tr>
<th> </th>
<th>Order</th>
<th>Cube</th>
<th>Weight</th>
<th>Move</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<button type="button" onclick="move('tblSource','tblTarget')" style="width: 58px">To Trucks (Down)</button>
<button type="button" onclick="move('tblTarget', 'tblSource')" style="width: 58px">To Orders (Up)</button>
</form>
<form>
<table id="tblTarget">
<thead>
<tr>
<th> </th>
<th>Order</th>
<th>Cube</th>
<th>Weight</th>
<th>Move</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</form>
<table id="hiddenTable" style="display: none"> <!--this table is hidden! -->
<thead>
<tr>
<th> </th>
<th>Order</th>
<th>Cube</th>
<th>Weight</th>
<th>Move</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</body>
</html>
FUNCTION STARTS HERE
function move(from, to) {
var frTbl = document.getElementById(from);
var toTbl = document.getElementById(to);
chkArray.length = 0;
cbsMove = frTbl.getElementsByTagName('input');
for (var oChk = 0; oChk < cbsMove.length; oChk++) {
if (cbsMove[oChk].type == 'checkbox') {
if (cbsMove[oChk].checked == true) {
var prntRow = cbsMove[oChk].parentNode.parentNode;
var prntRowIdx = prntRow.rowIndex;
chkArray.push(prntRowIdx);
cbsMove[oChk].checked = false;
}
}
}
for (iMove = chkArray.length -1; iMove >= 0; iMove--) {
var num = chkArray[iMove];
var row = frTbl.rows[num];
var cln = row.cloneNode(true);
toTbl.appendChild(cln);
frTbl.deleteRow(num);
}
sum();
}
So it turns out that my row cloning for moving between tables was causing malformed HTML where the rows would not longer be inside the table body tags. In addition, not trusting the browser to keep track of the button IDs and using the button IDs to setAttributes to the button also caused button ID overlap eventually. So, I got rid of the node cloning and did the row moving between tables the manual way and used innerHTML to add the function call inside the buttons. Upon further reflection, I've come to learn that some people actually make functions that handle ALL button clicks without calling them inside the button and route them to the proper function depending on the ID or other factors such as parent nodes of the button. Perhaps that is best. The main trick here is to STICK TO ONE METHOD. I was all over the place in how I manipulated the tables and it broke things. Here is the working source for those looking to do similar things.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<style type="text/css">
#selectSource {
width: 320px;
}
#selectTarget {
width: 320px;
}
table, th, td
{
border: 1px solid black;
}
</style>
<title>Loader</title>
<script>
var chkArray = [];
var data = [];
var tmpArray = [];
var iChk = 0;
var swap;
window.onload = function () {
var load = document.getElementById('selectSource')
loadFromAJAX();
}
function loadFromAJAX()
{
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
var rawData = xmlhttp.responseText;
data = JSON.parse(rawData);
for (iData = 0; iData < data.length; iData++) {
newRow = document.getElementById('tblSource').insertRow(iData + 1);
var dn = "dn" + (iData + 1);
var up = "up" + (iData + 1);
cel0 = newRow.insertCell(0);
cel1 = newRow.insertCell(1);
cel2 = newRow.insertCell(2);
cel3 = newRow.insertCell(3);
cel4 = newRow.insertCell(4);
cel0.innerHTML = "<input type='checkbox' name='chkbox'>";
cel1.innerHTML = data[iData].num;
cel2.innerHTML = data[iData].cube;
cel3.innerHTML = data[iData].wgt;
cel4.innerHTML = "<button type='button' onclick=moveUp(this)>up</button><button type='button' onclick=moveDn(this)>down</button>";
}
}
}
xmlhttp.open("POST","http://192.168.3.2/cgi-bin/rims50.cgi/json.p",true);
xmlhttp.send();
}
function moveUp(mvThisRow) {
var mvThisRowRow = mvThisRow.parentNode.parentNode;
var mvThisRowTbl = mvThisRowRow.parentNode.parentNode;
var mvThisRowIndex = mvThisRowRow.rowIndex;
var mvThisRowTblLngth = mvThisRowTbl.rows.length;
var mvFrRow = mvThisRowTbl.rows[mvThisRowIndex];
var mvToRow = mvThisRowIndex - 1;
var mvThisDn = "dn" + (mvToRow) + mvThisRowTbl;
var mvThisUp = "up" + (mvToRow) + mvThisRowTbl;
if (mvThisRowIndex - 1 !== 0) {
moveToRow = mvThisRowTbl.insertRow(mvToRow);
mvRowCel0 = moveToRow.insertCell(0);
mvRowCel1 = moveToRow.insertCell(1);
mvRowCel2 = moveToRow.insertCell(2);
mvRowCel3 = moveToRow.insertCell(3);
mvRowCel4 = moveToRow.insertCell(4);
mvRowCel0.innerHTML = "<input type='checkbox' name='chkbox'>";
mvRowCel1.innerHTML = mvFrRow.cells[1].innerHTML;
mvRowCel2.innerHTML = mvFrRow.cells[2].innerHTML;
mvRowCel3.innerHTML = mvFrRow.cells[3].innerHTML;
mvRowCel4.innerHTML = "<button type='button' onclick=moveUp(this)>up</button><button type='button' onclick=moveDn(this)>down</button>";
mvThisRowTbl.deleteRow(mvThisRowIndex +1);
}
else {
alert("You can't move the top row 'up' try moving it 'down'.");
}
}
function moveDn(mvThisRow) {
var mvThisRowRow = mvThisRow.parentNode.parentNode;
var mvThisRowTbl = mvThisRowRow.parentNode.parentNode;
var mvThisRowTblLngth = mvThisRowTbl.rows.length;
var mvThisRowIndex = mvThisRowRow.rowIndex;
if (mvThisRowIndex + 1 !== mvThisRowTblLngth) {
var mvFrRow = mvThisRowTbl.rows[mvThisRowIndex];
var mvToRow = mvThisRowIndex + 2;
var moveToRow = mvThisRowTbl.insertRow(mvToRow);
var dn = "dn" + (mvToRow) + mvThisRowTbl;
var up = "up" + (mvToRow) + mvThisRowTbl;
mvRowCel0 = moveToRow.insertCell(0);
mvRowCel1 = moveToRow.insertCell(1);
mvRowCel2 = moveToRow.insertCell(2);
mvRowCel3 = moveToRow.insertCell(3);
mvRowCel4 = moveToRow.insertCell(4);
mvRowCel0.innerHTML = "<input type='checkbox' name='chkbox'>";
mvRowCel1.innerHTML = mvFrRow.cells[1].innerHTML;
mvRowCel2.innerHTML = mvFrRow.cells[2].innerHTML;
mvRowCel3.innerHTML = mvFrRow.cells[3].innerHTML;
mvRowCel4.innerHTML = "<button type='button' onclick=moveUp(this)>up</button><button type='button' onclick=moveDn(this)>down</button>";
mvThisRowTbl.deleteRow(mvThisRowIndex);
}
else {
alert("You can't move the bottom row 'down' try moving it 'up'.");
}
}
function sum() {
var trgTbl = document.getElementById('tblTarget');
var tblLength = trgTbl.rows.length;
var sumAddCube = 0;
var sumAddWgt = 0;
document.getElementById("cubesum").setAttribute("value", sumAddCube);
document.getElementById("wgtsum").setAttribute("value", sumAddWgt);
for (iSum = 1; iSum < tblLength; iSum++) {
celCubeNum = trgTbl.rows[iSum].cells[2].innerHTML;
celWgtNum = trgTbl.rows[iSum].cells[3].innerHTML;
sumAddCube = parseInt(sumAddCube) + parseInt(celCubeNum);
sumAddWgt = parseInt(sumAddWgt) + parseInt(celWgtNum);
}
document.getElementById("cubesum").setAttribute("value", sumAddCube);
document.getElementById("wgtsum").setAttribute("value", sumAddWgt);
}
function move(from, to) {
var frTbl = document.getElementById(from);
var toTbl = document.getElementById(to);
chkArray.length = 0;
cbsMove = frTbl.getElementsByTagName('input');
for (var oChk = 0; oChk < cbsMove.length; oChk++) {
if (cbsMove[oChk].type == 'checkbox') {
if (cbsMove[oChk].checked == true) {
var prntRow = cbsMove[oChk].parentNode.parentNode;
var prntRowIdx = prntRow.rowIndex;
chkArray.push(prntRowIdx);
cbsMove[oChk].checked = false;
}
}
}
for (iMove = chkArray.length -1; iMove >= 0; iMove--) {
var num = chkArray[iMove];
var row = frTbl.rows[num];
var toRow = toTbl.rows.length
moveRow = toTbl.insertRow(toRow);
var dn = "dn" + (toRow) + toTbl;
var up = "up" + (toRow) + toTbl;
mvCel0 = moveRow.insertCell(0);
mvCel1 = moveRow.insertCell(1);
mvCel2 = moveRow.insertCell(2);
mvCel3 = moveRow.insertCell(3);
mvCel4 = moveRow.insertCell(4);
mvCel0.innerHTML = "<input type='checkbox' name='chkbox'>";
mvCel1.innerHTML = row.cells[1].innerHTML;
mvCel2.innerHTML = row.cells[2].innerHTML;
mvCel3.innerHTML = row.cells[3].innerHTML;
mvCel4.innerHTML = "<button type='button' onclick=moveUp(this)>up</button><button type='button' onclick=moveDn(this)>down</button>";
frTbl.deleteRow(num);
}
sum();
}
</script>
</head>
<body>
<form>
<input value="0" type="text" id="cubesum" size="5"/>
<input value="0" type="text" id="wgtsum" size="5"/>
</form>
<form>
<table id="tblSource">
<thead>
<tr>
<th> </th>
<th>Order</th>
<th>Cube</th>
<th>Weight</th>
<th>Move</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<button type="button" onclick="move('tblSource','tblTarget')" style="width: 58px">To Trucks (Down)</button>
<button type="button" onclick="move('tblTarget', 'tblSource')" style="width: 58px">To Orders (Up)</button>
</form>
<form>
<table id="tblTarget">
<thead>
<tr>
<th> </th>
<th>Order</th>
<th>Cube</th>
<th>Weight</th>
<th>Move</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</form>
<table id="hiddenTable" style="display: none"> <!--this table is hidden! -->
<thead>
<tr>
<th> </th>
<th>Order</th>
<th>Cube</th>
<th>Weight</th>
<th>Move</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</body>
</html>

Iterate over table cells, re-using rowspan values

I have a simple HTML table, which uses rowspans in some random columns. An example might look like
A | B |
---|---| C
D | |
---| E |---
F | | G
I'd like to iterate over the rows such that I see rows as A,B,C, D,E,C, then F,E,G.
I think I can probably cobble together something very convoluted using cell.index() to check for "missed" columns in later rows, but I'd like something a little more elegant...
without jquery:
function tableToMatrix(table) {
var M = [];
for (var i = 0; i < table.rows.length; i++) {
var tr = table.rows[i];
M[i] = [];
for (var j = 0, k = 0; j < M[0].length || k < tr.cells.length;) {
var c = (M[i-1]||[])[j];
// first check if there's a continuing cell above with rowSpan
if (c && c.parentNode.rowIndex + c.rowSpan > i) {
M[i].push(...Array.from({length: c.colSpan}, () => c))
j += c.colSpan;
} else if (tr.cells[k]) {
var td = tr.cells[k++];
M[i].push(...Array.from({length: td.colSpan}, () => td));
j += td.colSpan;
}
}
}
return M;
}
var M = tableToMatrix(document.querySelector('table'));
console.table(M.map(r => r.map(c => c.innerText)));
var pre = document.createElement('pre');
pre.innerText = M.map(row => row.map(c => c.innerText).join('\t')).join('\n');
document.body.append(pre);
td {
border: 1px solid rgba(0,0,0,.3);
}
<table>
<tr>
<td colspan=2>A</td>
<td rowspan=2>B</td>
</tr>
<tr>
<td>C</td>
<td rowspan=3>D</td>
</tr>
<tr>
<td rowspan=2>E</td>
<td rowspan=4>F</td>
</tr>
<tr></tr>
<tr>
<td rowspan=2 colspan=2>G</td>
</tr>
<tr></tr>
<tr>
<td rowspan=3 colspan=3>H</td>
</tr>
<tr></tr>
<tr></tr>
<tr>
<td colspan=3>I</td>
</tr>
</table>
Try this:
<table id="tbl">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td colspan="2" rowspan="2">A</td>
<td rowspan="2">C</td>
</tr>
<tr>
<td rowspan="2">E</td>
</tr>
<tr>
<td>F</td>
<td>G</td>
</tr>
</table>
Script:
var finalResult = '';
var totalTds = $('#tbl TR')[0].length;
var trArray = [];
var trArrayValue = [];
var trIndex = 1;
$('#tbl TR').each(function(){
var currentTr = $(this);
var tdIndex = 1;
trArray[trIndex] = [];
trArrayValue[trIndex] = [];
var tdActuallyTraversed = 0;
var colspanCount = 1;
$('#tbl TR').first().children().each(function(){
if(trIndex > 1 && trArray[trIndex - 1][tdIndex] > 1)
{
trArray[trIndex][tdIndex] = trArray[trIndex - 1][tdIndex] - 1;
trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex - 1][tdIndex];
finalResult = finalResult + trArrayValue[trIndex][tdIndex];
}
else
{
if(colspanCount <= 1)
{
colspanCount = currentTr.children().eq(tdActuallyTraversed).attr('colspan') != undefined ? currentTr.children().eq(tdActuallyTraversed).attr('colspan') : 1;
}
if(colspanCount > 1 && tdIndex > 1)
{
trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') : 1;
trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex][tdIndex - 1];
colspanCount--;
}
else
{
trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed).attr('rowspan') : 1;
trArrayValue[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).html();
tdActuallyTraversed++;
}
finalResult = finalResult + trArrayValue[trIndex][tdIndex];
}
tdIndex++;
});
trIndex++;
});
alert(finalResult);
Fiddle
i am not sure about the performance, but it works well.
what I understood with your question is: You want to split the merged cell with same value and then iterate the table simply by row.
I've created a JSFiddle that will split the merged cells with the same value. Then you'll have a table that can be iterated simply by rows to get the desired output that you specified.
See it running here http://jsfiddle.net/9PZQj/3/
Here's the complete code:
<table id="tbl" border = "1">
<tr>
<td>A</td>
<td>B</td>
<td rowspan="2">C</td>
</tr>
<tr>
<td>D</td>
<td rowspan="2">E</td>
</tr>
<tr>
<td>F</td>
<td>G</td>
</tr>
</table>
<br>
<div id="test"> </div>
Here's the jquery that is used to manipulate the table's data.
var tempTable = $('#tbl').clone(true);
var tableBody = $(tempTable).children();
$(tableBody).children().each(function(index , item){
var currentRow = item;
$(currentRow).children().each(function(index1, item1){
if($(item1).attr("rowspan"))
{
// copy the cell
var item2 = $(item1).clone(true);
// Remove rowspan
$(item1).removeAttr("rowspan");
$(item2).removeAttr("rowspan");
// last item's index in next row
var indexOfLastElement = $(currentRow).next().last().index();
if(indexOfLastElement <= index1)
{
$(currentRow).next().append(item2)
}
else
{
// intermediate cell insertion at right position
$(item2).insertBefore($(currentRow).next().children().eq(index1))
}
}
});
console.log(currentRow)
});
$('#test').append(tempTable);
You can use this Gist. It supports all the requirements by W3C, even "rowspan=0" (which seems to be only supported by Firefox).

Categories

Resources