Currently I have problem with adding/removing content dynamically from my application.
Scenario: I have few buttons in each row of table. After click on specified button, its value + typename should be visible on list below table. Button should also get active-class.
On the other hand, click on ACTIVE button should remove specified item from list and should also remove active-class.
My idea of adding elements was to create empty itemsArray = [] and push into that array details about clicked elements. PS. I can click all buttons from all rows so all can be active.
Question: how to remove specified item? On what should I iterate ? Buttons in first row have indexes equal to 1,2,3...
Buttons in second row have indexes equal to 1,2,3... and all rows have the same.
Splice won't work because script doesn't know which index=1, index=2 should remove.
<tr ng-repeat="score in scores" ng-class-odd="'odd-row'" ng-class-even="'even-row'">
<td class="time">{{score.time}}</td>
<td class="result">{{score.result}}</td>
<td class="match-odds">
<a class="default-btn" ng-repeat="match_odd in score.match_odds">{{match_odd.value}}</a>
</td>
</tr>
Related
It may sound stupid or even trivial for most experienced users, but I just landed a few hours ago on front-end javascript and I must say I am a bit puzzled with the behavior of the insertBefore javascript function.
My intention here is plain and simple: I have a table with its rows and cells, and in each row I have a cell with a button with the only purpose of duplicating that cell (with all its contents) and place the new duplicated cell right next to the original one.
I have a javascript function for it such like this one:
// id -> the id of the table I want the row to be added
// caller -> the object of the element that called the function
function duplicateRow(id, caller)
{
const table = document.getElementById(id);
const row = caller.parentNode.parentNode; // Caller is always a button inside a cell inside a row
const clone = row.cloneNode(true);
table.insertBefore(clone, row.nextElementSibling);
}
This function is called like this (from an extract of my HTML):
<tr>
<td>
<input type="text" name="competence-name">
</td>
<td>
<button name="duplicate-row-button" onclick="duplicateRow( 'competencies-table', this )"></button>
</td>
</tr>
So, what I would expect from it is that, at each click on the duplicate row button, it would create an exact copy of the row where the button is being clicked and add it right after that row.
My problem here is not with the duplicating (that is done just right and smooth as one would expect) but with where the new row is placed:
The first time, when there is only one row, it is placed at the end (since nextSibling is null).
The second time clicking the button on the first row (despite now having a sibling right after it), the new row is again placed at the end of the table (as if nextSibling for the first row was still null).
And so on (even strager placements happen when mixing duplications with the newly added rows).
Shouldn't the nextSibling and/or rowIndex properties be updated when adding a new node to the DOM? Is there a way of forcing them to update? What is it that I have wrong? My code, my understanding of how it should work?
I am surely open to any possible explanation/solution/alternative to achieve what I need, and thank you all in advance!
The problem is that initial table row is wrapped in a tbody element (for which you can omit both start and end tag), which is required according to the content model of tables. However, when you programmatically add more rows, they are inserted outside the tbody and your initial row is the only child of that implicit tbody, so the DOM tree looks like this:
<table>
<tbody>
<tr></tr>
</tbody>
<tr></tr>
<tr></tr>
</table>
To solve it I suggest to add a clone to cloned row's parent:
function duplicateRow(caller){
const row = caller.parentNode.parentNode; // Caller is always a button inside a cell inside a row
const clone = row.cloneNode(true);
row.parentNode.insertBefore(clone, row.nextElementSibling);
}
<table id="competencies-table">
<tr>
<td>
<input type="text" name="competence-name">
</td>
<td>
<button name="duplicate-row-button" onclick="duplicateRow( this )">Duplicate</button>
</td>
</tr>
</table>
I have the following situation I can not solve. I would be very thankful if anyone had an idea:
My webpage contains a table of players. Each line (player) contains two checkboxes: One that selects if the player is active (checked) or not, the other which team he/she belongs to (checked=Team 1; unchecked=Team 2).
So each line looks sth like this:
<tr>
<td><input id="plyr2_active" type="checkbox" name="plyr_active[]" value="2"></td>
<td><input type="checkbox" id="plyr2_team" name="plyr_team[2]" data-on-color="danger" data-off-color="success" data-on-text="RED" data-off-text="GREEN" checked value="1"></td>
</tr>
I'd like to add a button that, when clicked, will run a function that randomizes the teams of the ACTIVE players. Meaning that the players will be shuffled and half of them belong to one, the other half to the other team.
What I tried: Get all checkbox states in an array, then shuffle() the array and try to change the checked-state via bootstrap. Miserably failed :-(
Any help will be much appreciated. Thanks!!
Okay, this should help to get you started. It shows how to pull a list of active players (using jQuery) from your table.
Assuming you have a button with an id of 'shuffleBtn':
<button id="shuffleBtn">Shuffle<button>
and a table with id 'players':
<table id='players'>
:
</table>
-
$("#shuffleBtn").click(function() {
var newPlayerArray = [],
id = 1;
$("#players tr td:first-child").each(function() {
if ($(this).find('input:first').prop('checked')) {
newPlayerArray.push(id);
}
id++;
});
console.log(newPlayerArray);
});
This will display an array of the active players (assuming the first row is player 1, the second player 2, etc.) on the console.
Example: [1,3,4]
It then iterates each row () and grabs the first column (). Then for each of those it finds the first <input> and checks if the 'checked' property is present (this means the checkbox has been clicked).
I am just pushing the row index (starting at 1) so you may need to change how you interpret the associated player.
I have a page with a list of items on it. Each row has a button. By pressing a button list item is added to another list on the same page (it's a typical "order" form). I'm using angular ng-repeater to show the first list. After user press a button an item info is added to JSON varaible. The question is what's the best way to show user's choice list on the same page? So far I'm think of adding an attribute to the first list so when user choose it, it'll be shown in the second list. But I also want first list to be modified by user without any changes to the second one. Any ideas?
Check the code below, the button ng-click directive is calling the function AddtoList2($index) to add the current List1 item to List2, optionally it removes the current item from List1.
At template side
<div ng-repeat="item1 in List1">
...
<input type="button" ng-click="AddtoList2($index)" />
</div>
<div ng-repeat="item2 in List2">
...
</div>
At controller side
$scope.List1 = [];
$scope.List2 = [];
$scope.AddtoList2 = function (idx) {
var item = $scope.List1[idx];
$scope.List2.push(item);
//If you want to remove from List 1
$scope.List1.splice(idx, 1)
};
template.html
<td style="width:150px;"><input type="button" name="delete" value="{{ report_person.report_person.id}}" class="delete_icon" />{{report_person.report_person.name }}
</td>
The above row is created dynamically using python/django.Its the person name and delete icon.
For every row created dynamically,the delete icon will appear.
<td class="ir-shade" colspan="4"><button id="{{report_person.report_person.id}}" type="button" class="add_treatment" class="button_style">Add treatment notes</button>
<div id="result-{{report_person.report_person.id}}" class="toggle"></div></td>
Add treatment notes is a toggle button,it show the treatment details on one toggle,at this state the name of button become Hide treatment notes.
I want to hide the delete_icon class for individual name when the treatment note is open f.Since i am using comman css class for delete_icon,using this $('.delete_icon').hide(); is hiding the delete icon for all rows created dynamically.Only unique thing is the value of that delete button,that means the delete_icon.Is any possibility is their to hide the css class icon with reference to value.So that the delete image will hide only for cases the treatment notes are in open condition.
Note:It is some django code are used for passing variable,looks different from html.
In jQuery, you can use this to find child elements. Assuming that this is all in one div, or span, or some sort of container. You could simply search downwards from that container and toggle off your delete button.
$(this).children("input.delete_icon").hide();
Going off of your supplied template, you would use children and also .prev() to navigate up your DOM, and then back down.
Your code will roughly be:
$(this).closest('tr').prev().children(":first").children('input.delete_icon').hide();
Let's walk through this:
$(this) is your currently 'clicked' table row, that includes your
add_treatment button.
.closest('tr') looks UP for the nearest
table row. It will find the table row that your button is placed
inside of
.prev() looks for the previous sibling of the selected
object. Since we are currently selecting the <tr> your button is in
(as per our .closest('tr')) it will look for the previous <tr>
which is above it, and holds your delete_icon button.
Now, we are on the <tr> of your button object, but we need to navigate downwards
.children(":first") will navigate to the first child of the current element. This would be your first <td> element.
We need to navigate down one more, so we select the button child by using .children('index.delete_icon')
You have now "selected" your .delete_icon button, and can .hide() it.
Try using the jQuery .find() function.
$('.add_treatment').on('click', function() {
var $this = $(this);
$this.find('input[class*='delete_icon']').prop('disabled', true);
// toggle notes
// hide delete icon (if you do not like the css below)
});
Adding css rules would help reduce the amount of javascript functions/actions needed.
tr td .delete_icon {
display:none;
}
tr:hover td .delete_icon {
display:block;
}
There are other ways to do this that are more efficient but we would need more html structure.
if the delete icon is in the following td (created dynamically) you need:
$('.add_treatment').click(function(){
// should point to the parent td, the next td, its children,
// and hide the first child which is the input button
$(this).parent().next().children('.delete_icon').hide();
});
I'm dynamically creating and appending into a table, a <tr> and a <td> with the following code:
$("#table1").append(
'<tr>'+
'<td style="cursor:pointer" onclick="pass.data.carregar(this.parentNode.rowIndex-2);">'+$("#DRVR_NAME").val()+'</td>'+
'</tr>');
It's Ok so far: I can load the Td data into another fields that I want and there's no problem on creating it.
But beyond creating it I must allow the user to remove the <td> dynamically, but as you can see, there's no ID to look for. What's the better way to allow the user to remove the <td> ?
Im trying the following code:
$("#table1>tbody>td>tr."+teste+"").remove();
But no success! The test variable is a number that I automatically define for the register.
Any help?
If test is the 0-based index of the row you want to remove...
$("#table1>tbody>tr:eq("+test+")").remove();
Set a unique id attribute when you dynamically create each cell.
<tr id="uniqueID"><td>Cell Content</td></tr>
Then use simple jquery to remove the row by id.
$('#uniqueID').remove();
Your remove code assumes there is a class on the TD. You'll have to target it with :eq() by referencing the value in your hidden field. If the value in the hidden field is a number (the index of the td the user selected = your counter), you could try something like this:
var hiddenFieldValue = $('input.hiddenFieldClassName').val();
$("#table1>tbody>tr>td:eq("+hiddenFieldValue+")").remove();
You could add a little x next to each driver name that will delete that td by changing your code a bit:
$("#table1").append('<tr>'+'<td style="cursor:pointer" onclick="pass.data.carregar(this.parentNode.rowIndex-2);">'+$("#DRVR_NAME").val()+'<span onclick="$(this.parentNode).remove()">x</span></td>'+'</tr>');
Or you could add another function to the click handler that you are binding to each <td> that will display a message in a predefined <div> asking the user if s/he wants to delete that element:
$("#table1").append('<tr>'+'<td style="cursor:pointer" onclick="pass.data.carregar(this.parentNode.rowIndex-2);askDelete(this);">'+$("#DRVR_NAME").val()+'</td>'+'</tr>');
and then define a message area (id = 'messageArea') somewhere in your HTML and the following function in your code:
askDelete(el){
var MA=$('#messageArea');
MA.empty();
MA.html('Do you want to delete ' + el.innerHTML + '?<br>').append('<span id="confirmDelete">delete</span> <span id="cancelDelete">cancel</span>')
MA.find('#confirmDelete').click(function(){$(el).remove();});
MA.find('#cancelDelete').click(function(){MA.empty();})
}
then style your delete and cancel buttons as you wish.