jQuery deleting multiple items instead of just one - html

I have a table which has buttons when you hover on its rows. There is a delete button that calls a custom confirm dialog; this basically just accepts the callback function that it will perform when the delete is confirmed.
The HTML is as follows:
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<link rel="stylesheet" type="text/css" href="css/styles.css" />
</head>
<body>
<section>
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>Doe, Jane</td>
<td>
<div>
25
<span class="actions">
<input type="button" value="Edit" class="btn-edit" />
<input type="button" value="Delete" class="btn-delete" />
</span>
</div>
</td>
</tr>
<tr>
<td>Doe, John</td>
<td>
<div>
35
<span class="actions">
<input type="button" value="Edit" class="btn-edit" />
<input type="button" value="Delete" class="btn-delete" />
</span>
</div>
</td>
</tr>
<tr>
<td>Smith, John</td>
<td>
<div>
30
<span class="actions">
<input type="button" value="Edit" class="btn-edit" />
<input type="button" value="Delete" class="btn-delete" />
</span>
</div>
</td>
</tr>
</tbody>
</table>
</section>
<!-- popups -->
<div id="confirm-delete" class="popup confirm-dialog">
<h3>Delete</h3>
<div class="popup-content">
<p class="confirm-message">Are you sure you want to delete this item?</p>
<div class="buttons">
<input id="btn-delete-confirm" type="button" class="button btn-confirm" value="Delete" />
<input id="btn-delete-cancel" type="button" class="button btn-close-popup" value="Cancel" />
</div>
</div>
</div>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/home.js"></script>
</body>
</html>
JavaScript codes:
$(document).ready(function(){
var btnDelete = $('.btn-delete');
btnDelete.on('click', function(e){
var popUpId = 'confirm-delete',
btn = $(e.currentTarget),
item = $(e.currentTarget).closest('tr'),
header = 'Delete Item',
message = 'Are you sure you want to delete ' + item.find('.name').text() + '?';
customConfirm(popUpId, header, message, function(){ deleteItem(item); });
});
});
function customConfirm(id, header, message, callback){
var popUp = $('#' + id),
btnConfirm = popUp.find('.btn-confirm');
popUp.find('h3').html(header);
popUp.find('.confirm-message').html(message);
popUp.append('<div class="mask"></div>');
popUp.show();
btnConfirm.on('click', {popUpId: id, callBack: callback}, confirmClick);
}
function confirmClick(e){
e.data.callBack();
closePopUp(e);
}
This works fine when I click on the delete button for one item and confirm its deletion. But when I click on the delete button of an item and then cancel it, click on another item's delete button and confirm, both items are deleted. It happens everytime I cancel the deletion of an item. So if I cancel deleting three items and confirm the deletion of the next item, four items will be deleted.
Help on this would be greatly appreciated.
Thank you :)
PS
Here's the jsfiddle link :)

What's happening is, the click handlers from previous showings of the dialog are still attached to its "Confirm" button. When you click the button, all the previous handlers are firing, and thus all the previous deletions are being confirmed.
You need to get rid of the previous handlers, either when the dialog is dismissed or as part of showing the dialog. It's probably simpler, i think, to get rid of it when showing the form; you could simply say .off('click') before attaching the new click handler:
btnConfirm
.off('click')
.on('click', {popUpId: id, callBack: callback}, confirmClick);

I think this should work..
i have modified you js code a bit
http://jsfiddle.net/VKKpe/
changed this
btnConfirm = popUp.find('.btn-confirm');
to
btnConfirm = $('#btn-delete-confirm');

I've encountered this problem before and it's not something I would have really thought about, and I'm super glad that I have the opportunity to help someone with it:
binding with .on() adds a binding, doesn't replace it.. So it will execute everything you have bound to it in the past.
Simple Solution: btnConfirm.unbind('click'); right before binding.
Working example: http://jsfiddle.net/asifrc/VXsEB/8/

Related

Why isn't HTML working in Bootstrap v5 Popover?

