How to apply highlight function on each table row? - javascript

I developed a web project where I can upload two files and django server execute a function to return the lines that don't match with other in a pandas dataframe which is renderized in a html template. Is returned a two columns table, file1 and file2. I would like to have another column with the text and text difference 'highlighted'. I have no knowledge about javascript programing, but I don't know how to apply the function on each table row.
My views.py
def index(request):
form = UploadFileForm(request.POST, request.FILES)
if request.method == 'POST':
if form.is_valid():
check = CheckFiles(form.cleaned_data["arquivo1"], form.cleaned_data["arquivo2"]).verifica_tamanho()
if type(check) == str:
return HttpResponse('The file are the same!')
#return HttpResponse(check.to_html())
return render(request, 'index2.html', {'check': check})
else:
print('Invalid Form!')
return render(request, 'index.html', {'form': form})
and in my index2.html:
<table class="table" border="1px">
<thead class="thead-dark">
<tr>
<th scope="col">Original File</th>
<th scope="col">Secondary File</th>
</tr>
</thead>
<tr>
{% for _, record in check.iterrows %}
<tr>
{% for value in record %}
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}
</tr>
</table>
and the highlight javascript function is:
highlight($("#new"), $("#old"));
function highlight(newElem, oldElem){
var oldText = oldElem.text(),
text = '';
newElem.text().split('').forEach(function(val, i){
if (val != oldText.charAt(i))
text += "<span class='highlight'>"+val+"</span>";
else
text += val;
});
newElem.html(text);
}
.highlight {background-color: #B4D5FF}
So, I need some help to understand how to apply this javascript function on each table row.
Thank you, have a nice day.

I can see you also use jquery so:
$(.table tr).each(function(index){
$(this).addClass("highlight");
});
that way you can apply highlight to every row.
It seems like your current highlight function "highlights" chars that have changed in the string but I have no idea what it has to do with rows... What is $("#new") ... what is $("#old")...
**UPDATE **
$("table tr").each(function(index){
a = $(this).find("td");
first_td = a.eq(0);
second_td = a.eq(1);
highlight(second_td, first_td);
});

Related

Auto hide Row / Column of Table if specific field exists in MySQL Database using Django

I am working on a Django project and I am stuck in a situation where I want to hide a row in a table if specific entity exists in column in database. I am using MYSQL database. I want auto hide row without clicking on any button or any checkbox.
page.html:
<table border="2">
<tr>
<th> ID</th>
<th> NAME</th>
<th> PASSWORD</th>
<th> IP</th>
<th>PORT</th>
</tr>
{% for data in Cvs_logs %}
<tr>
<td>{{data.id}}</td>
<td>{{data.user}}</td>
<td>{{data.pass}}</td>
<td>{{data.ip}}</td>
<td>{{data.port}}</td>
</tr>
{% endfor %}
</table>
views.py:
def home_view(request):
auth = Cvs_logs.objects.all()
return render(request, 'page.html', {'Cvs_logs': auth })
models.py:
class Cvs_logs(models.Model):
id = models.BigIntegerField
ip = models.CharField(max_length= 100)
port = models.CharField(max_length= 100)
user = models.CharField(max_length= 100)
pass = models.CharField(max_length= 100)
class Meta:
db_table = "xyz"
The condition is if name == 'abc', then It should hide data automatically without clicking on any button
In views.py you can use exclude so:
def home_view(request):
auth = Cvs_logs.objects.exclude(user="abc") #here
return render(request, 'page.html', {'Cvs_logs': auth })
This will not include the specific data with user = "abc".

Bootstrap multi row selection from table data and post to Flask backend

What I want to do is to let my users select multiple rows in a table and them hit a button to send this data back. My JS script file looks has the following:
<script>
$(document).ready(function () {
// Setup - add a text input to each footer cell
$('#example tfoot th').each(function () {
var title = $(this).text();
$(this).html('<input type="text" placeholder="Search ' + title + '" />');
});
$('#example tbody').on('click', 'tr', function () {
$(this).toggleClass('selected');
});
$('#button').click(function () {
alert(table.rows('.selected').data().length + ' row(s) selected');
});
// DataTable
var table = $('#example').DataTable({
initComplete: function () {
// Apply the search
this.api()
.columns()
.every(function () {
var that = this;
$('input', this.footer()).on('keyup change clear', function () {
if (that.search() !== this.value) {
that.search(this.value).draw();
}
});
});
},
});
});
</script>
My HTML code is as follows:
<form action="/get1" method="POST" name = 'input'>
<button id="button">Row count</button>
<table id="example" class="table table-striped">
<thead>
<tr>
<th scope="col">Index</th>
<th scope="col">Col2</th>
<th scope="col">Col3</th>
<th scope="col">Col4</th>
</tr>
</thead>
<tbody>
{% for item in rows %}
<tr>
<td>{{item[0]}}</td>
<td>{{ item[1] }}</td>
<td>{{ item[2] }}</td>
<td>{{ item[3] }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<th>Index</th>
<th>Col2</th>
<th>Col3</th>
<th>Col4</th>
</tr>
</tfoot>
</table>
</form>
I need some help with JS and HTML to POST values (such as row index) to the backend that the backend can read.
Let's assume you have added the following DataTables Select resources to the head of your web page:
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/select/1.4.0/css/select.dataTables.css"/>
<script type="text/javascript" src="https://cdn.datatables.net/select/1.4.0/js/dataTables.select.js"></script>
Then you can enable the extension by adding the following option to your DataTable:
select: true
Now you can experiment with selecting and de-selecting rows. You can use the CTRL and SHIFT keys to select multiple rows.
In your button click event you can now use the selected() function I mentioned in my comment - for example:
$('#button').click(function () {
selected_ids = [];
table.rows().every(function () {
if ( this.selected() ) {
selected_ids.push( this.data()[0] );
}
});
console.log( selected_ids );
});
This will capture an array of IDs from the selected rows.
Note how it uses very similar logic to the columns().every() function you already have - except it uses rows().every() to iterate over the rows in the DataTable - not only the visible rows in the current page, but also all rows in other DataTables pages (if there multiple pages of table data).
The next step is a completely different question: How to submit the IDs in that array to your Flask back end.
That has been covered elsewhere in various questions - for example: jQuery Ajax POST example with PHP. Yes, this mentions PHP, but the jQuery piece is independent of the server technology.
That question has 25 answers, and there are various other questions along similar lines, which should help you. If you get stuck you can ask a new question with the specific problem you are facing.
But, basically, instead of my console.log( selected_ids );, you would use a jquery Ajax call: $.ajax( { ... } ); to send the data to Flask.

How to update prefix id of a formset

I'm new at python, but no at programing. I'm using Django to create a webapp and in some part, I have to create products. A product has a name, brand and type, but this product can have many "inventories". For example: The product Iphone has a brand Apple, type Phone and since I have 3 in my stock, there is another table that saves 3 individual codes for them (and the price and state as well).
For this solution I have used formsets, and it was working fine without the JS. What I mean is that the process is ok, but when I want to dinamically add a new row to add a new Inventory, is added visually but then when I tried to save it, it just saves the last row. I have looked into the debug console of chrome and it seems that the problem is that the name and ID, of the new row, remains the same as the original one (the prefix I believe), but I don't know how to change it. Here is my code: Note in this image that the prefix of the second row is 0
views.py:
class ProductoInline(InlineFormSetFactory):
model= Inventario
fields = ['codigo', 'Producto', 'Precio', 'Estado']
factory_kwargs = {'extra':1 , 'max_num': 10,
'can_order': False, 'can_delete': False}
class InventarioCreateView(LoginRequiredMixin, CreateWithInlinesView):
model = Producto
inlines = [ProductoInline]
fields = '__all__'
factory_kwargs = {'extra': 3, 'max_num': 10,'can_order': False,
'can_delete': False}
template_name = 'ventas/inventario_form.html'
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
inventario_form.html:
{%extends "ventas/base.html" %}
{% load staticfiles %}
{% load crispy_forms_tags %}
{%block content %}
<section class="card">
<header class="card-header">Crea/actualiza producto</header>
<div class="card-body">
<form method="POST">
{% csrf_token %}
{{ form|crispy }}
{% for formset in inlines %}
<table class="table table-bordered table-responsive-md table-striped text-center">
<tr>
<th class="text-center">Código</th>
<th class="text-center">Precio</th>
<th class="text-center">Estado</th>
<th class="text-center">Eliminar</th>
</tr>
{{formset.management_form}}
<tbody>
{% for form2 in formset %}
<tr id="{{ form2.prefix }}-row" class="dynamic-form">
<td>{{ form2.codigo }}</td>
<td>{{ form2.Precio }}</td>
<td>{{ form2.Estado }}</td>
<td><a id="remove-{{ form2.prefix }}-row" href="javascript:void(0)" class="delete-row">Eliminar</a></td>
</tr>
{% endfor %}
<tr>
<td colspan="4">Añadir producto</td>
</tr>
</tbody>
</table>
{% endfor %}
<button type="submit">Crear producto</button>
</form>
</div>
{%endblock content %}
formset.js:
function updateElementIndex(el, prefix, ndx) {
var id_regex = new RegExp('(' + prefix + '-\\d+)');
var replacement = prefix + '-' + ndx;
if ($(el).attr("for")) $(el).attr("for",
$(el).attr("for").replace(id_regex, replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function addForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
var row = $('.dynamic-form:first').clone(true).get(0);
$(row).removeAttr('id').insertAfter($('.dynamic-form:last')).children('.hidden').removeClass('hidden');
$(row).children().not(':last').children().each(function() {
updateElementIndex(this, prefix, formCount);
$(this).val('');
});
$(row).find('.delete-row').click(function() {
deleteForm(this, prefix);
});
$('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1);
return false;
}
function deleteForm(btn, prefix) {
$(btn).parents('.dynamic-form').remove();
var forms = $('.dynamic-form');
$('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
for (var i=0, formCount=forms.length; i<formCount; i++) {
$(forms.get(i)).children().not(':last').children().each(function() {
updateElementIndex(this, prefix, i);
});
}
return false;
}

I want to display a message to confirm the delete

first of all, even if i want to display a message after click on the table, nothing happened. i didn't understand what is missing for this first step.
At the end, i want to confirm the delete after click on the button delete.
There is my code for each files html.twig and js
main.js:
var produits = document.getElementById('produits');
if (produits) {
produits.addEventListener('click', e => {
// if (e.target.className === 'btn btn-danger') {
// if (confirm('Are you sure?')) {
// const id = e.target.getAttribute('data-id');
//
// fetch(`/Delete/${id}`, {
//
// }).then(res => window.location.reload());
//}
// }
alert(2);
});
}
Affiche.html.twig:
<table class="table table-striped table-bordered" id="produits">
<tr>
<th>Nom</th>
<th>Desctiption</th>
<th>Image</th>
<th>Operation</th>
<th>Actions</th>
</tr>
{% for produit in produits %}
<tr>
<td>{{ produit.nomProduit }}</td>
<td>{{ produit.descriptionProduit }}</td>
<td><img alt="" src="{{ asset('uploads/images/'~produit.imageProduit) }}"></td>
<td>{{ produit.operationProduit }}</td>
<td>
Show
Edit
Delete
</td>
</tr>
{% endfor %}
</table>
An ID is by definition unique, here it seems you can have more than one product so you should set a class to target them all. And moreover you set a "data-id" and not an id. I used "produits-alerte" in my example.
Select products by class and loop over them to add an onClick event, so you can both trigger dialog and get the specific id of the product clicked.
So it leads to :
for (var i = 0, len = produits_alerte.length; i < len; i++) {
produits_alerte[i].onclick = function() {
if (confirm("Are you sure?")) {
console.log('Product ID Clicked : ' + this.getAttribute("data-id"));
//delete product with id above
} else {
//or don't
}
}
}
Here is a working solution using only vanilla JavaScript.
create a function:
<script>
function getvalue() {
alert("Hi");
return;
}
</script>
Link it to the button with 'onClick':
Delete

Flask jinja2 table generation with variable

I'd like to filter dynamically a flask generated table thanks to a variable set in JavaScript from another similar table.
Unfortunately, it seems that Javascript variables cannot be reused in Jinja2 contexts (because jinja2 contexts are run prior to Javascript).
In the example below, I'd like to filter the tasks with the project_id. This project_id was set thanks to the value selected in another table.
Note: I'd like to avoid to reload the page thanks to this solution.
{% for Task in mytasks %}
{% if Task.project_id == var_project_id %} <- Not working, the javascript variable is not recognized
<tr class="clickable-row">
<td style="display:none;"> {{ Task.task_id }} </td>
<td style="display:none;"> {{ Task.project_id }} </td>
<td>{{ Task.title }}</td>
<td class="task_description" > {{ Task.description }} </td>
<td class="task_creation_date"> {{ Task.creation_date }} </td>
</tr>
{% endfor %}
I've found a solution thanks to a simple javascript function.
Here is it, just in case some one else has the same issue:
<script>
//The project id is defined when the project is selected in a hover table
$('#myTableProject tbody tr').click(function (event) {
$('tr').not(this).removeClass('highlight');
$(this).addClass('highlight');
project_id = $(this).find('td.project_id').text();
//...
var tableTasks;
tableTasks = document.getElementById("myTableTasks");
tr = tableTasks.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[1];// [1] is the column number you want to filter
if (td) {
//each cell of the column [1] is compared to the project id
if (td.innerHTML.toUpperCase().indexOf(project_id) > -1) {
tr[i].style.display = "";//the data is displayed
} else {
tr[i].style.display = "none";//the data is hidden
}
} }
</script>
More info:
https://www.w3schools.com/howto/howto_js_filter_table.asp

Categories