I'm developing an Admin Panel on a website (Python + Flask) and I came across with an issue while trying to implement a Select All toggle.
The table looks like the following:
The toggle itself has been implemented but now I want to make it useful.
Upon clicking the 'SELECTED' button I want to be able to delete each and every selected item (flag) but I'm not exacly sure how I can pull it off.
Each flag can be individually deleted by clicking on the glyphicon-trash according to the following Python/HTML:
<button onclick="deleteSelected('politician')">SELECTED</button>
{% for flag in flags %}
<tr>
<!-- Check box -->
<td style="width: 60px;"><input type="checkbox" name="politician" value="bar1"></td>
<!-- First Name -->
<td class="col-title">{{flag.flagtitle}}</td>
<!-- Last Name -->
<td class="col-description">{{flag.flagreason}}</td>
<!-- Details -->
<td>
<a href="/flag/{{ flag.idflag }}">
<span class="glyphicon glyphicon-info-sign"></span>
</a>
</td>
<!-- Edit icon -->
<td class="list-buttons-column">
<a href="/politician/{{ flag.politician }}">
<span class="glyphicon glyphicon-pencil"></span>
</a>
</td>
<!-- DELETE ITEM/FLAG -->
<td class="col-delete">
<form action ="/delete_flag/{{ flag.idflag }}" method="POST">
<button onclick="return confirm('Are you sure you want to delete this flag?');">
<span class="fa fa-trash glyphicon glyphicon-trash"></span>
</button>
</form>
</td>
</tr>
{% endfor %}
My idea was to develop a JavaScript function to delete the selected content but I'm not sure how I can get the flag.idFlag, which is the flags' id's associated.
I thought it would look something like this:
function deleteSelected(elem) {
checkboxes = document.getElementsByName(elem);
for(var i=0, n=checkboxes.length;i<n;i++) {
if (checkboxes[i].checked) {
delete((checkboxes[i].getSelectedFlag).idFlag)
}
}
}
Obviously the code above doesn't work, it was just meant to give you an idea of what I'm looking for.
Is there a way I can do this? Thanks in advance.
EDIT:
Ok so I figured it out. Considering I had to submit multiple forms where action="/delete_flag/flag.idFlag", I added a column to the table where the flag's id would be visible. Like the following:
For that matter, I created a JS function to retrieve the first value of each row (ID) and store it in an array of IDs so that I could create and submit a form for each one of them.
For each ID of the array I create a form where form.action = "/delete_flag/" + retrievedID. See code below.
function deleteRecords() {
var arrayOfIDs;
arrayOfIDs = $('#table-style').find('[type="checkbox"]:checked').map(function(){
return $(this).closest('tr').find('td:nth-child(2)').text();
}).get();
var delFlagForm = document.createElement("form");
var action;
var formID;
var submitFormStr;
for (var i = 0; i < arr.length; i++) {
action = "/delete_flag/" + arr[i];
formID = 'form' + i;
delFlagForm.setAttribute("id", formID);
delFlagForm.setAttribute("method", "post");
delFlagForm.setAttribute("action", action);
delFlagForm.submit();
}
}
This sounded good in my head until I realised multiple form submissions will only work asynchronously. So I made the following changes and this is where I'm stuck right now. The forms simply won't be submitted, nothing happens:
function deleteRecords() {
var arraryOfIDs;
arraryOfIDs = $('#table-style').find('[type="checkbox"]:checked').map(function(){
return $(this).closest('tr').find('td:nth-child(2)').text();
}).get();
var delFlagForm = document.createElement("form");
var action;
var formID;
var submitFormStr;
for (var i = 0; i < arr.length; i++) {
action = "/delete_flag/" + arr[i];
formID = 'form' + i;
delFlagForm.setAttribute("id", formID);
delFlagForm.setAttribute("method", "post");
delFlagForm.setAttribute("action", action);
if (i != 0) submitFormStr += ' #' + formID;
else submitFormStr = '#' + formID;
}
$('submitFormStr').submit();
return false;
}
The variable submitFormStr updated within the loop stores the id for each form created like the following: #form0 #form1so for this reason I don't understand why the piece of code $('submitFormStr').submit(); which is equivalent to $('#form0 #form1').submit(); is not working.
Is there anything I'm doing wrong?
Ok so I figured it out. Considering I had to submit multiple forms where action="/delete_flag/flag.idFlag", I added a column to the table where the flag's id would be visible. Like the following:
For that matter, I created a JS function to retrieve the first value of each row (ID) and store it in an array of IDs so that I could create and submit a form for each one of them.
For each ID of the array I create a form where form.action = "/delete_flag/" + retrievedID. See code below.
function deleteRecords() {
var arrayOfIDs;
arrayOfIDs = $('#table-style').find('[type="checkbox"]:checked').map(function(){
return $(this).closest('tr').find('td:nth-child(2)').text();
}).get();
var delFlagForm = document.createElement("form");
var action;
var formID;
var submitFormStr;
for (var i = 0; i < arr.length; i++) {
action = "/delete_flag/" + arr[i];
formID = 'form' + i;
delFlagForm.setAttribute("id", formID);
delFlagForm.setAttribute("method", "post");
delFlagForm.setAttribute("action", action);
delFlagForm.submit();
}
}
This sounded good in my head until I realised multiple form submissions will only work asynchronously. So I made the following changes and this is where I'm stuck right now. The forms simply won't be submitted, nothing happens:
function deleteRecords() {
var arraryOfIDs;
arraryOfIDs = $('#table-style').find('[type="checkbox"]:checked').map(function(){
return $(this).closest('tr').find('td:nth-child(2)').text();
}).get();
var delFlagForm = document.createElement("form");
var action;
var formID;
var submitFormStr;
for (var i = 0; i < arr.length; i++) {
action = "/delete_flag/" + arr[i];
formID = 'form' + i;
delFlagForm.setAttribute("id", formID);
delFlagForm.setAttribute("method", "post");
delFlagForm.setAttribute("action", action);
if (i != 0) submitFormStr += ' #' + formID;
else submitFormStr = '#' + formID;
}
$('submitFormStr').submit();
return false;
}
The variable submitFormStr updated within the loop stores the id for each form created like the following: #form0 #form1so for this reason I don't understand why the piece of code $('submitFormStr').submit(); which is equivalent to $('#form0 #form1').submit(); is not working.
Is there anything I'm doing wrong?
Related
I want to check if a form has changed by using pure javascript.
My plan is to take all text including html tags between the form tag, hash the string and then when I need to check if any of the values has changed, I can just rehash the form and compare them.
So I have
<form action="/Building" method="post"> <div class="row">
<div class="col-md-12">
<div class="row">
<div class="col-md-3"> Building Address </div>
<div class="col-md-2"> City </div>
<div class="col-md-1"> State </div>
<div class="col-md-2"> Zip </div>
</div>
<div class="row">
<div class="col-md-3">
<input id="bldgResult_bldg_mail_address" name="bldgResult.bldg_mail_address" type="text" value="">
</div>
<div> ...etc
<input type="submit" value="Save and Next Building »" name="action:SaveContinue" class="btn btn-info pull-right">
<input type="submit" value="Save" class="btn btn-primary pull-right" name="action:Save">
<input type="submit" value="Go To Next Building" class="btn btn-primary hash" name="action:Next">
</div>
</form>
The problem is "value" of the input fields doesn't update. I'm able to change every textbox field and the value or the inner HTML doesnt change.
Here is the code that actually hashes and gets the innerHTML
window.onload = function () {
var forms = document.getElementsByTagName("form");
var hashValue = forms[1].innerHTML.hashCode();
Array.prototype.map.call(document.getElementsByClassName("hash"), function (hObj) {
hObj.addEventListener("click", function (event) {
if (document.getElementsByTagName("form")[1].innerHTML.hashCode() == hashValue) {
return true;
}
else {
var conf = confirm("Continue to the next building WITHOUT saving? Pressing \"Okay\" will undo any pending changes." );
if(conf)
{
return true;
}
event.preventDefault();
return false;
}
});
});
};
The above block
if (document.getElementsByTagName("form")[1].innerHTML.hashCode() == hashValue) {
return true;
}
Is always returning true, because the innerHTML doesnt change, even after the textboxes have been typed in.
What can I do? Is there another way to get the text in the HTML with updated information?
You could assign an event handler to the 'input' event of each of your fields that changes a boolean flag. You then just check that flag and set it back to false after your check is complete.
For example
document.querySelectorAll("#yourForm input").forEach(input => {
input.addEventListener("input", () => {
changed = true;
});
}
/* ... */
function checkIfChanged() {
if(changed) {
// ...
}
changed = false;
}
If you also need to check for backspace you could use the keypress event instead.
You could loop though your form elements, get and concatenate the values, and then hash the values.
Update:
Here is an example using FormData (depends on browser target):
Hash Function from Here: Generate a Hash from string in Javascript/jQuery
String.prototype.hashCode = function() {
var hash = 0, i, chr;
if (this.length === 0) return hash;
for (i = 0; i < this.length; i++) {
chr = this.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
};
function GetFormHash() {
var hashes = [];
var forms = document.getElementsByTagName("form");
var _hash = ""
for(var i=0;i<forms.length;i++) {
var formData = new FormData(forms[i]);
for (var key of formData.keys()) {
console.log(key + "=" + formData.get(key));
_hash = _hash + key + "=" + formData.get(key);
}
hashes.push(_hash.hashCode());
console.log(_hash.hashCode());
}
return hashes;
}
There is also an onchange event for <form>. Depends on browser...
<form onchange="alert('changed')"></form>
If you use something like jQuery you could use that change() event: https://api.jquery.com/category/events/form-events/
Change will not tell you if they change the data back - so not 100% reliable. If you were open to a library like jQuery - you could possibly serialize the data https://api.jquery.com/serialize/ to keep track of changes,
One last incomplete example. You would need to update to get non "input" form elements like textarea etc. You would also have to do a bit of work to get the selected radios...
function GetFormHashOther() {
var hashes = [];
var forms = document.getElementsByTagName("form");
var _hash = ""
for(var i=0;i<forms.length;i++) {
var chill = forms[i].getElementsByTagName("input");
for (var c of chill) {
console.log(c.name + " = " + c.value);
_hash = _hash + c.name + " = " + c.value;
}
hashes.push(_hash.hashCode());
console.log(_hash.hashCode());
}
return hashes;
}
I have an HTML page which contains table rows like
<tr id="tp1">
<input type="checkbox" id="tc_">
</tr>
<tr id="tp2">
<input type="checkbox" id="tc_">
</tr>
The page contains input elements other than checkboxes as well
I have to change the values of all checkbox's id from tc_ to tc_1 ,tc_2 and so on.
I have thought of doing it as below
function startup(){
for(var i=0;i<3;i++)
{
var elem=document.getElementById("tp"+i);
var str=elem.innerHTML;
str.replace(/tc_,'tc_'+i); // how do I correctly use the arguments here?
elem.innerHTML=str;
//alert (""+str);
}
}
Thanks.
It isn't valid to have non-unique IDs in the first place. Any chance you can fix how the checkboxes are rendered so you don't have to do this?
That being said, I wouldn't do this by manipulating the HTML attributes. I would instead do this by manipulating the DOM properties of those input checkboxes:
// keep track of the current "new" checkbox ID suffix
var checkBoxIndex = 0;
for (var i = 0; i < 3; i++) {
// find the table row
var elem = document.getElementById("tp" + i);
// get the input elements within that row
var inputs = elem.getElementsByTagName("input");
// for each of the input elements...
for (var j = 0, k = inputs.length; j < k; j++) {
// if it's not a checkbox, skip it
if (inputs[j].type.toLowerCase() !== 'checkbox') {
continue;
}
// Alas, give the checkbox a new, unique ID
inputs[j].id = "tc_" + (checkBoxIndex++);
}
}
Also, hopefully you get an answer for your other question. This is a terrible workaround and I would hate to see it in production code.
The trick here is to select all the input elements of your rows using the appropriate CSS selector, then modify their ids:
function startup() {
for (var i = 0; i < 3;i++) {
var elem = document.getElementById("tp" + i);
var l = elem.querySelectorAll('td > input'); // Select "input"s in "td"s
Array.prototype.forEach.call(l, function (e, j) { // Apply to each element obtained
e.id = 'tc_' + j; // Modify the id
});
}
}
There's several good answers above but if you still want to change the id from tc_ to tc_ + i then you can do it like this.
<body>
<button id="tc_">1</button>
<button id="tc_">2</button>
<button id="tc_">3</button>
<script type="text/javascript">
for(var i=0;i<3;i++)
{
document.getElementById("tc_").id="tc_"+i;
}
</script>
</body>
Honestly though you shouldn't be doing it like this despite the fact this code works as other users have said it isn't valid to have non-unique id's.
HTML:
<form id='pool_play'>
<?php
$PLAYERS = 8;
for ($i=1; $i <= $PLAYERS; $i++) {
print $i . ' <input type="text" class="initial_players" autofocus> <br/>';
}
?>
<br>
<button type="submit" class="random"> Randomize bracket</button>
</form>
<p class="debug"></p>
js:
$("#pool_play").submit(function(event) {
var participants = $('.initial_players').map(function() {
return $(this).val();
}).get();
for (var i = 0; i < participants.length; i++) {
$('p.debug').append(participants[i] + " ");
}
});
I'm basically trying to do is that when the form of #pool_play is submitted, print the contents of the input boxes in the .debug paragraph tag.
What happens is that it appears for a few milliseconds and then disappears. My guess is when the page is submitted, the old data(meaning the content of the .debug paragraph after it gets filled) gets thrown away. Tips?
You need to prevent the submit action or the page will just reload without your changes to the page.
$("#pool_play").submit(function(event) {
var participants = $('.initial_players').map(function() {
return $(this).val();
}).get();
for (var i = 0; i < participants.length; i++) {
$('p.debug').append(participants[i] + " ");
}
event.preventDefault();
return false;
});
It may be a better idea however to change your button to a button instead of a submit
<button type="button" class="random"> Randomize bracket</button>
You can prevent the page from submitting using event.preventDefault()
$("#pool_play").submit(function(event) {
var participants = $('.initial_players').map(function() {
return $(this).val();
}).get();
for (var i = 0; i < participants.length; i++) {
$('p.debug').append(participants[i] + " ");
}
event.preventDefault();//stops submit
});
Look at code. You catching submit event, getting data printing them... And then you go out from your function, so default action for submit event are executed by browser, because you don't stop it. Thats why you see this content only in miliseconds - browser is refreshing page.
You should use event.preventDefault() function to prevent browser from submiting form after execution your function.
I have a page which contains a 10 items(formatted list).Here in this page I need to add check box for each item and add the item as the value to each check box.when the user click on the check box the selected value should be passed to a new page.Can anyone help me how to add a check box for the innerHTML in java script.
Code:
var newsletter=document.getElementById("block-system-main");
var districolumn=getElementsByClassName('view-id-_create_a_news_letter_',newsletter,'div');
if(districolumn!=null)
{
var newsletterall=newsletter.getElementsByTagName('li');
alert(newsletterall[0].innerHTML);
var all=newsletter.innerHTML;
newsletter.innerHTML="<input type='button' onclick='changeText()' value='Change Text'/>";
}
function changeText()
{
alert("dfgsdg");
}
I don't exactly understand what each part of your code is doing, but i'll try and give a general answer:
In your HTML, do something like this:
<form id="myForm" action="nextPage.com">
<div id="Boxes"></div>
</form>
Change the above names to wherever you want your checkboxes to be written.
And your function:
function changeText()
{
for(var i=0 ; i < newsletterall.length ; i++)
{
var inner = document.getElementById("Boxes").innerHTML;
var newBox = ('<input type="checkbox" name="item[]" value="' + newsletter[i] + '>' + newsletterall[i]);
document.getElementById("Boxes").innerHTML = inner + newBox;
}
document.getElementById("myForm").submit();
}
The last line of code submits the checkboxes automatically. If you don't want that, remove that line, and add a submit button to the form myForm.
$('ul#list li').each(
function() {
var me = $(this),
val = me.html(),
ckb = $('<input type="checkbox" />');
ckb.click(function() {
var where=val;
window.location.href='http://google.com/?'+where;
});
me.html('');
me.append(ckb).append($('<span>'+val+'</span>'));
}
);
I have a HTML form where i dynamically create elements and set its name , value attributes .
when i tried to access the value say document .formname.nameoftheelement.value then i get the error that value is undefined.
Then i tried to use the following function to access the values .it returns the input elements as 4 but value as null when i it already has predefined value .
function returnTheStoredValues(getTableName) {
//Array arrList = new Array(20);
var tableName = document.getElementById (getTableName);
console.log("The table name" + tableName);
if (tableName) {
var inputs = tableName.getElementsByTagName ('td');
console.log("the inputs are " + inputs.length);
if (inputs) {
console.log("inputs not equal to null")
for (var i = 0; i < inputs.length; ++i) {
console.log("the value in phones table are " + inputs[i].value);
//arrList[i] = inputs[i].value;
}
}
}
//return arrList;
}
The html code is
Phone
<table id="email_table">
<tr>
<td><h3>Email</h3></td>
<td><input value="+" type="submit" onClick="checkTheEmailButtonClicked()"></td>
</tr>
</table>
<table>
<tbody>
<tr>
<td><input type="submit" value ="Save" onclick="getData();"/></td>
<td><input type="submit" value = "Cancel"/></td>
</tr>
</tbody>
</table>
Appreciate all your help .
You seem to want the values of the input elements, so:
function returnTheStoredValues(getTableName) {
var arrList = [];
var table = document.getElementById(getTableName);
var inputs = table.getElementsByTagName('input');
for (var i=0, iLen=inputs.length; i<iLen; i++) {
arrList[i] = inputs[i].value;
}
return arrList;
}
Because you're getting the TD's and not the INPUT's?
var inputs = tableName.getElementsByTagName('td');
Should be
var inputs = tableName.getElementsByTagName('input');
By the way, if you use a Javascript framework, your code will be happier.
You really need to look into using jQuery for accessing elements through JavaScript.
You could then re-write your function to the following:
function returnTheStoredValues(getTableName) {
return $("#email_table input").map(function() {
return $(this).val();
}).get();
}