Template for Image grid and select - javascript

I am working on a website withDjango, and I would like to make a page where:
There is a table listing all the images of a model
There are two available space two show the images selected by the user
Example:
image grid display
Currently, in my template I produce the table like that:
<table class="table table-striped table-advance table-hover">
<tr>
<th>Field 1</th>
<th>Field 2</th>
<th>Field 3</th>
</tr>
{% for imagemodel in imagemodel %}
<tr>
<td>{{ imagemodel.image }}</td>
<td>{{ imagemodel.date_taken }}</td>
<td>{{ imagemodel.image.url }}</td>
</tr>
{% endfor %}
</table>
I don't know what would be the best way to make my wish feasable:
Is it possible to do that only with javascript ? or only html ?
Should I work through my django view ?
Many thanks for your help, I am lost :/
Cheers.

I found my solution pure javascript:
var image1 ='';
var tbl = document.getElementById("galleryTable");
if (tbl != null) {
for (var i = 0; i < tbl.rows.length; i++) {
for (var j = 2; j < tbl.rows[i].cells.length; j++)
tbl.rows[i].cells[j].onclick = function () { getval(this); };
}
}
function getval(cel) {
image1 = tbl.rows[cel.parentNode.rowIndex].cells[2].innerHTML;
document.getElementById("2x2_topleft_image_tag").src=image1;
}

Related

Compare 2 columns data of a row and highlight one having same match using javascript

I have a query regarding javascript. I am working on a structure with nested tables and rows (tr) are in the loop and inside it (td) are also in the loop. I want to compare the data of 2 columns one outside the loop and one td inside the loop and in case of a match would like to highlight the td outside the loop. Here is a piece of code that I wrote but it is highlighting all the rows rather than only the corresponding one. Also, it's not running on all the td which are inside the for-loop.
function highlight_text(){
table = document.getElementById("table");
tr = table.getElementsByClassName("rows");
for (x = 0; x < tr.length; x++) {
td = tr[x].getElementsByTagName("td")[3];
txtValue = td.textContent || td.innerText;
txtValue = txtValue.trim()
search_text = tr[x].getElementsByTagName("td")[5];
search_value = search_text.textContent || search_text.innerText
search_value = search_value.trim()
if (txtValue.toUpperCase().indexOf(search_value.toUpperCase()) > -1) {
const regex = new RegExp(search_value,"gi");
let text = tr[x].getElementsByTagName("td")[3].innerHTML;
text = text.replace(/(<mark>|<\/mark>)/gim, '');
text = text.replace(regex, '<mark>$&</mark>')
td.innerHTML = text
}
}
}
<table id="table" style="border: none;">
{% for a in range(respondent_id|length) %}
<tr class="rows">
<td class="c1" colspan="2"><b>{{ Score[a] }}</b></td>
<td><span style="display:none;" id="id_resp">{{ respondent_id[a] }}</span></td>
<td>
<table width="980px;" style="border-color:white;">
<tr>
<td class="verb">{{ Verbatim_data[a] }}</td>
</tr>
</table>
<table>
<tr>
{% for w in range(Final_L1L2L3|length) %}
<td class="L3_comment" onclick="highlight_text()"><div>{{Final_L1L2L3[w] | safe}} </div></td>
<td style="display: none;" class="search">{{Final_verb[w] | safe}}</td>
{% endfor %}
</tr>
</table>
</td>
</tr>
{{endfor}}
</table>
enter image description here

HTML Table fixed first column, cell text is not behind sticky column

