How to automatically generate dynamic moment.js? - javascript

The idea would be to make one page a monthly table and each line would have week numbers and edit selection. For this I need moment.js and javascript to generate tables. Define the exact year and generate one table per month, week numbers, and the first day of the week.
I appreciate if you can help me with this.
Here we go jsfiddle and example.
https://jsfiddle.net/n1039cme/1/
Example:
.table-bordered {
border: 1px solid #dee2e6;
}
.table-bordered thead td, .table-bordered thead th {
border-bottom-width: 2px;
}
.table thead th {
vertical-align: bottom;
border-bottom: 2px solid #dee2e6;
}
.table-bordered td, .table-bordered th {
border: 1px solid #dee2e6;
}
table.table thead th {
border-top: none;
}
table.table td, table.table th {
padding-top: 1.1rem;
padding-bottom: 1rem;
}
.table td, .table th {
padding: .75rem;
vertical-align: top;
border-top: 1px solid #dee2e6;
}
table td {
font-size: .9rem;
font-weight: 300;
}
Generate 2019 (target) year months, week number and first day automatically with moment.js. I'm gonna use php to make tables dynamically.</p>
<table id="tablePreview" class="table table-hover table-bordered">
<!--Table head-->
<thead>
<tr>
<th>January</th>
<th>Week first day</th>
<th>Last Name</th>
<th>Username</th>
<th>Edit</th>
</tr>
</thead>
<!--Table head-->
<!--Table body-->
<tbody>
<tr>
<th scope="row">Week number 1</th>
<td>2019-01-01</td>
<td>Otto</td>
<td>#mdo</td>
<td>Edit</td>
</tr>
<tr>
<th scope="row">Week number 2</th>
<td>2019-01-01</td>
<td>Thornton</td>
<td>-</td>
<td>Edit</td>
</tr>
<tr>
<th scope="row">Week number 3</th>
<td>2019-01-01</td>
<td>the Bird</td>
<td>#twitter</td>
<td>Edit</td>
</tr>
</tbody>
</table>
<br><br>
<table id="tablePreview" class="table table-hover table-bordered">
<!--Table head-->
<thead>
<tr>
<th>February</th>
<th>Week first day</th>
<th>Last Name</th>
<th>Username</th>
<th>Edit</th>
</tr>
</thead>
<!--Table head-->
<!--Table body-->
<tbody>
<tr>
<th scope="row">Week number 5</th>
<td>2019-02-01</td>
<td>Otto</td>
<td>#mdo</td>
<td>Edit</td>
</tr>
<tr>
<th scope="row">Week number 6</th>
<td>2019-02-01</td>
<td>Thornton</td>
<td>-</td>
<td>Edit</td>
</tr>
<tr>
<th scope="row">Week number 7</th>
<td>2019-02-01</td>
<td>the Bird</td>
<td>#twitter</td>
<td>Edit</td>
</tr>
</tbody>
</table>
<p>
etc...
</p>
</p>
With moment.js this is all I have done..
var months = [];
for( var i = 0; i < 12; i++ ){
months.push( new Date(0,i).toLocaleString({},{month:'long'}) );
}
console.log(months);

I've quickly scribbled something together for you. This should be enough to get you going:
var thisYear = 2018;
var start = new Date("1/1/" + thisYear);
var defaultStart = moment(start.valueOf());
var weekNumber = 1;
this.months = [];
for (var i = 0; i < 12; i++) {
var weeks = [];
var currentMonth = defaultStart.month();
var monthLimit = i + 1;
if (defaultStart.month() == 11) {
monthLimit = 0;
}
while (defaultStart.month() != monthLimit) {
weeks.push(
{
weekNumber: weekNumber,
firstDayOfWeek: defaultStart.format("MMM Do YYYY")
}
)
weekNumber++;
defaultStart.add(7, 'days')
}
this.months.push(
{
weeks: weeks,
month: moment().month(currentMonth).format("MMMM")
});
}
This will create an array (the months array) for you of 12 objects; this object will contain the name of the month and an array of week objects, which consists of the week number and the first date of the week.
Take a look at this SlackBlitz example, where the table is displayed using the data generated in the code above using the KnockOutJS library.