When I add HTML into my Bootstrap v5 popover, it does not display the HTML in the popover. I believe that I have all of the correct options passed as described in the docs. Almost all of the results which I've gotten from searches to try and understand this issue deal with Bootstrap v4 and v3, so they aren't of use to me.
The popover all of the way on the right should have the switch affordance ("Toggle") appear below "Hello World" in the popover. The HTML code is present.
The code of the above tests centers around these 3 affordances:
<!-- Popover Works -->
<span class="fs-3 actions-link-style ai-more-horizontal" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" title="Title" data-bs-sanitize="false" data-bs-html="true" data-bs-content="Hello World"></span>
<!-- HTML Switch Works -->
<div class='form-check form-switch'><input type='checkbox' class='form-check-input' id='customSwitch1'><label class='form-check-label' for='customSwitch1'>Toggle</label></div>
<!-- Popover with HTML Switch Does Not Work -->
<span class="fs-3 actions-link-style ai-more-horizontal" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" title="Title" data-bs-sanitize="false" data-bs-html="true" data-bs-content="Hello World<br><div class='form-check form-switch'><input type='checkbox' class='form-check-input' id='customSwitch2'><label class='form-check-label' for='customSwitch2'>Toggle</label></div>"></span>
Have I missed something? Please let me know. Thank you!
Ok, reading and re-reading the Bootstrap v5 documentation's fine print finally led me to the solution.
Even though data-bs-sanitize="false" is a valid option that can be passed, per the documentation... the documentation also notes elsewhere that:
Note that for security reasons the sanitize, sanitizeFn, and allowList
options cannot be supplied using data attributes.
So... in order for the HTML to execute, because data-bs-sanitize="false" is ignored, one has to manually add non-default values to the Sanitizer whitelist which are used with the HTML code inside the popover. In my case, they were as follows:
var myDefaultAllowList = bootstrap.Tooltip.Default.allowList
// To allow elements
myDefaultAllowList.input = ['type', 'checked']
myDefaultAllowList.label = ['for']
And now... it's working as intended. A lesson in sanitization.
I'm not sure if you initialize the popovers correctly as data-bs-sanitize="false" should allow any html used.
You are adding elements that are not in the bootstrap.Tooltip.Default.allowList object. So to allow the elements and attributes used in your code the following config options will work to render the popover as intended:
$(document).ready(function() {
const myDefaultAllowList = bootstrap.Tooltip.Default.allowList
// To allow elements and attributes on elements
myDefaultAllowList.input = ['type', 'checked']
myDefaultAllowList.label = ['for']
$('[data-bs-toggle="popover"]').popover({
allowList: myDefaultAllowList,
html: true
})
/* or just disable the sanitzer
$('[data-bs-toggle="popover"]').popover({
sanitize: false
})
*/
})
<link rel="stylesheet" media="screen" href="https://hopspin.com/testing/testing2.css">
<link rel="stylesheet" media="screen" href="https://hopspin.com/testing/testing3.css">
<link rel="stylesheet" media="screen" href="https://hopspin.com/testing/testing.css">
<div class="container">
<div class="row" style="padding-top: 15em !important;">
<!-- Body -->
<div class="col-lg-12 content py-4 mb-2 mb-sm-0 pb-sm-1 no-sidebar-padding-override">
<div class="row row-panel-hs">
<div class="row section-container-bottom row-section-hs">
<table class="table keep-table-fixed no-margin-bottom entities-table">
<tbody>
<tr>
<td>Work alone:
</td>
<td>
<!-- Popover Works -->
<span class="fs-3 actions-link-style ai-more-horizontal" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" title="" data-bs-sanitize="false" data-bs-html="true" data-bs-content="Hello World" data-bs-original-title="Title" aria-label="Title"></span>
</td>
<td>
<!-- HTML Switch Works -->
<div class="form-check form-switch"><input type="checkbox" class="form-check-input" id="customSwitch1"><label class="form-check-label" for="customSwitch1">Toggle</label></div>
</td>
<td>
</td>
<td>
</td>
<td>Fail combined:
</td>
<td>
<!-- Popover with HTML Switch Does Not Work -->
<span class="fs-3 actions-link-style ai-more-horizontal" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" title="" data-bs-sanitize="false" data-bs-html="true" data-bs-content="Hello World<br><div class='form-check form-switch'><input type='checkbox' class='form-check-input' id='customSwitch2'><label class='form-check-label' for='customSwitch2'>Toggle</label></div>"
data-bs-original-title="Title" aria-label="Title">...</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
Note:
You need to do more work in order to preserve the checked state of the toggle. As it is, the toggle reverts back to the initial state when closed and re-opened. Fixing this would be a different question.

Opening a different tab on button click and redirecting to another html