I'm trying to have an html table where the first column is sticky. I followed other advice on using position: sticky. I'm also using some javascript because I'm building the table dynamically depending on the data passed to the DOM. The following code works as expected:
html
<table class="table table-hover">
<thead>
<tr>
<th scope="col" class="filled">Person</th>
<th scope="col"># Items 1</th>
<th scope="col"># Items 2</th>
<th scope="col"># Items 3</th>
<th scope="col"># Items 4</th>
<th scope="col"># Items 5</th>
<th scope="col"># Items 6</th>
<th scope="col"># Items 7</th>
<th scope="col"># Items 8</th>
<th scope="col"># Items 9</th>
<th scope="col"># Items 10</th>
<th scope="col"># Items 11</th>
<th scope="col"># Items 12</th>
<th scope="col"># Items 13</th>
<th scope="col"># Items 14</th>
<th scope="col"># Items 15</th>
<th scope="col"># Items 16</th>
</tr>
</thead>
<tbody>
<tr>
<td id="row_1" class="filled">Jim</td>
<td id="row_1_col_1">64</td>
<td id="row_1_col_2">12</td>
<td id="row_1_col_3">33</td>
<td id="row_1_col_4">32</td>
<td id="row_1_col_5">59</td>
<td id="row_1_col_6">64</td>
<td id="row_1_col_7">12</td>
<td id="row_1_col_8">33</td>
<td id="row_1_col_9">32</td>
<td id="row_1_col_10">59</td>
</tr>
<tr>
<td id="row_2" class="filled">Sam</td>
<td id="row_2_col_1">83</td>
<td id="row_2_col_2">12</td>
<td id="row_2_col_3">32</td>
<td id="row_2_col_4">27</td>
<td id="row_2_col_5">9</td>
<td id="row_2_col_6">83</td>
<td id="row_2_col_7">12</td>
<td id="row_2_col_8">32</td>
<td id="row_2_col_9">27</td>
<td id="row_2_col_10">9</td>
</tr>
<tr>
<td id="row_3" class="filled">Ted</td>
<td id="row_3_col_1">11</td>
<td id="row_3_col_2">39</td>
<td id="row_3_col_3">77</td>
<td id="row_3_col_4">68</td>
<td id="row_3_col_5">93</td>
<td id="row_3_col_6">11</td>
<td id="row_3_col_7">39</td>
<td id="row_3_col_8">77</td>
<td id="row_3_col_9">68</td>
<td id="row_3_col_10">93</td>
</tr>
</tbody>
</table>
javascript
var rowName = [];
var cellName = [];
var numberPeople = 3;
var numberItems = 10;
var score = 5
for(var n=0; n < (numberPeople); n++) {
for(var i = 0; i < numberItems; i++) {
// +1 b/c starts at 0
rowName[n] = "row_" + (n + 1) + "_col_" + (i+1);
cellName[n] = document.createElement('td');
document.getElementById(rowName[n]).appendChild(cellName[n]);
switch (score) {
case 5:
document.getElementById(rowName[n]).style.backgroundColor = "#fff";
document.getElementById(rowName[n]).style.opacity += "0.5";
break;
}
}
}
css
.table th:first-child,
.table td:first-child {
position: sticky;
left: 0;
z-index: 6;
}
.table .filled {
background-color: #fff;
}
Here is the jsfiddle link.
However, when I try to use this code in my actual webpage, it does not work as expected. In my actual webpage, the text in the table cells that scrolls will sit over top of the sticky column (whereas in the jsfiddle, the cell text will go behind the sticky column - hidden by the background-color: #fff).
The webpage code and js is almost the same as the jsfiddle, the css is the same for both.
html
<div class="container ps-4">
<div class="row">
<div class = "table-responsive">
<table id="grade-table" class="table table-bordered table-sm ">
<thead>
<tr>
<th scope="col" class="filled">Students</th>
{% for obj in objective_list %}
<th scope="col">{{ obj.objective_name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for student in student_list %}
<tr>
<td id="row_{{ forloop.counter }}" class="filled">{{ student }}</td>
{% for obj in objective_list %}
<td id="row_{{ forloop.parentloop.counter }}_col_{{ forloop.counter }}"></td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div>
javascript
<script>
// gradeArray contains number of students & objectives, objective name and score for each objective
var gradeArray = {{ grade_report|safe }};
var numberStudent = gradeArray.shift();
var numberObj = gradeArray.shift();
if (numberObj > 0) {
var obj = []
for (var g = 0; g < numberObj; g++) {
obj[g] = gradeArray.shift();
}
}
var rowName = [];
var studentname = [];
var objective = [];
var cellName = [];
if (numberObj > 0) {
for(var n=0; n < (numberStudent); n++) {
for(var i = 0; i < numberObj; i++) {
// +1 b/c starts at 0
rowName[n] = "row_" + (n + 1) + "_col_" + (i + 1);
cellName[n] = document.createElement('td');
// numberObj + 2 b/c in the array one index is the name and the other is the grade
let score = gradeArray[(n)*(numberObj+2)+i+1];
cellName[n].innerHTML = score
document.getElementById(rowName[n]).appendChild(cellName[n]);
//document.getElementById(rowName[n]).style.color = "grey";
switch (score) {
case 'BEG':
case 'EMG':
document.getElementById(rowName[n]).className += "table-danger";
break;
case 'DEV':
document.getElementById(rowName[n]).className += "table-warning";
break;
case 'APP':
case 'PRF':
document.getElementById(rowName[n]).className += "table-success";
break;
case 'APP+':
case 'PRF+':
document.getElementById(rowName[n]).className += "table-info";
break;
case 'EXT':
document.getElementById(rowName[n]).className += "table-primary";
break;
case '---':
case 'I':
document.getElementById(rowName[n]).className += "table-secondary";
document.getElementById(rowName[n]).style.opacity += "0.5";
break;
}
}
}
}
</script>
There are a couple of tags in here from the django framework such as {{ student }} but I don't think they are problem - they're just how I'm passing data to the DOM. It's also how I iterate through the data. All of the text, colors, data, displays as expected except for the cell data/text not scrolling behind the sticky column.
My webpage is using boostrap 4, I don't know if that is causing the issue.
Edit
I have set up a demo account to see this issue live. Here is the direct link to a page that will show issue, you may need to make your browser window a bit more narrow to bring up the table scrolling.
username: Demo
password: demodemo
I just checked out your website and the following CSS changes fix the issue:
First, remove the z-index from this CSS selector (style.css):
.table th:first-child, .table td:first-child {
position: sticky;
left: 0;
/* z-index: 6; */
Instead, add a z-index to your .filled elements:
.table .filled {
background-color: #fff;
z-index: 1;
}
Also, in order to get rid of the rows being shown left to the row header (when scrolling), remove (or overwrite) the padding on this element (bootstrap's _grid.scss):
.row>* {
flex-shrink: 0;
width: 100%;
max-width: 100%;
padding-right: calc(var(--bs-gutter-x) * .5);
/* padding-left: calc(var(--bs-gutter-x) * .5); */
margin-top: var(--bs-gutter-y);
}

Counting entries in a table using Javascript

I'm using django to list the number of cars sold in a particular dealership. (assuming there are only red and blue cars)
I have designed the query in such a way that we could visualise cars at a monthly or weekly or yearly level. so the data in the table in going to be changing , so I have written the following javascript code to read the table that will be generated everytime . I have also used pagination to include only 10 in a page.
The code just reads what is available on the first page and returns 10 every single time whereas I need it to consider all the pages . Can someone help
<script>
function counter(){
var j = 6; //j=6 is the column id for colour in my table , so I'm, directly using it
var total = 0;
var red= 0;
var blue= 0;
var table = document.getElementById("datatable");
for (var i = 1, row; row = table.rows[i]; i++)
{
var Row = document.getElementById("datatable").rows[i].cells[j].innerHTML;
var colour = document.getElementById("datatable").rows[i].cells[j].innerHTML;
//alert(document.getElementById("datatable").rows[i].cells[j].innerHTML);
if (colour == "red")
{
red= red+ 1;
}
else if (colour== "blue")
{
blue= blue+ 1;
}
total = red+ blue;
}
document.getElementById("total_count").innerText = total;
document.getElementById("red_count").innerText = red;
document.getElementById("blue_count").innerText = blue;
}
</script>
HTML to the table
<div class="menu">
<table cellpadding="0" id="datatable" style="margin-top: 20px" style="margin-bottom:20px" class="table" >
<thead>
<tr class="text-light bg-dark">
<th class="text-center" >Date</th>
<th class="text-center" >Model</th>
<th class="text-center" >CustomerName</th>
<th class="text-center" >Mobile</th>
<th class="text-center" >Adress</th>
<th class="text-center" >Delivery</th>
<th class="text-center" >Colour</th>
</tr>
</thead>
<tbody>
{% for obj in filter.qs %}
<tr>
<td class="text-center" >{{ obj.Date}}</td>
<td class="text-center" >{{ obj.Model}}</td>
<td class="text-center" >{{ obj.CustomerName}}</td>
<td class="text-center" >{{ obj.Mobile}}</td>
<td class="text-center" >{{ obj.Address}}</td>
<td class="text-center" >{{ obj.Delivery }}</td>
<td class="text-center" >{{ obj.Qa_Decision }}</td>
since there table with id 'datatable' exist, im assuming you using DataTables library
if you not using server side datatables pagination, you can access all data with rows().data() refrence https://datatables.net/reference/api/rows().data()
if your using server side datatables or even not using datatables
you only can count that data in backend(django), since js cant access all that data

pagination for table rows with fixed tablehead

On my website I created a "dynamic" table. I want to include a pagination, to only show 10 rows at a time. The table head shall be displayed above the rows on every page.
But with my pagination function, all the content within is put under "Ref.". If I uncomment the commented part, the pagination does not work at all.
What needs to changed in my code to display the table correct on each page? (all ref{{i}} under "Ref." / "score{{i}} under "Score" /...)
Table:
{% if empty == False %}
<table style="float: left; width: 100%" class="table table-hover">
<thead id="header">
<tr >
<th>Ref.</th>
<th>Score</th>
<th>Title</th>
</tr>
</thead>
<tbody>
{% for i in range (0,numofresults) %}
<tr id="cardmb3n{{i}}">
<td id="ref{{i}}"> </td>
<td id="score{{i}}" "> </td>
<td>
<div>
<a id="header{{i}}" href=""></a><br>
<a id="hyperlink{{i}}" href="" ></a>
</div>
</td>
</tr>
</tbody>
{% endfor %}
</table>
Pagination:
{% if empty == False %}
function paginate(page){
var val = parseInt(document.getElementById("currentpage").innerHTML);
if(page=='Next'){
page = val + 1;
} else if(page=='Previous'){
page = val - 1;
} else{
page = parseInt(page);
}
if(val!=page){
for(var j = 0; j<ergebnisliste.length; j++){
if(j>=(page-1)*10 && j<10*page){
// document.geElementById("header").style = "display:table";
document.getElementById("cardmb3n" + j).style = "display:block";
}else{
// document.geElementById("header").style = "display:none";
document.getElementById("cardmb3n" + j).style = "display:none";
}
}
........some code.........
}
}
{% endif %}
found a solution: document.getElementById("cardmb3n" + j).style = "display:table-row";

Loop through elements in a HTML table

I am learning Javascript, in a school assignment we have to by using a loop count how many games was made in 2014.
It does not return anything in the console, where have I gone wrong?
var allGames = document.getElementsByTagName('td');
var array = Array.prototype.slice.call(allGames, 0)
var games14 = 0;
for (var i = 0; i < array.length; ++i) {
if (array[i] == 2014) {
games14++;
console.log(games14)
}
}
<table id="games">
<thead>
<tr>
<th>Titel</th>
<th>Genre</th>
<th>Årstal</th>
</tr>
</thead>
<tbody id="games_tbody">
<tr class="horror">
<td class="title">Outlast</td>
<td>Horror</td>
<td>2013</td>
</tr>
<tr class="rpg">
<td class="title">Dragon Age: Inquisition</td>
<td>Role-playing Game</td>
<td>2014</td>
</tr>
<tr class="rpg">
<td class="title">Skyrim</td>
<td>Role-playing Game</td>
<td>2011</td>
</tr>
<tr class="horror">
<td class="title">Amnesia: The Dark Descent</td>
<td>Horror</td>
<td>2010</td>
</tr>
<tr class="simulator">
<td class="title">Scania Truck Driving Simulator</td>
<td>Simulator</td>
<td>2012</td>
</tr>
<tr class="horror">
<td class="title">Five Nights at Freddy’s</td>
<td>Horror</td>
<td>2014</td>
</tr>
<tr class="simulator">
<td class="title">Sims 4</td>
<td>Simulator</td>
<td>2014</td>
</tr>
<tr class="rts" id="last">
<td class="title">Warcraft III: Reign of Chaos</td>
<td>Real-time Strategy</td>
<td>2002</td>
</tr>
</tbody>
</table>
You need to check for its text:
var allGames = document.getElementsByTagName('td');
...
if (array[i].innerHTML == '2014') {
OR,
if(array[i].innerText == '2014' || array[i].textContent == '2014'){
No need to do Loop through elements in a HTML table.. You can simply use regular expressions to count all occurrences within the games_tbody:
var games14 = document
.getElementById('games_tbody')
.innerText
.match(/2014/g)
.length;
console.log('Games made in 2014:', games14);
<table id="games">
<thead>
<tr><th>Titel</th><th>Genre</th><th>Årstal</th></tr>
</thead>
<tbody id="games_tbody">
<tr class="horror"><td class="title">Outlast</td><td>Horror</td><td>2013</td></tr>
<tr class="rpg"><td class="title">Dragon Age: Inquisition</td><td>Role-playing Game</td><td>2014</td></tr>
<tr class="rpg"><td class="title">Skyrim</td><td>Role-playing Game</td><td>2011</td></tr>
<tr class="horror"><td class="title">Amnesia: The Dark Descent</td><td>Horror</td><td>2010</td></tr>
<tr class="simulator"><td class="title">Scania Truck Driving Simulator</td><td>Simulator</td><td>2012</td></tr>
<tr class="horror"><td class="title">Five Nights at Freddy’s</td><td>Horror</td><td>2014</td></tr>
<tr class="simulator"><td class="title">Sims 4</td><td>Simulator</td><td>2014</td></tr>
<tr class="rts" id="last"><td class="title">Warcraft III: Reign of Chaos</td><td>Real-time Strategy</td><td>2002</td></tr>
</tbody>
</table>
array[i] == 2014
Everything in the array will be an HTML Table Data Cell Element object.
Nothing in the array will be the Number 2014.
You need to read the text content from the element and then compare that.
I think this is a better way.
var table = document.getElementById("games");
count = 0;
for (let i = 0; row = table.rows[i]; i++) {
if (row.cells[2].innerHTML === "2014"){
count++;
}
/*
for (let j = 0; col = row.cells[j]; j++) {
if (col.innerHTML === "2014"){
count++;
}
}
*/
}
console.log(count);
The commented code is for checking every item on a single row.

Categories

Resources