JQuery selector bug - not working - javascript

I have a weird JQuery bug that I cannot find the cause for.
There is an edit button for each row that changes the title and body cells to an input and textarea field.
It works for the first row but not for any other rows
If I click the first row, it will work for consecutive rows.
Can someone please have a look over my code
#extends('layouts')
#section('content')
<div class="container">
<h1>Diary Application</h1>
<button style="margin-bottom: 10px;" class="btn btn-primary"></span></button>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Date</th>
<th>Title</th>
<th>Content</th>
</tr>
</thead>
<tbody>
#foreach($entries as $entry)
<tr id={{ $entry->id }}>
<td>{{ $entry->created_at->format('l h:ia d/m/Y') }}</td>
<td id="title">{{ $entry->title }}</td>
<td id="body">{{ $entry->body }}</td>
<td id="buttons"><button class="btn btn-danger"><a href={{ url("/deleteEntry/$entry->id")}}>Delete</a></button> <button class="btn btn-warning" id="edit" data-id={{ $entry->id }}>Edit</button></td>
</tr>
#endforeach
</tbody>
</table>
</div>
#endsection
#section('scripts')
<script>
$(document).ready(function() {
$("button#edit").click( function() {
var id = $(this).data("id");
var titleField = $("tr#" + id + " > td#title");
var contentField = $("tr#" + id + " > td#body");
alert("tr#" + id + " > td#body");
alert($("tr#" + id + " > td#body").html());
titleField.replaceWith("<td style='vertical-align: center;'><input type=text name='title' value=" + titleField.html() + "></td>");
contentField.replaceWith("<td style='vertical-align: center;'><textarea rows='3' name='body'> " + contentField.html() + "</textarea></td>");
$("tr#" + id + " > td#buttons").append(" <button class='btn btn-success'>Save</button>");
$("tr#" + id + " > td#buttons > .btn-warning").attr('disabled', 'disabled');
});
});
</script>
#endsection