Related

Group column with the same subheader name in datatable using Javascript/jQuery

I have a table like this
In which I have different city where we have demand-supply of different products.
Now what I want as here demand is different for all the products However supply is the same on all of three product, so I want that table looks like in this manner.
What I want to do is I want only to show the supply column once in the last of the table. This has to be done dynamically as in the future we have multiple products
Can anyone help me with this?
What the code below does is:
Identify the positions of the "Supply"'s and store them in ind array, in this case will be [3, 5, 7]
Loops through ind except for the last element 7(as one "Supply" will be left) and hide all td's; $("td:nth-child("3"), $("td:nth-child("5")
The "Demand"s that precede each of these elements will be assigned two spaces.
let ind = [];
$("td:contains('Supply')").each(function (index) {
ind.push($(this).index() + 1);
});
$(".hide").on("click", function () {
for (let i = 0; i < ind.length - 1; i++) {
let el = $("td:nth-child(" + ind[i] + ")");
el.prev().attr("colspan", "2");
el.hide();
}
});
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th>City</th>
<th colspan="2">Product 1</th>
<th colspan="2">Product 2</th>
<th colspan="2">Product 3</th>
</tr>
<tr>
<td></td>
<td>Demand</td>
<td>Supply</td>
<td>Demand</td>
<td>Supply</td>
<td>Demand</td>
<td>Supply</td>
</tr>
<tr>
<td>City 1</td>
<td>50$</td>
<td>60$</td>
<td>90$</td>
<td>60$</td>
<td>100$</td>
<td>60$</td>
</tr>
<tr>
<td>City 2</td>
<td>50$</td>
<td>60$</td>
<td>90$</td>
<td>60$</td>
<td>100$</td>
<td>60$</td>
</tr>
<tr>
<td>City 3</td>
<td>50$</td>
<td>60$</td>
<td>90$</td>
<td>60$</td>
<td>100$</td>
<td>60$</td>
</tr>
<tr>
<td>City 4</td>
<td>50$</td>
<td>60$</td>
<td>90$</td>
<td>60$</td>
<td>100$</td>
<td>60$</td>
</tr>
</table>
<button class="hide">Hide</button>

Individual column searching (text inputs)