I know there are similar questions, but the answers and suggestions are not working for me and i am unable to understand the error.
On click of a button, I want to load another HTML in a new tab. When I try, "www.google.com", I am able to do so. But when I try to load an HTML which I have, I am unable to do so.
Here is the relevant html code :
<div id="button">
<a href="www.google.com"
target="_blank"><input type="button" value="Visualisation"></a><!-- THIS WORKS -->
<form action="/Users/tarun/Work/marchDemo/public/views/tree_custom.html"
target="_blank">
<input type="submit"
value="Go to Google" />
</form><!-- THIS Fails -->
<input type=button
onClick="location.href='tree_custom.html'"
value='click here'
target="_blank"><!-- THIS Fails -->
</div>
The error I get is this, which I am not able to debug :
Error: Not Found
at /Users/tarun/Work/marchDemo/app.js:41:13
at Layer.handle [as handle_request] (/Users/tarun/Work/marchDemo/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/tarun/Work/marchDemo/node_modules/express/lib/router/index.js:312:13)
at /Users/tarun/Work/marchDemo/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/Users/tarun/Work/marchDemo/node_modules/express/lib/router/index.js:330:12)
at next (/Users/tarun/Work/marchDemo/node_modules/express/lib/router/index.js:271:10)
at /Users/tarun/Work/marchDemo/node_modules/express/lib/router/index.js:618:15
at next (/Users/tarun/Work/marchDemo/node_modules/express/lib/router/index.js:256:14)
at Function.handle (/Users/tarun/Work/marchDemo/node_modules/express/lib/router/index.js:176:3)
at router (/Users/tarun/Work/marchDemo/node_modules/express/lib/router/index.js:46:12)
You can use onclick="window.open('tree_custom.html')" with target="_blank" instead of using location.href
<div id="button">
<a href="www.google.com"
target="_blank"><input type="button" value="Visualisation"></a><!-- THIS WORKS -->
<form action="/Users/tarun/Work/marchDemo/public/views/tree_custom.html"
target="_blank">
<input type="submit"
value="Go to Google" />
</form><!-- THIS works -->
<input type=button onclick="window.open('tree_custom.html')"
value='click here'
target="_blank"><!-- THIS WORKS -->
</div>
Check working plunker : https://plnkr.co/edit/PQk5al?p=preview
If you're using Angular, I would suggest using ng-click. Then you can bind a method that's defined in your controller to the ng-click. Which will open a new tab with the desired url when the user clicks your button.
body.html
<div ng-controller="exampleCtrl as ctrl">
<button ng-click="ctrl.directToGoogle()"></button>
</div>
index.js
angular.module('exampleModule', [])
.controller('exampleCtrl', ['$scope', '$window',
function ($scope, $window) {
$scope.directToGoogle = function () {
$window.open('https://www.google.com', '_blank')
}])
This would be a simple and contrived example of how to bind a method to ng-click and do what you described in your question earlier.

Button - Voucher onclick

Hello community need some assistance,
I am trying since couple days to add into exit-popup template one php button which onlick interacts with less template and adds Voucher code into the cart.
I got no success yet, if someone could assist me. Could possibly award somehow :)
Theoreticly its could even be possible to inject into sql onlick instead of injecting to element.
Github Original cart_footer.tpl
Github Original Voucher.tpl
Platform: shopwaredemo.de/
and any item to cart, so you can see elemnts
So far i have done:
Form:
<form method="post" action="{url action='addVoucher' sTargetAction=$sTargetAction}">
<div class="popupbanner">
<a href="#" class="myButton" clickon="copyToClipboard('#p2');ImportVoucher('FREE16')" >
<div class="close-exit-intent" title="Click to Copy" type="submit">
<input id="p2" class="p22" value="FREE16" />
<p id="p2" class="p22">FREE16</p>
</div> </a>
<p class="click2copy">Click to Copy ↗</p>
<p>No thanks</p>
</div>
</form>
Copytoclipboard js
function copyToClipboard(element) {
var $temp = $("<input>");
$("body").append($temp);
$temp.val($(element).text()).select();
document.execCommand("copy");
$temp.remove();
}
ImportVoucher js
function ImportVoucher(element) {
$('input[type=p2]').click(function(ev) {
ev.preventDefault();
$(this).siblings('input[type=p2]').removeClass('selected');
$(this).addClass('selected');
$('#sVoucher').val($('.selected').val());
$temp.remove();
}
added id into cart-footer
<input type="text" class="add-voucher--field is--medium block" id="sVoucher" name="sVoucher" placeholder="{"{s name='CheckoutFooterAddVoucherLabelInline'}{/s}"|escape}" />

send data from table to another page into forms

I have a table in "clients.html" that contains clients data,when I clic on one of those clients then the "create Document" I want to send the data of this clients to the new page "Doc.html",this is my code:
clients.html
<div class="btn-group" style="
right: 5px;
" ng-repeat="post in posts">
<div class="btn btn-icon">
<a ui-sref="app.deviscl({customerID:post.id})" data-toggle="tooltip" title="create Doc"><img src="img\facturejj.png"
class="m-b-xs w-xs"> </a>
</div></div>
this is the routing:
.state('app.deviscl', {
url: '/devis/ajout/:customerID',
templateUrl: 'tpl/deviscl.html',
controller: 'editController'
})
but in the clients.html the button create Doc appears many times,If I try to remove ng-repeat from the div of the button I can't get any result
thanks a lot for help
Basicly with this code you are creating a button for every post in posts. I am guessing you want 1 button, but somehow that 1 button knows which post in posts is selected?
In that case you can create a form with a select dropdown, then they pick a 'post in posts' from the select and then submit the form, which links them to the create doc page with the right data?
UPDATE
Example as requested:
<form>
<table>
<tr>
<td>
<select ng-model="postId" ng-options="post.id as post for post in posts"></select>
</td>
</tr>
<tr>
<td><input type="submit" ng-click="createDoc(postId) value="save" /></td>
</tr>
</table>
</form>
Ofcourse you can alter this simple form to be applicable for your own app. e.g add css or change some names etc.
and then in your controller:
$scope.createDoc = function(postId) {
app.deviscl({customerID:postId});
}
and your routing remains the same.

show a div on a button click using angularjs and HTML

I want to show a div on a button click using angularjs and HTML
I am learning angularJs.
I want to design a webpage in which on click of 'Add' button a div(EmployeeInfoDiv) is shown.
When I fill the textboxes in it and save it the data should reflect in table within the div(EmpDetTable).
Here is the HTML page code:
<body ng-app="MyApp">
<div ng-controller="EmpDetCtrl">
<div ng-model="EmpDetTable" class="container body" ng-hide="addEmp">
<label class="TabHeadings">Employee Details</label>
<div class="EmployeeInfo">
<table ng-model="Employee" border="1">
<thead><tr><th>Name</th><th>Designation</th><th>Salary</th></tr></thead>
<tbody>
<tr ng-repeat="emp in employees">
<td>{{emp.name}}</td>
<td>{{emp.desg}}</td>
</tr>
</tbody>
</table>
<button ng-model="AddEmp" ng-click="ShowAddEmployee()">Add</button>
</div>
</div>
<div ng-model="EmployeeInfoDiv" class="popover right EmployeeInfo" style="width:1500px;" ng-show="addEmp" >
<label class="TabHeadings" style="width:830px;">Employee Details</label>
<div class="EmployeeInfo">
<table>
<tr><td><label class="table_label">Name:</label></td><td><input type="text" ng-model="name" class="textbox"/></td>
<td><label class="table_label">Designation:</label></td><td><input type="text" ng-model="desg" class="textbox"/></td>
</tr>
</table>
<div ng-model="botton_container">
<button ng-model="save" class="save_buttons" ng-click="SaveData();">Save</button>
<button ng-model="cancel" class="cancel_buttons" ng-click="ShowViewEmployee();">Cancel</button>
</div>
</div>
</div>
</div>
</body>
Controller Code:
function EmpDetCtrl($scope) {
$scope.employees = [
{ name: 'A',desg: 'C'}
];
$scope.addNew = function () {
$scope.employees.push({
name: $scope.name,desg: $scope.desg
});
}
$scope.ShowAddEmployee= function () {
return $scope.EmployeeInfoDiv=true;
}
$scope.ShowViewEmployee=function () {
return $scope.EmployeeInfoDiv = false;
}
}
I don't know whether this code is correct or not.
I just tried it.
Can anyone please help me out.
Thanks in advance.
Your ng-click is updating the EmployeeInfoDiv variable. So, reference that in ng-show and ng-hide:
<div ng-hide="EmployeeInfoDiv" class="container body">
...
<div ng-show="EmployeeInfoDiv" class="popover right EmployeeInfo" style="width:1500px;">
You do not need ng-model in the div to make that work.
ng-model="EmployeeInfoDiv"
Update
A few more issues. Most important is that (at least in the code posted) MyApp isn't defined anywhere, and your controller is defined on the global scope. So you need to change your html to:
<div ng-app>
<div ng-controller="EmpDetCtrl">
...
However, note that this is not the recommended method. See the angular documentation for controllers.
Here is a working demo: http://jsfiddle.net/wittwerj/xrB77/