Change id to class and try the below code,
$(document).ready(function() {
$("button.edit").click( function() {
var tr = $(this).closest("tr");
var titleField = tr.find(".title");
var contentField = tr.find(".body");
alert(contentField);
alert(contentField.html());
titleField.replaceWith("<td style='vertical-align: center;'><input type=text name='title' value=" + titleField.html() + "></td>");
contentField.replaceWith("<td style='vertical-align: center;'><textarea rows='3' name='body'> " + contentField.html() + "</textarea></td>");
tr.find(".buttons").append(" <button class='btn btn-success'>Save</button>")
.find(".btn-warning") // use chaining
.prop('disabled', true);// use prop instead of attr
});
});
Your HTML should be,
<tr id={{ $entry->id }}>
<td>{{ $entry->created_at->format('l h:ia d/m/Y') }}</td>
<td class="title">{{ $entry->title }}</td>
<td class="body">{{ $entry->body }}</td>
<td class="buttons"><button class="btn btn-danger"><a href={{ url("/deleteEntry/$entry->id")}}>Delete</a></button> <button class="btn btn-warning edit" data-id={{ $entry->id }}>Edit</button></td>
</tr>
Snippet,
$(document).ready(function() {
$("button.edit").click(function() {
var tr = $(this).closest("tr");
var titleField = tr.find(".title");
var contentField = tr.find(".body");
titleField.replaceWith("<td style='vertical-align: center;'><input type=text name='title' value=" + titleField.html() + "></td>");
contentField.replaceWith("<td style='vertical-align: center;'><textarea rows='3' name='body'> " + contentField.html() + "</textarea></td>");
tr.find(".buttons").append(" <button class='btn btn-success'>Save</button>")
.find(".btn-warning") // use chaining
.prop('disabled', true); // use prop instead of attr
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table>
<tr id="1">
<td>Date 1</td>
<td class="title">Title1</td>
<td class="body">Body1</td>
<td class="buttons"><button class="btn btn-danger">Delete</button> <button class="btn btn-warning edit" data-id="1">Edit</button></td>
</tr>
<tr id="2">
<td>Date 2</td>
<td class="title">Title2</td>
<td class="body">Body2</td>
<td class="buttons"><button class="btn btn-danger">Delete</button> <button class="btn btn-warning edit" data-id="2">Edit</button></td>
</tr>
<tr id="3">
<td>Date 3</td>
<td class="title">Title3</td>
<td class="body">Body3</td>
<td class="buttons"><button class="btn btn-danger">Delete</button> <button class="btn btn-warning edit" data-id="3">Edit</button></td>
</tr>
</table>

First change the IDs to Classes &
Use jQuery's $.closest() like below
$(document).ready(function() {
$("button#edit").click( function() {
var tr = $(this).closest("tr"); // This will give you the TR in which your elements reside.
....
your rest of the code with some modifications
....
});
});

You are generating several button tags with de same id (#edit), in the html document an id attibute must be unique, you could use a class selector like this.
<button class="btn btn-warning edit" data-id={{ $entry->id }}>Edit</button>
And then in your javascript use:
$("button.btn.edit").click( function() {...});

Related

i use append in for loop of local storage ,i want to display item in a new line every time loop finished

for(item in cart){
let name =cart[item][1];
let qty =cart[item][0];
let image =cart[item][2];
let price=cart[item][3];
mystr=` <td class="product-thumbnail"><image src="${image}" alt="product"> </td>
<td class="product-name">${name}</td>
<td class="product-price"><span class="amount">${price}</span></td>
<td class="product-quantity">
<button id='plus" + item + "' class ='btn btn-primary plus'>+</button>
<span id="quantity" >${qty}</span>
<button id='minus" + item +"' class='btn btn-primary minus'>-</button>
</td>
<td class="product-subtotal"><span class="amount"></span></td>
<td class="product-remove"><i class="fa fa-times"></i></td> `
console.log(mystr);
$('#items').append(mystr)
}
I expect this:
But currently, it coming like this:
Your HTML string is missing the <tr> and </tr> tags to tell the browser you need to go to a newline.
Try replacing mystr with:
var mystr = `<tr>
<td class="product-thumbnail"><a href="shop-details.html">
<image src="${image}" alt="product">
</a></td>
<td class="product-name">${name}</td>
<td class="product-price"><span class="amount">${price}</span></td>
<td class="product-quantity">
<button id='plus" + item + "' class='btn btn-primary plus'>+</button>
<span id="quantity">${qty}</span>
<button id='minus" + item +"' class='btn btn-primary minus'>-</button>
</td>
<td class="product-subtotal"><span class="amount"></span></td>
<td class="product-remove"><i class="fa fa-times"></i></td>
</tr>`
This should display your content the right way.

Add Row After Particular Class JQuery

I have problem with add more button with particular row. It was adding row at last in each row. I discussed my problem in details:
Please See The Code Snipest :
var i = 2;
$(document).on("click",".btn_add",function(){
var str1 = '<tr><td>'+i+'</td><td>Row '+i+'</td><td><button class="btn btn-sm btn-success btn_add">Add</button> <button class="btn btn-sm btn-success btn_addsub">Add Sub</button></td></tr>';
$(this).parent().parent().parent().find("tr:last").after(str1);
i++;
});
$(document).on("click",".btn_addsub",function(){
var str1 = '<tr><td>'+i+'</td><td>Row '+i+'</td><td><button class="btn btn-sm btn-danger btn_remove">Remove</button></td></tr>';
//$(this).parent().find('tr:last').after(str);
$(this).parent().parent().parent().find("tr:last").after(str1);
i++;
});
$(document).on("click",".btn_remove",function(){
$(this).parent().parent().remove();
});
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table">
<tr>
<th>#</th>
<th>Row</th>
<th>Action</th>
</tr>
<tr>
<td>1</td>
<td>Row 1</td>
<td><button class="btn btn-sm btn-success btn_add">Add</button> <button class="btn btn-sm btn-success btn_addsub">Add Sub</button></td>
</tr>
</table>
Problem
Step 1. Click On Row 1 Add Sub Button
Step 2. Again Click On Row 1 Add Sub Button
Step 3. Now Click On Row 1 Add Button
Step 4. Now Click On Row 4 Add Sub Button
That's Working Properly. But Now If I Click On Button Add Sub Button Of Row 1: Then It Will be added after Row 3. Currently it is added after Row 5.
So Please Help Me To Overcome this problem.
Thank You in advance.
One Solution I Tried But No Idea about this : Like Generated Code Will See Like This :
<tr class="row_1">
<td>1</td>
<td>Row 1</td>
<td><button class="btn btn-sm btn-success btn_add">Add</button> <button class="btn btn-sm btn-success btn_addsub">Add Sub</button></td>
</tr>
<tr>
<td>1</td>
<td>Row 1</td>
<td><button class="btn btn-sm btn-danger btn_remove">Remove</button></td>
</tr>
<tr>
<td>1</td>
<td>Row 1</td>
<td><button class="btn btn-sm btn-danger btn_remove">Remove</button></td>
</tr>
<tr class="row_2">
<td>1</td>
<td>Row 1</td>
<td><button class="btn btn-sm btn-success btn_add">Add</button> <button class="btn btn-sm btn-success btn_addsub">Add Sub</button></td>
</tr>
As per your comment
Can I add This At Last Of that first tr
, here's a demo:
1) Get all of the trs' index that has .btn_add
var index = $(this).closest('table').find('.btn_add').map(function(){
return $(this).closest('tr').index()
}).get()
2) Find the index of the current row
var thisIndex = $(this).closest('tr').index()
3) Find next tr's index from index array
var nextIndex = index[index.indexOf(thisIndex) + 1]
4) If the current index is the last one, then nextIndex would be undefined and add the new row to the last of the table. Or add the new row before the nextIndex's tr.
if(nextIndex)
$(this).closest('table').find('tr').eq(nextIndex).before(str1);
else
$(this).closest('table').find("tr:last").after(str1);
var i = 2;
$(document).on("click", ".btn_add", function() {
var str1 = '<tr><td>' + i + '</td><td>Row ' + i + '</td><td><button class="btn btn-sm btn-success btn_add">Add</button> <button class="btn btn-sm btn-success btn_addsub">Add Sub</button></td></tr>';
$(this).closest('table').find("tr:last").after(str1);
i++;
});
$(document).on("click", ".btn_addsub", function() {
var str1 = '<tr><td>' + i + '</td><td>Row ' + i + '</td><td><button class="btn btn-sm btn-danger btn_remove">Remove</button></td></tr>';
var index = $(this).closest('table').find('.btn_add').map(function(){
return $(this).closest('tr').index()
}).get()
var thisIndex = $(this).closest('tr').index()
var nextIndex = index[index.indexOf(thisIndex) + 1]
if(nextIndex)
$(this).closest('table').find('tr').eq(nextIndex).before(str1);
else
$(this).closest('table').find("tr:last").after(str1);
i++;
});
$(document).on("click", ".btn_remove", function() {
$(this).closest('tr').remove();
});
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table">
<tr>
<th>#</th>
<th>Row</th>
<th>Action</th>
</tr>
<tr>
<td>1</td>
<td>Row 1</td>
<td><button class="btn btn-sm btn-success btn_add">Add</button> <button class="btn btn-sm btn-success btn_addsub">Add Sub</button></td>
</tr>
</table>
Is this what you want?
I've changed $(this).parent().parent().parent().find("tr:last").after(str1); to $(this).closest("tr").after(str1);
Demo
var i = 2;
$(document).on("click", ".btn_add", function() {
var str1 = '<tr><td>' + i + '</td><td>Row ' + i + '</td><td><button class="btn btn-sm btn-success btn_add">Add</button> <button class="btn btn-sm btn-success btn_addsub">Add Sub</button></td></tr>';
$(this).parent().parent().parent().find("tr:last").after(str1);
i++;
});
$(document).on("click", ".btn_addsub", function() {
var str1 = '<tr><td>' + i + '</td><td>Row ' + i + '</td><td><button class="btn btn-sm btn-danger btn_remove">Remove</button></td></tr>';
$(this).closest("tr").after(str1);
i++;
});
$(document).on("click", ".btn_remove", function() {
$(this).parent().parent().remove();
});
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table">
<tr>
<th>#</th>
<th>Row</th>
<th>Action</th>
</tr>
<tr>
<td>1</td>
<td>Row 1</td>
<td><button class="btn btn-sm btn-success btn_add">Add</button> <button class="btn btn-sm btn-success btn_addsub">Add Sub</button></td>
</tr>
</table>

Change html from place

I want to change a row from a table to another but I want to replace the addBtn for a removeBtn.
dataTableTeamMembers is the other table
$('.addBtn').click(function() {
var row = $(this).closest('tr');
console.log(row[1]);
$('#dataTableTeamMembers tbody').append(row);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<tr class="text-center hover-table odd" role="row">
<td class="sorting_1"><img class="avatarImage" src="data:image/jpg;base64,iVBORw"></td>
<td>johns</td>
<td>John Smith</td>
<td>Member</td>
<td>
<button type="button" class="btn btn-primary addBtn"> Add</button>
</td>
</tr>
update your js code with this.
$('.addBtn').click(function () {
var row = $(this).closest('tr');
console.log(row[0]);
$('#dataTableTeamMembers tbody').append(row[0].innerHTML);
});
$('.addBtn').click(function() {
var row = $(".tbl .tbltr").html();
console.log(row[1]);
$('.tbl').append(row);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class='tbl'>
<tr class="text-center hover-table odd tbltr" role="row">
<td class="sorting_1"><img class="avatarImage" src="data:image/jpg;base64,iVBORw"></td>
<td>johns</td>
<td>John Smith</td>
<td>Member</td>
<td>
<button type="button" class="btn btn-primary addBtn"> Add</button>
</td>
</tr>
</table>

PHP Form/Table - Sending row contents when checked

I am working on a project and have an idea but not sure how to accomplish (new to PHP/JS).
Basically, I have a table within a form with one row being a checkbox. I would like to check the box(es) and when the form is submitted it sends the values of each column in the selected rows.
For example:
1 - Domain | MatchedTo | Percentage | Checkbox
2 - Domain | MatchedTo | Percentage | Checkbox
If row 1 is checked I would like the submit to POST the domain, matchedto and percentage values.
Here is what I have so far:
<script type="text/javascript">
$('#test-form').submit(function(event) {
event.preventDefault();
var buttonAction = event.originalEvent.explicitOriginalTarget.value;
var formData = $(this).serialize();
var varData = formData + "&action=" + buttonAction;
$.ajax({
type: 'POST',
url: 'test_submit.php',
data: varData,
success: function() {
window.location.reload(true);
console.log("Form posted successfully.", varData);
}
})
});
</script>
<form method="POST" id="test-form">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Ratio</th>
<th>Domain</th>
<th>Matched</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr id="6" role="row" class="odd">
<td>50</td>
<td class="sorting_1">www.test.com</td>
<td class="sorting_1">anothertest2.com</td>
<td><button type="button" class="btn btn-danger del_domain" domain="www.test.com">Remove</button>
<button type="button" class="btn btn-primary update_domain" domain="www.test.com" matchedto="anothertest2.com">Keep</button>
<input name="domain[]" value="www.test.com" type="checkbox"></td>
</tr>
<tr id="6" role="row" class="odd">
<td>50</td>
<td class="sorting_1">www.test2.com</td>
<td class="sorting_1">anothertest2.com</td>
<td><button type="button" class="btn btn-danger del_domain" domain="www.test2.com">Remove</button>
<button type="button" class="btn btn-primary update_domain" domain="www.test.com" matchedto="anothertest2.com">Keep</button>
<input name="domain[]" value="www.test2.com" type="checkbox"></td>
</tr>
</tbody>
</table>
<button class="btn btn-success" type="submit" value="save"><span class="fa fa-arrow-right">Save Selected</span></button>
<button class="btn btn-danger" type="submit" value="delete"><span class="fa fa-times">Delete Selected</span></button>
<button class="btn btn-warning" type="reset" value="reset"><span class="fa fa-times">Clear Selected</span></button>
</form>
I am assuming I need to create an input field for each column? How do I go about POSTing all of these fields when a box is checked?
Thank you for any assistance.
If you're going to submit via ajax, you'll probably want to create the string you'll be submitting. Something like the following may be a starting-point, if I understand what you're trying to do.
Note that this doesn't address actually sending the data, it's simply about how to hijack the form and create the format you're looking for.
// First, I'm stopping the default behaviors
$("button").on("click", function(event){
event.stopPropagation();
event.preventDefault();
})
// Now, when we click save, I want to format
// a string.
$("button[value='save']").on("click", function(){
var returnString = "";
// The following selector gets all the rows
// that have a CHECKED checkbox. Note I
// don't get the checkbox, simply the row.
var rowEls = $("#test-form").find("tr:has(input[type='checkbox']:checked) ");
// For every row, we'll add to our string...
rowEls.each(function(){
var rowEl = $(this);
// First, a row id
returnString += rowEl.attr("id")+" - ";
var cells = rowEl.children("td");
// Next the contents of each cell THAT
// HAS A data-content ATTRIBUTE. This
// way, we don't get the remove/keep.
cells.each(function(){
if($(this).data("content")){
returnString += $(this).data("content")+"="+$(this).text();
if($(this).not(":last"))
returnString += " | ";
}
})
returnString += " ";
})
console.log(returnString);
})
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form method="POST" id="test-form">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Ratio</th>
<th>Domain</th>
<th>Matched</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr id="6" role="row" class="odd">
<td data-content="ratio">50</td>
<td class="sorting_1" data-content="domain">www.test.com</td>
<td class="sorting_1" data-content="matched">anothertest2.com</td>
<td><button type="button" class="btn btn-danger del_domain" domain="www.test.com">Remove</button>
<button type="button" class="btn btn-primary update_domain" domain="www.test.com" matchedto="anothertest2.com">Keep</button>
<input name="domain[]" value="www.test.com" type="checkbox"></td>
</tr>
<tr id="6" role="row" class="odd">
<td data-content="ratio">50</td>
<td class="sorting_1" data-content="domain">www.test2.com</td>
<td class="sorting_1" data-content="matched">anothertest2.com</td>
<td><button type="button" class="btn btn-danger del_domain" domain="www.test2.com">Remove</button>
<button type="button" class="btn btn-primary update_domain" domain="www.test.com" matchedto="anothertest2.com">Keep</button>
<input name="domain[]" value="www.test2.com" type="checkbox"></td>
</tr>
</tbody>
</table>
<button class="btn btn-success" type="submit" value="save"><span class="fa fa-arrow-right">Save Selected</span></button>
<button class="btn btn-danger" type="submit" value="delete" disabled><span class="fa fa-times">Delete Selected</span></button>
<button class="btn btn-warning" type="reset" value="reset" disabled><span class="fa fa-times">Clear Selected</span></button>
</form>

Issue in recursive loop : JQuery

About the below code
I am trying to delete the roles and it's child roles recursively in Js. In the below Html: data-id="2" is RoleID and data-parentid="1" is Parent Role.
Problem
When debugger comes at last row, it does not go back to its parent row which is already traversed in the loop.
Am I missing anything?
Html Part
<table id="RoleList" class="table table-bordered">
<tbody>
<tr data-id="15">
<td>under first</td>
<td>first</td>
<td>Yes</td>
<td>
<button class="DeleteRole btn btn-primary btn-xs">Delete</button>
</td>
</tr>
<tr data-id="16" data-parentid="15">
<td>Second</td>
<td>under first</td>
<td>Yes</td>
<td>
<button class="DeleteRole btn btn-primary btn-xs">Delete</button>
</td>
</tr>
<tr data-id="17" data-parentid="16">
<td>under second</td>
<td>Second</td>
<td>Yes</td>
<td>
<button class="DeleteRole btn btn-primary btn-xs">Delete</button>
</td>
</tr>
</tbody>
</table>
JS Part
function RemovedDeletedRoles(RoleID) {
var Roles = $("#RoleList").find("tr[data-parentID='" + RoleID + "']");
$.each(Roles, function(index, row) {
var ID = $(row).attr("data-id");
var childRoles = $("#RoleList").find("tr[data-parentID='" + ID + "']");
if(childRoles.length === 0) {
$(row).remove();
}
else {
RemovedDeletedRoles($(row).attr("data-id"));
}
});
}
DOM Ready Event
$(document).on("click", ".DeleteRole", function() {
var deleteButton = $(this);
var roleID = $(deleteButton).parent().parent().attr("data-id");
RemovedDeletedRoles(roleID);
$(deleteButton).parent().parent().remove();
});
this is my code that work fine:
<table id="RoleList" class="table table-bordered">
<tbody>
<tr data-id="15">
<td>under first</td>
<td>first</td>
<td>Yes</td>
<td>
<button class="DeleteRole btn btn-primary btn-xs">Delete</button>
</td>
</tr>
<tr data-id="16" data-parentid="15">
<td>Second</td>
<td>under first</td>
<td>Yes</td>
<td>
<button class="DeleteRole btn btn-primary btn-xs">Delete</button>
</td>
</tr>
<tr data-id="17" data-parentid="16">
<td>under second</td>
<td>Second</td>
<td>Yes</td>
<td>
<button class="DeleteRole btn btn-primary btn-xs">Delete</button>
</td>
</tr>
</tbody>
</table>
//direction 0:remove children, 1:remove parents
function RemoveRoles(roleId, direction) {
direction=direction || 0; //remove by defautl remove children
//alert("RoleId:"+roleId+" - direction->"+(direction==0?"children":"parents"));
var $tr=$("#RoleList").find("tr[data-id='" + roleId + "']");
var parentId=$tr.data("parentid");
var itemsToRemove = [];
if(direction==0){
itemsToRemove=$("#RoleList").find("tr[data-parentid='" + roleId + "']");
}else{
itemsToRemove=$("#RoleList").find("tr[data-id='" + parentId + "']");
}
//alert(itemsToRemove.length);
$tr.remove();
$.each(itemsToRemove, function(index, item) {
var id = $(item).data("id");
RemoveRoles(id, direction);
});
}
$(document).on("click", ".DeleteRole", function() {
var deleteButton = $(this);
var roleID = $(deleteButton).parent().parent().attr("data-id");
RemoveRoles(roleID, 1);
$(deleteButton).parent().parent().remove();
});
Try it

Categories

Resources