I'm trying to add an individual search box for each table column without success.
What should be added to code below in order to make it work?
Currently my code contains a single search box for first column only.
Please run snippet to get full details.
function myFunction() {
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
p.a {
white-space: nowrap;
}
h2 {
text-align: center;
font-family: Helvetica, Arial, sans-serif;
}
table {
margin-left: auto;
margin-right: auto;
}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 5px;
text-align: left;
font-family: Helvetica, Arial, sans-serif;
font-size: 90%;
white-space:nowrap;
}
table tbody tr:hover {
background-color: #dddddd;
}
.wide {
width: 90%;
}
<h2> Title here </h2>
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name"><table border="1" class="dataframe wide" id="myTable">
<thead>
<tr style="text-align: right;">
<th></th>
<th>KEY</th>
<th>DEVREVSTEP</th>
<th>WW32</th>
<th>WW33</th>
<th>WW34</th>
<th>WW35</th>
<th>WW36</th>
<th>WW37</th>
<th>WW38</th>
<th>WW39</th>
<th>WW40</th>
<th>Rule</th>
<th>LINK</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>First</td>
<td>A</td>
<td>-0.64</td>
<td>6.47</td>
<td>23.14</td>
<td>3.51</td>
<td>0.13</td>
<td>-0.41</td>
<td>-0.59</td>
<td>-0.31</td>
<td>33.13</td>
<td>A</td>
<td>Google.com</td>
</tr>
<tr>
<th>1</th>
<td>Second</td>
<td>B</td>
<td>-18.04</td>
<td>-18.42</td>
<td>-17.44</td>
<td>-16.35</td>
<td>-19.06</td>
<td>-17.49</td>
<td>-18.62</td>
<td>-17.92</td>
<td>-18.23</td>
<td>C</td>
<td>Amazon.com</td>
</tr>
<tr>
<th>2</th>
<td>Third</td>
<td>C</td>
<td>NaN</td>
<td>NaN</td>
<td>-0.59</td>
<td>2.25</td>
<td>-0.33</td>
<td>0.55</td>
<td>-0.53</td>
<td>8.96</td>
<td>17.53</td>
<td>B</td>
<td>Ebay.com</td>
</tr>
<tr>
<th>3</th>
<td>Fourth</td>
<td>A</td>
<td>-0.18</td>
<td>3.25</td>
<td>7.63</td>
<td>1.90</td>
<td>-0.19</td>
<td>0.41</td>
<td>0.15</td>
<td>0.20</td>
<td>17.31</td>
<td>A</td>
<td>Yahoo.com</td>
</tr>
<tr>
<th>4</th>
<td>Fourth</td>
<td>A</td>
<td>0.24</td>
<td>-3.25</td>
<td>-6.42</td>
<td>-1.51</td>
<td>0.60</td>
<td>-0.01</td>
<td>0.25</td>
<td>-0.02</td>
<td>-15.13</td>
<td>A</td>
<td>MSN.com</td>
</tr>
<tr>
<th>5</th>
<td>First</td>
<td>D</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>5.06</td>
<td>NaN</td>
<td>1.27</td>
<td>-0.56</td>
<td>13.24</td>
<td>A</td>
<td>Google.com</td>
</tr>
</tbody>
</table>
If you want to show only rows that are a match for all entered filter values - then you best loop over all the input fields on each change, that is easiest to handle.
I inserted input fields into the table header cells here, and then simply select them using getElementsByTagName - you can change that to a different position and / or using a different method to select them (f.e. by class maybe), it might need some slight adaptations then.
Notice how in both loops I start with the index 1 here, not 0 - to ignore the first table row in the i loop (because the header row should not disappear; could be done differently by selecting only the rows in the tbody to begin with), and to ignore the first cell in the j loop. And since the number of input fields is one less than the number of cells per row, I access the input using index j - 1, got get the one corresponding to the cell index.
This probably leaves room for refinements in several places, but should be enough to illustrate the basic principle.
function myFunction() {
var inputs, table, tr, i, j, inputValue, txtValue, showRow;
inputs = document.getElementsByTagName("input");
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 1; i < tr.length; i++) {
showRow = true;
for (j = 1; j < tr[i].cells.length; j++) {
inputValue = inputs[j - 1].value
txtValue = tr[i].cells[j].textContent || tr[i].cells[j].innerText;
if (inputValue != "" && txtValue.toUpperCase().indexOf(inputValue.toUpperCase()) == -1) {
showRow = false;
break;
}
}
tr[i].style.display = showRow ? "" : "none";
}
}
p.a {
white-space: nowrap;
}
h2 {
text-align: center;
font-family: Helvetica, Arial, sans-serif;
}
table {
margin-left: auto;
margin-right: auto;
}
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
th,
td {
padding: 5px;
text-align: left;
font-family: Helvetica, Arial, sans-serif;
font-size: 90%;
white-space: nowrap;
}
table tbody tr:hover {
background-color: #dddddd;
}
.wide {
width: 90%;
}
<h2> Title here </h2>
<table border="1" class="dataframe wide" id="myTable">
<thead>
<tr style="text-align: right;">
<th></th>
<th><input type="text" onkeyup="myFunction()"><br>KEY</th>
<th><input type="text" onkeyup="myFunction()"><br>DEVREVSTEP</th>
<th><input type="text" onkeyup="myFunction()"><br>WW32</th>
<th><input type="text" onkeyup="myFunction()"><br>WW33</th>
<th><input type="text" onkeyup="myFunction()"><br>WW34</th>
<th><input type="text" onkeyup="myFunction()"><br>WW35</th>
<th><input type="text" onkeyup="myFunction()"><br>WW36</th>
<th><input type="text" onkeyup="myFunction()"><br>WW37</th>
<th><input type="text" onkeyup="myFunction()"><br>WW38</th>
<th><input type="text" onkeyup="myFunction()"><br>WW39</th>
<th><input type="text" onkeyup="myFunction()"><br>WW40</th>
<th><input type="text" onkeyup="myFunction()"><br>Rule</th>
<th><input type="text" onkeyup="myFunction()"><br>LINK</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>First</td>
<td>A</td>
<td>-0.64</td>
<td>6.47</td>
<td>23.14</td>
<td>3.51</td>
<td>0.13</td>
<td>-0.41</td>
<td>-0.59</td>
<td>-0.31</td>
<td>33.13</td>
<td>A</td>
<td>Google.com</td>
</tr>
<tr>
<th>1</th>
<td>Second</td>
<td>B</td>
<td>-18.04</td>
<td>-18.42</td>
<td>-17.44</td>
<td>-16.35</td>
<td>-19.06</td>
<td>-17.49</td>
<td>-18.62</td>
<td>-17.92</td>
<td>-18.23</td>
<td>C</td>
<td>Amazon.com</td>
</tr>
<tr>
<th>2</th>
<td>Third</td>
<td>C</td>
<td>NaN</td>
<td>NaN</td>
<td>-0.59</td>
<td>2.25</td>
<td>-0.33</td>
<td>0.55</td>
<td>-0.53</td>
<td>8.96</td>
<td>17.53</td>
<td>B</td>
<td>Ebay.com</td>
</tr>
<tr>
<th>3</th>
<td>Fourth</td>
<td>A</td>
<td>-0.18</td>
<td>3.25</td>
<td>7.63</td>
<td>1.90</td>
<td>-0.19</td>
<td>0.41</td>
<td>0.15</td>
<td>0.20</td>
<td>17.31</td>
<td>A</td>
<td>Yahoo.com</td>
</tr>
<tr>
<th>4</th>
<td>Fourth</td>
<td>A</td>
<td>0.24</td>
<td>-3.25</td>
<td>-6.42</td>
<td>-1.51</td>
<td>0.60</td>
<td>-0.01</td>
<td>0.25</td>
<td>-0.02</td>
<td>-15.13</td>
<td>A</td>
<td>MSN.com</td>
</tr>
<tr>
<th>5</th>
<td>First</td>
<td>D</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>5.06</td>
<td>NaN</td>
<td>1.27</td>
<td>-0.56</td>
<td>13.24</td>
<td>A</td>
<td>Google.com</td>
</tr>
</tbody>
</table>

