I am trying to update the text inside a cell that contains also an input box.
In line $(ib).closest('td').prop('textContent',888); I am assigning the value 888 to the text but this results in assignment of cell's text to "888" but also for some reason deleting the input box.
My code (Django template):
{% extends "base.html" %}
{% block head_scripts %}
<script type="text/javascript" src="/static/script/api_recs.js"></script>
<script type="text/javascript" src="/static/script/site_filter.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css"/>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/1.2.2/css/buttons.dataTables.min.css"/>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/2.5.0/jszip.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/buttons/1.2.2/js/dataTables.buttons.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/buttons/1.2.2/js/buttons.html5.min.js"></script>
{% endblock %}
{% block title %}
Schedule Match
{% endblock %}
{% block styles %}
<style type="text/css">
tfoot {
display: table-header-group;
}
</style>
{% endblock %}
{% block content %}
<table id='pm_table' class="display" cellspacing="0" width="100%">
<thead>
<tr>
{% for col_name in table_headers%}
<th>{{col_name}}</th>
{% endfor %}
</tr>
</thead>
<tfoot>
<tr>
{% for col_name in table_headers%}
<th>{{col_name}}</th>
{% endfor %}
</tr>
</tfoot>
<tbody>
{% for data_row in table_data%}
<tr>
{% for item in data_row%}
<td>{{item}}</td>
{% endfor%}
</tr>
{% endfor %}
</tbody>
</table>
<script>
$(document).ready(function() {
var SITE_ID_COL = 0;
var PRIORITY_COL = 3;
var IS_SCHEDULED_COL = 4;
// priority input box
$("#pm_table td:nth-child(" + PRIORITY_COL + ")").each(function() {
// $(this).children().css('visibility', 'hidden');
$(this).css('text-align', 'center');
// $(this).css('font-size', 0);
var $input_box = $('<input type="text" class="priority_changed" />')
$input_box.prop('value', $(this).text());
$input_box.prop('size', 1);
$input_box.css('text-align', 'center');
$input_box.prependTo(this);
});
// remember old value of input box
$("#pm_table td:nth-child(" + PRIORITY_COL + ")").on('focus', '.priority_changed', function() {
this.old_val = this.value;
});
// priority input box listener
$('#pm_table').on('change', '.priority_changed', function() {
var $changed_tr = $(this).closest('td').closest('tr');
var site_id = $changed_tr.children().eq(SITE_ID_COL).text();
var old_val = parseInt($(this).closest('td').text());
var ib = this;
// confirm change
if (!confirm('Change priority for site ' + site_id + ' from ' + this.old_val + ' to ' + this.value + " ?")) {
//revert input box value
$(this).prop('value', this.old_val);
} else {
// make the change in db
new_val = this.value;
var url = '/api/manage/schedule_match/set_priority/' + site_id + '/' + new_val + '/';
$.ajax({
type: 'POST',
url: url,
success: function(result) {
res = JSON.parse(result) // todo read res
alert('SUCCESSFULLY changed priority for site ' + site_id + ' from ' + ib.old_val + ' to ' + res.new_val + ".");
$(ib).closest('td').prop('textContent',888);
},
error: function() {
alert('ERROR updating database!');
//revert input box state
$(ib).prop('value', ib.old_val);
},
});
}
});
</script>
{% endblock %}
I tried $(ib).closest('td').text(888); and many different properties like innerText, innerHtml,$(ib).closest('td').childNodes[1].prop('text',888) but without result in right direction.
What am I doing wrong here?
You should change your template to have a span inside td. Like:
<tbody>
{% for data_row in table_data%}
<tr>
{% for item in data_row%}
<td><span>{{item}}</span></td>
{% endfor%}
</tr>
{% endfor %}
</tbody>
Then you can use $(ib).closest('td').children('span').text(888) to change the text without deleting the input box.
Related
Actually I'm working with the following datatable:
Data Table code:
<table aria-describedby="dataTable_info" cellspacing="0" class="table table-hover dataTable" id="dataTable" role="grid" style="width:100%;" width="100%">
<thead>
<tr>
<th>{{'fsaGeneralPlan.table.Auditors'|trans({}, 'FSABundle')}}</th>
<th>{{'fsaGeneralPlan.table.Audits'|trans({}, 'FSABundle')}}</th>
<th>{{'fsaGeneralPlan.table.Areas'|trans({}, 'FSABundle')}}</th>
</tr>
</thead>
<tbody>
{% for audit in auditsByArea %}
{% set myArray = audit.Audits|split(',') %}
{% set AuditsStatus = audit.AuditsStatus|split(',') %}
<tr>
<td>{{ audit.Auditor }}</td>
<td>
{# {% set long = numberOfAudits|length + 2 %} #}
{# <h1>{{ long }}</h1> #}
{% for i in 0..3 %}
{% set e = i + 1 %}
<a title="{{ AuditsStatus[i] }}" class="btn btn-outline-primary btn-sm auditButton {{ AuditsStatus[i] }}" data-id="Audit{{ myArray[i] }}" data-area="{{ audit.area_name }}" data-status="{{ AuditsStatus[i] }}" id="auditButton{{ myArray[i] }}" name="auditButton">{{'w' ~ e }}</a>
{# <input class ="auditButton {{ AuditsStatus[i] }} mx-2" value="{{'W' ~ i }}" href="" data-id="Audit{{ myArray[i] }}" data-area="{{ audit.area_name }}" data-status="{{ AuditsStatus[i] }}" id="auditButton{{ myArray[i] }}" name="auditButton" type='text' readonly ></input> #}
{% endfor %}
</td>
<td>{{ audit.area_name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
And I have this Javascript to change the class of the buttons in the datatable once that the page is loaded:
<script type="text/javascript">
$(document).ready(function(){
$(".auditButton.Submitted").removeClass('btn-outline-primary');
$(".auditButton.Submitted").addClass('btn-outline-success');
$(".auditButton.Expired").addClass('btn-outline-danger');
$(".auditButton.Capturable").addClass('btn-outline-warning');
});
It works correctly but just in the first page of the datatable, it does not work in the other pages.
Any idea or subject of how to fix it or what is wrong?
You need to listen to the draw event for your table.
Why?
Your current setup works fine for the first page, because those elements are all rendered when $(document).ready() fires. However, the other pages are rendered after the document is ready.
Try:
const table = $('#dataTable').DataTable();
// Event listener for DT 1.10+
table.on('draw', function() {
$(".auditButton.Submitted").removeClass('btn-outline-primary');
$(".auditButton.Submitted").addClass('btn-outline-success');
$(".auditButton.Expired").addClass('btn-outline-danger');
$(".auditButton.Capturable").addClass('btn-outline-warning');
});
Doing this, you can also remove the same block of code from `$(document).
You can also place all this inside the draw callback for your datatable if you'd prefer:
const table = $('#dataTable').DataTable({
drawCallback: function(settings) {
// changes in here
}
});
I cannot send selected value to test.html.
I wrote codes
<form method="post" action="">
<select id="mainDD" data-placeholder="Choose" class="chzn-select" style="width:600px;" name="main">
{% for i in json_data.items.values %}
<option value="{{forloop.counter}}">{{ i }}</option>
{% endfor %}
</select>
{% for key, values in preprocessed %}
<select name="type" id=type{{forloop.counter}}>
{% for counter, value in values %}
<option value="{{forloop.counter}}">{{ value }}</option>
{% endfor %}
</select>
{% endfor %}
</form>
<script type="text/javascript">
$(document).ready(function () {
$('#mainDD').on('change', function() {
var thisType = "type" + $(this).val();
for(i=1; i<6; i++) {
var thisId = "type" + i;
if(thisType !== thisId) {
$("#"+thisId).hide();
}
else {
$("#"+thisId).show();
}
}
}).trigger('change');
});
</script>
<form id="postform" action="app/test_view" method="GET">
{% csrf_token %}
<input type="submit" value="SEND">
</form>
<script type="text/javascript">
var key = $('select[name="main"] option:selected').text();
var value = $('select[name="type"] option:selected').text();
var array1 = [];
var array2 =[];
document.querySelector("input[type=submit]").onclick = e => {
const test = window.open(`test_view?${key}=${value}`, "_blank");
}
</script>
But now test.html shows
I wrote test.html
<h2>RESULTS</h2>
<script type="text/javascript">
onload = () => {
document.body.appendChild(
document.createTextNode([...new URLSearchParams(location.search).entries()])
);
}
</script>
I selected i(actually value is A) & value(actually value is a-1) in index.html so I wanna show in test.html like
These 2 selected buttons load json file like
{
"items":
{
"---":"---",
"A":"A",
"B":"B",
},
"type1":
{
"---":"---",
"a-1":"a-1",
"a-2":"a-2",
},
"type2":
{
"---":"---",
"b-1":"b-1",
"b-2":"b-2",
}
}
How should I fix this?What should I write it?Is it garbled?or code error?
Here I found the following helpful javascript to dynamically add a form to my python/django template. Here is the code:
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) {
// Make a variable and assign to it a string convertd to an integer. The string is the variable
// with the the #id assigned to it. The value of this attribute is saved. The value will equal
// the current number of forms
var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
// Find the element with the given class, and clone it after loading the 0 index get request.
// Var row is now a cloned row.
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;
}
Then I have my following template.
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% crispy form form.helper %}
{% load staticfiles %}
{% block extrahead %}
{% endblock %}
{% block blurb %}
<h1>Upload Samples</h1>
<p>Upload A Single Sample, Or A Batch Of Samples</p>
{% endblock %}
{% block form %}
<style>
tr th {text-align:center;}
</style>
<!-- Display formset -->
<form id="myForm" method="post" action="">
{{ formset.management_form }}
<div class='table'>
<table class='no_error' id='id_forms_table' border="2px" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th></th>
</tr>
</thead>
<tbody>
{% for form in formset %}
<tr id="{{ form.prefix }}-row" class="dynamic-form">
<td></td>
<
<td {% if forloop.first %} class="hidden"{% endif %}>
<a id="remove-{{ form.prefix }}-row" href="javascript:void(0)" class="delete-row"><input type='button' value='Remove Row' class='delete-row'></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
<!-- Dynamic Formset javascript -->
<script type="text/javascript">
$(function () {
$('.add-row').click(function() {
return addForm(this, 'form');
});
$('.delete-row').click(function() {
return deleteForm(this, 'form');
})
$('.add-10-rows').click(function() {
return addForm(this, 'form');
})
})
</script>
<input type='button' value='Add Row' class='add-row'>
<input type='button' value='Add 10 Rows' class='add-10-rows'>
<div style='padding-top:20px'>
<input class='btn btn-primary' type='submit' value='Upload' />
</div>
{% endblock %}
This works great, but now I would like to adjust this to allow for the addition of n rows. I will make a form that takes in an interger, then when a button is pressed, I would like to add that number of forms instead of one at a time. I am quite new to javascript/jquery, but I figured the psudo code would look something like this:
function addNForms(btn, prefix, n){
for(var i = 0; i < n; i++){
// Perform the same logic as addForm.
}
}
Unfortunately I have not been able to figure it out. I have performed the function logic n times in a for loop, but the result was that only one form at a time was being made. Which part of the addForm function can I put in a for loop to achive this goal?
I am working on an already written code base. I have to implement ajax pagination to a table. Right now we are using jquery datatable. When the page is opened they content is loaded as html thought jinja templating.
<table id="dataGrid" class="display">
<thead>
<tr>
{% if app_ctx.sub_nav == 'mine' or app_ctx.category == 'members' %}
<th class="no_sort mid"><input type="checkbox" value="" name="" id="dataGrid_check_all" /></th>
{% endif %}
{% if app_ctx.root == 'lab' %}
<th></th>
{% endif %}
<th>Access</th>
{% for field_title in field_titles() %}
<th>{{field_title}}</th>
{% endfor %}
</tr>
</thead>
<tfoot>
<tr>
{% if app_ctx.sub_nav == 'mine' or app_ctx.category == 'members' %}
<th></th>
{% endif %}
{% if app_ctx.root == 'lab' %}
<th></th>
{% endif %}
<th>Access</th>
{% for field_title in field_titles() %}
<th>{{field_title}}</th>
{% endfor %}
</tr>
</tfoot>
<tbody>
{% for item in items %}
<tr>
{% if app_ctx.sub_nav == 'mine' or app_ctx.category == 'members' %}
<td><input type="checkbox" class="item-ids" value="{{ item.id }}" /></td>
{% endif %}
{% if app_ctx.root == 'lab' %}
<td><a target="_blank" href="{{ '%s/%s' % ( app_ctx.url_for('details'), item.id) }}">More...</a></td>
{% endif %}
<td>{% if app_ctx.sub_nav != 'mine' %}<input name="item_ids" type=hidden value="{{ item.id }}">{% endif %}
<div style="width: 65px; display: block; overflow: auto;">{{ acl_display(item) }}</div></td>
{% for field_value in field_values(app_ctx, item) %}
{{field_value|safe}}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
What i need to do is, I just want to load first ten records as html and then load rest of the pages through Ajax request. Please tell how can this be achieved.
current js code
var table = $("{{ selector }}");
var dataTableInitOptions = {
"sPaginationType": "full_numbers",
"bJQueryUI": true,
"aaSorting": {% if app_ctx and app_ctx.category == 'files' and app_ctx.sub_nav == 'mine' %}[[ 7, "desc" ]]{% else %}[[ 1, "desc" ]]{% endif %},
"oLanguage":{
"sSearch":"Search all columns:"
},
"bStateSave": true {# save search and sorting state in cookies #}
};
{% if init_options %}
var additionalOptions = ({{ init_options|safe }});
for (var i in additionalOptions) {
dataTableInitOptions[i] = additionalOptions[i];
}
{% endif %}
if (table.width() > 900) {
dataTableInitOptions.sScrollX = 920;
dataTableInitOptions.bScrollCollapse = true;
//dataTableInitOptions.sScrollXInner = table.width();
}
dataTableInitOptions.fnInitComplete = function() {
{% if filters and filters_placed_in_table %}{{ filters.render_filters_js() }}{% endif %}
{# sort by Uploaded #}
{% if app_ctx and app_ctx.category == 'files' %}
{% if app_ctx.sub_nav == 'mine' %}
this.fnSort( [[7,'desc']] );
{% else %}
this.fnSort( [[6,'desc']] );
{% endif %}
{% endif %}
//move footer column filters to the top
if ($('.dataTables_scroll').length) {
var scrollParts = $('.dataTables_scroll').children();
var footer = scrollParts[2],
body = scrollParts[1];
scrollParts[1] = footer;
scrollParts[2] = body;
$('.dataTables_scroll').append(scrollParts);
} else {
//no scroll
//append empty row to the header and move footer in place of that row
$(this).css({position:'relative'});
var footer = $('tfoot tr', $(this)).children(),
colNum = footer.length,
header = $('thead tr:first', $(this)).children();
var widths = header.map(function(){return $(this).width()});
$('tfoot', $(this)).css({'position':'absolute', 'top': $('thead', $(this)).height() + 'px', 'left':'0', 'right':'0'});
$('thead', $(this)).append($('<tr></tr>').css({'height':$('tfoot', $(this)).height() + 12 + 'px'}));
footer.each(function(i, el) { $(el).width(widths[i] + 2) });
}
};
$("{{ selector }}").dataTable(dataTableInitOptions).columnFilter();
I have a dynamically populated html table that can be edited by an user (they can add rows delete them, etc -this is managed through javascript-).
The problem is, even when the table is inside the form, the server doesn't get any post data from it.
Here is the code for the template:
{% extends 'base.html' %}
{% block content %}
<script>
function add_row(){
var table = document.getElementById("body");
var row = table.insertRow(table.rows + 1);
var cell = row.insertCell(0);
var combo1 = document.createElement("select");
var option;
{% for opt in options_all %}
option = document.createElement("option");
option.setAttribute("value", "{{ opt.id }}");
option.text="{{ opt.description }}";
combo1.add(opcion);
{% endfor %}
cell.appendChild(combo1);
}
</script>
<form action='.' method='post'>
{% csrf_token %}
{{ form.as_p }}
<input type="button" value="New row" onclick="add_row()">
<table id="table_id">
<thead>
<tr>
<th>
Options
</th>
</tr>
</thead>
<tbody id="body">
</tbody>
</table>
<input type='submit' value='Submit'>
</form>
{% endblock %}
How can I get the data from the select elements?? Thanks!!
Edit: I have checked the request element and request.post doesn't have the desired data
SOLVED.
You have to specify a name for each select element inside the table. (Not the option elements)