JS Sortable Tables with linked rows?

Okay, I have a table. In this table I have a whole bunch of columns, and I would like to use a Sortable Tables javascript so that the user can sort the table as they wish. There are many such JS scripts available (ie: http://tablesorter.com/docs/)
However, the problem I have is that for each row of my table that I want sorted, there is a colspan="4" row right below it that I dont want sorted. In fact, I want these rows linked directly to the row above them so that when those rows get sorted, the 4-span row below it sticks with it.
Is something like this possible?
table {
border: 1px black solid;
width: 100%;
}
thead {
background-color: lightgrey;
text-align: left;
}
.notes {
text-align: right;
}
<table>
<thead>
<tr>
<th>Command</th>
<th>DMG</th>
<th>EXE</th>
<th>TOT</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jouho Touken</td>
<td>19</td>
<td>17</td>
<td>42</td>
</tr>
<tr>
<td colspan="4" class="notes">Opponent crouching (H: Stagger)</td>
</tr>
<tr>
<td>Chouyoushu</td>
<td>25</td>
<td>18</td>
<td>46</td>
</tr>
<tr>
<td colspan="4" class="notes">Damage varies due to distance (25-40)</td>
</tr>
<tr>
<td>Tetsuzankou</td>
<td>40</td>
<td>19</td>
<td>75</td>
</tr>
<tr>
<td colspan="4" class="notes">Super Replay; Damage varies due to distance: 40-80</td>
</tr>
</tbody>
</table>
Here is an example of how you could do this.
Make an array of all rows in the <tbody>.
Group it into pairs. [{data, note}, ...]
Sort by a given sorting function
Flatten back into an array of table rows.
empty the <tbody> tag
Insert into the <tbody> tag everything in the sorted table rows array.
var tableBody = document.querySelector('tbody')
var tableRows = Array
.from(document.querySelectorAll('tbody > tr'))
var notesAndData = []
/* Group elements into
[
{data: <tr>, note: <tr>},
...
]
*/
for(var i = 1; i < tableRows.length; i += 2) {
notesAndData.push({
data: tableRows[i-1],
note: tableRows[i]
})
}
function flatten(arr) {
return arr.reduce(function(acc, curr) {
acc.push(curr.data)
acc.push(curr.note)
return acc
}, [])
}
function repopulateTable(arr) {
tableBody.innerHTML = ''
arr.forEach(function(element) {
tableBody.appendChild(element)
})
}
function sortTable(sortingFunc) {
/* Spread the notesAndData into a new array in
order to not modify it. This syntax is es6 */
var sorted = [...notesAndData].sort(sortingFunc)
repopulateTable(flatten(sorted))
}
function sortByDmg(ascending) {
return function(a, b) {
var aDmg = parseInt(a.data.children[1].textContent)
var bDmg = parseInt(b.data.children[1].textContent)
if (aDmg < bDmg) return ascending ? 1 : -1
return ascending ? 1 : -1
}
}
document
.querySelector('.dmgSort')
.addEventListener('click', function() {
sortTable(sortByDmg(true))
})
table {
border: 1px black solid;
width: 100%;
}
thead {
background-color: lightgrey;
text-align: left;
}
.notes {
text-align: right;
}
<button class="dmgSort">Sort By DMG Ascending</button>
<table>
<thead>
<tr>
<th>Command</th>
<th>DMG</th>
<th>EXE</th>
<th>TOT</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jouho Touken</td>
<td>19</td>
<td>17</td>
<td>42</td>
</tr>
<tr>
<td colspan="4" class="notes">Opponent crouching (H: Stagger)</td>
</tr>
<tr>
<td>Chouyoushu</td>
<td>25</td>
<td>18</td>
<td>46</td>
</tr>
<tr>
<td colspan="4" class="notes">Damage varies due to distance (25-40)</td>
</tr>
<tr>
<td>Tetsuzankou</td>
<td>40</td>
<td>19</td>
<td>75</td>
</tr>
<tr>
<td colspan="4" class="notes">Super Replay; Damage varies due to distance: 40-80</td>
</tr>
</tbody>
</table>

Highlighting a Table

So I'm trying to figure out the best and easiest way to highlight a selection of cells from a table.
#A1lnk, #B1lnk {cursor: pointer;}
<table border="1">
<tr>
<th colspan="2"><a id='A1lnk'>A1</a></th><th colspan="2"><a id='B1lnk'>B1</a></th>
</tr>
<tr>
<td>A1-1</td><td>A1-2</td><td>B1-1</td><td>B1-2</td>
</tr>
<tr>
<td>A1-3</td><td>A1-4</td><td>B1-3</td><td>B1-4</td>
</tr>
<tr>
<td>A1-5</td><td>A1-6</td><td>B1-5</td><td>B1-6</td>
</tr>
<tr>
<th colspan="2"><a id='C1lnk'>C1</a></th><th colspan="2"><a id='D1lnk'>D1</a></th>
</tr>
<tr>
<td>C1-1</td><td>C1-2</td><td>D1-1</td><td>D1-2</td>
</tr>
<tr>
<td>C1-3</td><td>C1-4</td><td>D1-3</td><td>D1-4</td>
</tr>
<tr>
<td>C1-5</td><td>C1-6</td><td>D1-5</td><td>D1-6</td>
</tr>
<tr>
<th colspan="2"><a id='E1lnk'>E1</a></th><th colspan="2"><a id='F1lnk'>F1</a></th>
</tr>
<tr>
<td>E1-1</td><td>E1-2</td><td>F1-1</td><td>F1-2</td>
</tr>
<tr>
<td>E1-3</td><td>E1-4</td><td>F1-3</td><td>F1-4</td>
</tr>
<tr>
<td>E1-5</td><td>E1-6</td><td>F1-5</td><td>F1-6</td>
</tr>
</table>
You can see I have essentially got two columns, A1 and B1. The contents are very simple but suffice to say the actual contents will not be that simple.
I want to be able to click B1 and all the cells below it are highlighted, highlights are the easy part, actually selecting the correct cells is much harder.
I will have multiple other small tables adding C1, D1, E1, F1, G1, H1 etc. So there could be a few extra but only ever in columns of two. They will cascade in the rows and so still be part of the parent table but I'm just trying to figure out the best way to go about it, since the table creates them in rows and not columns.
I tried something like you said, however the code gone very long, that's why I have removed some rows.
var a1lnk = document.getElementById('A1lnk');
var a2lnk = document.getElementById('B1lnk');
var a3lnk = document.getElementById('C1lnk');
var a1 = document.getElementById('a1');
var a2 = document.getElementById('a2');
var c1 = document.getElementById('c1');
var c2 = document.getElementById('c2');
function unhighlight () {
b1.removeAttribute('h');
b2.removeAttribute('h');
a1.removeAttribute('h');
a2.removeAttribute('h');
c1.removeAttribute('h');
c2.removeAttribute('h');
}
var b1 = document.getElementById('b1');
var b2 = document.getElementById('b2');
function highlightA () {
unhighlight();
a1.setAttribute('h', true);
a2.setAttribute('h', true);
}
function highlightB () {
unhighlight();
b1.setAttribute('h', true);
b2.setAttribute('h', true);
}
function highlightC () {
unhighlight();
c1.setAttribute('h', true);
c2.setAttribute('h', true);
}
a1lnk.onclick = highlightA;
a2lnk.onclick = highlightB;
a3lnk.onclick = highlightC;
#A1lnk, #B1lnk, #C1lnk {cursor: pointer;}
td[h] {
background-color: orange;
color: #fff;
}
<table border="1">
<tr>
<th colspan="2"><a id='A1lnk'>A1</a></th><th colspan="2"><a id='B1lnk'>B1</a></th>
</tr>
<tr>
<td id="a1">A1-1</td><td id="a2">A1-2</td><td id="b1">B1-1</td><td id="b2">B1-2</td>
</tr>
<tr>
<th colspan="2"><a id='C1lnk'>C1</a></th>
</tr>
<tr>
<td id="c1">C1-1</td><td id="c2">C1-2</td>
</tr>
</table>
Hope, this should work for you.
You should use a class for header instead of different ids. Then on click of header get it's index. Using this index you can easily select the cells below it using nextUntil() method and :nth-child pseudo selector and highlight them like following.
$('.header').click(function() {
var index = $(this).parent().index(),
a = index * 2 + 1,
b = a + 1;
$('.highlight').removeClass('highlight');
var tr = $(this).closest('tr').nextUntil(':has(th)')
tr.find('td:nth-child(' + a + '), td:nth-child(' + b + ')').addClass('highlight');
});
.header {
cursor: pointer;
}
.highlight {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
<tr>
<th colspan="2"><a class="header">A1</a></th>
<th colspan="2"><a class="header">B1</a></th>
</tr>
<tr>
<td>A1-1</td>
<td>A1-2</td>
<td>B1-1</td>
<td>B1-2</td>
</tr>
<tr>
<td>A1-3</td>
<td>A1-4</td>
<td>B1-3</td>
<td>B1-4</td>
</tr>
<tr>
<td>A1-5</td>
<td>A1-6</td>
<td>B1-5</td>
<td>B1-6</td>
</tr>
<tr>
<th colspan="2"><a class="header">C1</a></th>
<th colspan="2"><a class="header">D1</a></th>
</tr>
<tr>
<td>C1-1</td>
<td>C1-2</td>
<td>D1-1</td>
<td>D1-2</td>
</tr>
<tr>
<td>C1-3</td>
<td>C1-4</td>
<td>D1-3</td>
<td>D1-4</td>
</tr>
<tr>
<td>C1-5</td>
<td>C1-6</td>
<td>D1-5</td>
<td>D1-6</td>
</tr>
<tr>
<th colspan="2"><a class="header">E1</a></th>
<th colspan="2"><a class="header">F1</a></th>
</tr>
<tr>
<td>E1-1</td>
<td>E1-2</td>
<td>F1-1</td>
<td>F1-2</td>
</tr>
<tr>
<td>E1-3</td>
<td>E1-4</td>
<td>F1-3</td>
<td>F1-4</td>
</tr>
<tr>
<td>E1-5</td>
<td>E1-6</td>
<td>F1-5</td>
<td>F1-6</td>
</tr>
</table>

Javascript match/search table for results - total beginner

I am admittedly very inexperienced, but I'm trying to enhance the workflow at my company. I'm using the code from here to create internal site to search for current part numbers. My employees are searching by description, but the javascript included in the example searches by exact input instead of individual words.
For example, using the example code on the site, I would like a search for "Trading Island" to return the same result as "Island Trading". I know this is possible, but can't figure out how to make it work.
<!DOCTYPE html>
<html>
<head>
<style>
* {
box-sizing: border-box;
}
#myInput {
background-image: url('/css/searchicon.png');
background-position: 10px 10px;
background-repeat: no-repeat;
width: 100%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}
#myTable {
border-collapse: collapse;
width: 100%;
border: 1px solid #ddd;
font-size: 18px;
}
#myTable th, #myTable td {
text-align: left;
padding: 12px;
}
#myTable tr {
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
background-color: #f1f1f1;
}
</style>
</head>
<body>
<h2>My Customers</h2>
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">
<table id="myTable">
<tr class="header">
<th style="width:60%;">Name</th>
<th style="width:40%;">Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Germany</td>
</tr>
<tr>
<td>Berglunds snabbkop</td>
<td>Sweden</td>
</tr>
<tr>
<td>Island Trading</td>
<td>UK</td>
</tr>
<tr>
<td>Koniglich Essen</td>
<td>Germany</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Italy</td>
</tr>
<tr>
<td>North/South</td>
<td>UK</td>
</tr>
<tr>
<td>Paris specialites</td>
<td>France</td>
</tr>
</table>
<script>
function myFunction() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
</script>
</body>
</html>
When searching for word matches, it's best to place the search string
into an array and the cell contents to be searched into an array.
Then you can easily use the Array.prototype.every() or the Array.prototype.some() methods to see if all or some of the search words are present in the cell.
See my comments inline below for additional details.
// Get a reference to the input
var searchElement = document.getElementById("myInput");
// Hook element up to event handler:
searchElement.addEventListener("keyup", search);
// Event handler:
function search(){
// Now, break the search input into an array of words by splitting the string where
// there are spaces (regular expression used here to locate the strings).
// Also, note that strings are case-sensitive, so we are taking the input and
// forcing it to lower case and we'll match by lower case later.
var searchWords = searchElement.value.toLowerCase().split(/\s+/);
// Test to see the individual words
//console.clear();
//console.log(searchWords);
// Now you have to have some content to search against.
// So, we'll get all the cells, which will be our data source:
var theCells = document.querySelectorAll("td");
// Loop over each cell
theCells.forEach(function(cell){
// Reset any previous cell matches
cell.style.backgroundColor = "inherit";
// Get the words in the cell as an array (note: we are forcing lower
// case again here to match lower case against lower case
var cellWords = cell.textContent.toLowerCase().split(/\s+/);
// See if the cell contains all of the search words (You can substitute
// "some" for "every" to just see if the cell contains some of the search words
var result = cellWords.every(elem => searchWords.indexOf(elem) > -1);
// every and some return a boolean letting you know if your condition was met:
if(result){
console.clear();
console.log("Match found in: " + cell.textContent);
cell.style.backgroundColor = "#ff0";
}
});
}
<input type="text" id="myInput" placeholder="Search for names.." title="Type in a name">
<table id="myTable">
<tr class="header">
<th style="width:60%;">Name</th>
<th style="width:40%;">Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Germany</td>
</tr>
<tr>
<td>Berglunds snabbkop</td>
<td>Sweden</td>
</tr>
<tr>
<td>Island Trading</td>
<td>UK</td>
</tr>
<tr>
<td>Koniglich Essen</td>
<td>Germany</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Italy</td>
</tr>
<tr>
<td>North/South</td>
<td>UK</td>
</tr>
<tr>
<td>Paris specialites</td>
<td>France</td>
</tr>
</table>

Categories