Dynamically generated button, not open modal Bootstrap 3 - javascript

I'm using bootstrap 3 and dynamically creating buttons with a elements of the type
<a class="btn btn-primary" data-id="1" data-toggle="modal" data-target=".ver-persona">
<i class="fas fa-search"></i> Ver
</a>
My script to generate the button is:
let boton_elem = $('<a>');
boton_elem.addClass('btn');
for(let clase_btn in botones[boton].clases){
boton_elem.addClass(botones[boton].clases[clase_btn]);
}
for(let data_btn in botones[boton].datas){
boton_elem.data(botones[boton].datas[data_btn][0],botones[boton].datas[data_btn][1]);
}
if(botones[boton].icon !== undefined){
let icon_elem = $('<i>');
for(let clase_icon in botones[boton].icon.clases){
icon_elem.addClass(botones[boton].icon.clases[clase_icon]);
}
icon_elem.appendTo(boton_elem);
}
if(botones[boton].valor.length > 0){
boton_elem.html(boton_elem.html() + ' '+ botones[boton].valor);
}
if(botones[boton].listens !== undefined){
for(let listen in botones[boton].listens){
$('#'+tabla).on(botones[boton].listens[listen].evento,botones[boton].listens[listen].botones[boton].listens[listen].funcion);
}
}
boton_elem.appendTo(columna_elem);
The buttons are created perfect, the data is in it, and all parameters are applied correctly, but the .ver-persona modal not open with the generated button, all of buttons loaded with the page works perfectly and the modal opens normally.
Exist any way to refresh or reassing bootstrap listeners when a button is created? or some function to get button advised to open the modal?
I make this fiddle for reference: Live example
Thanks in advance.

For dynamic content, you can add data attributes using .attr of jQuery. So instead of boton_elem.data(boton.datas[data_btn][0],boton.datas[data_btn][1]); you can re-write it as boton_elem.attr("data-"+boton.datas[data_btn][0],boton.datas[data_btn][1]);
You can test it here

Related

Prevent people from being able to click icon inside of a button

I am making a quick throw-together website that requires users to be able to interact with a button to execute a delete action.
I have my button (code is shown below) where I have a basic bootstrap button paired with an icon (provided by their library) in which the user clicks to delete an "Infraction"
<button
referencedInfraction="<%= i.infractionID %>"
targetUserID="<%= i.userID %>"
class="deleteButton btn btn-danger"
>
<i class="bi bi-trash-fill"></i>
</button>
The infraction that the user wants to delete is passed through an attribute to the code below.
$(".deleteButton").click((event) => {
$("#confirmDeleteSingleInfractionModal").modal("toggle");
let data = {
infractionID: $(event.target).attr("referencedInfraction"),
targetUserID: $(event.target).attr("targetUserID"),
};
console.log(data);
$("#confirmDeleteSingleInfractionModal").on("hide.bs.modal", function () {
console.log("deleting");
$.ajax({
type: "delete",
url: `${window.location.origin}/dataLink/infraction`,
data,
success: () => {
console.log("done");
},
error: () => {
showInfractionDeleteError();
},
});
});
});
However, I've run into a bit of an issue. I notice that the only way for the user to actually click the button is if they click around the edges where the <I> element is not present.
Is there any way to prevent this from showing in event.target()?
All I want is the custom attribute from the button clicked, not the image.
Any help would be appreciated.
If you set pointer-events: none on the element with the icon that should prevent the click event from firing on it and instead use the button, allowing you to get the data attributes. Example:
.bi-trash-fill {
pointer-events: none
}
Or whatever element/class makes sense for your application. This allows the user to click anywhere on the button (including on the icon) and the event will fire getting the attributes from the button.
You can check if the element which is been clicked is i tag or button and depending on this change your selector to get required data.
Demo Code :
$('.deleteButton').click((event) => {
console.log(event.target.tagName.toLowerCase())
//get tag which is clicked change selector if needed
var target = event.target.tagName.toLowerCase() === 'button' ? $(event.target) : $(event.target).parent()
//$('#confirmDeleteSingleInfractionModal').modal('toggle');
let data = {
infractionID: target.attr('referencedInfraction'),
targetUserID: target.attr('targetUserID')
}
console.log(data);
//other codes..
});
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.1.0/css/v4-shims.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button referencedInfraction="1" targetUserID="12" class="deleteButton btn btn-danger"> <i class="fas fa-heart"></i> </button>
<button referencedInfraction="2" targetUserID="13" class="deleteButton btn btn-danger"><i class="fas fa-heart"></i> </button>
The best way to work around this is to add a function to the icon <i></i> that is called once it is clicked and inside this function you can call the same function called by clicking on the button <button></button> itself. Also you can pass the same data from the icon element <i></i> to its function to be used in the button function.
note: you don't want to prevent clicking on the icon because it will be a bad UX (user experience) but actually you want to use it for the right purpose.

Dynamic bootstrap modal, jQuery can not access html elements on first load

So i'm dynamically loading modal from my controller, with product information. Each product has a calculator to calculate price. The issue is when I open the modal the first time, I can remove the disable class from the calculate button. If i open/close/open it will work for every calculator on the page.
products.blade.php
foreach product
<a
class="btn-icon"
data-toggle="modal"
data-target="#publicModal"
data-url="{!! route('public.products.partials.calculator', ['product_id'=>$pp->product->id]) !!}"
data-title="Calculate cost"
data-size="modal-xl" >
<i class="fas fa-calculator"></i>
</a>
jquery
if(
custSQFT > 0 &&
custWidth > "0.00" &&
custLength > "0.00" &&
totalCost > 0
){
document.getElementById("calc-cost").classList.remove("disabled");
document.getElementById("calc-cost").classList.add("visible");
calcValid = true;
}else{
$('#calc-cost').prop("disabled",true).addClass('disabled')
calcValid = false;
}
Modal
<script type="text/javascript">
$('#publicModal').on('show.bs.modal', function (event) {
if(event.relatedTarget){
var button = $(event.relatedTarget) // Button that triggered the modal
}else{
var button = $('#loginButton');
}
var url = button.data('url') // Extract info from data-* attributes
var size = button.data('size')
var modal = $(this)
if (typeof(size) !== 'undefined') {
modal.find('.modal-dialog').addClass(size)
}
modal.find('.modal-body').load(url);
modal.find('.modal-title').html(button.data('title'))
});
$('#publicModal').on("hidden.bs.modal", function(){
$(".modal-body").html("");
$(".modal-title").html("Loading...");
});
</script>
So when I open up the modal, fill out the forms, I can console.log that I have made it inside the IF statement, but can not remove the visible class.
If I'm understanding correctly, you are having an issue with replacing the element in the dom with the same id.
I think probably easiest fix would be to add a unique id and capture that specific id to take action within your jquery.
Name the id uniquely, perhaps using the product id:
<a id='calc-cost-{{$pp->product->id}}' //... etc
Then you have a number of options to identify the current iteration, but I'll illustrate using blade instead of pure JS/Jquery for simplicity:
$('#calc-cost-'{{$pp->product->id}}).removeClass('disabled'); //etc
Normally, I'd add a data element on the <a> and grab the id through jquery to make it a little cleaner ( $('#calc-cost-'+grabbedIdVar)), but the above should give you an idea of how to go.
HTH.

Close menu dropdown by clicking on it twice

I have a vertical menu with some dropdown. Actually more dropdowns can't be opened simultaneously, and, if a dropdown is open, when I click on another dropdown-button, the dropdown closes himself.
You can see a demo here.
The problem is that now, if I click twice on the same dropdown button, the first time I click the dropdown open itself (as it should be), but the second time the dropdown doesn't close itself as I want.
Furthermore, also when the dropdown is open and I click on another button on the menu the dropdown doesn't close itself.
Here you can see my code:
<div class="sidenav">
About
Services
Clients
Contact
<button class="dropdown-btn">Dropdown
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
Link 1
Link 2
Link 3
</div>
<button class="dropdown-btn">Dropdown
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
Link 1
Link 2
Link 3
</div>
Search
</div>
var accItem = document.getElementsByClassName('dropdown-container');
var accHD = document.getElementsByClassName('dropdown-btn');
for (i = 0; i < accHD.length; i++) {
accHD[i].addEventListener('click', toggleItem, false);
}
function toggleItem() {
var itemClass = this.nextElementSibling;
for (i = 0; i < accItem.length; i++) {
accItem[i].style.display = "none";
accHD[i].classList.remove("active");
}
if (itemClass.style.display === "none") {
this.classList.add("active");
//this.classList.toggle("active");
this.nextElementSibling.style.display = "block";
}
}
Is someone able to find where the problem is and solve it?
Thank you, regards
(Hope it is clear, if not, let me know in the comments. I do not speak English very well.)
Above your for loop try adding:
if (itemClass.style.display === "block") {
this.nextElementSibling.style.display = "none";
this.classList.remove("active");
return;
}
This will check to see if the item clicked is already open and handle setting all your values. By adding the return it will prevent the rest of the code from being executed.
Here is a fiddle with your code and answering your other question about closing them on click of one of the main links:
fiddle

Why I can't click but can right click with Selenium

enter image description hereI specified the button class in CSS selector and right click executed.
Then options displayed on the button, so it assure that the correct element position has been acquired.
javascript
.then(function () {
var element = driver.findElement(By.className('xxx'))
return element;
})
.then(function (element) {
var action = new webdriver.ActionSequence(driver)
action.click(element, webdriver.Button.RIGHT).perform()
})
Problem arises when just click is executed, instead of right click.
.then(function (element) {
var action = new webdriver.ActionSequence(driver)
action.click(element).perform()
})
I hope the event when the button is pressed to be executed, but it doesn't. I cannot find any error message. I really don't know why...
html
<button class="btn btn-default btn-play">
<span class="glyphicon glyphicon-play" aria-hidden="true">
</span>
" play "
</button>
I tried to select each class and result was same.
button before
button after
Since the aria-hidden="true" you can achieve this by directly clicking using javascript. :)
driver.executeScript("document.getElementsByClassName('btn btn-default btn-play')[0].click()")

How to make two counters buttons independent of each other in jquery?

Actually I was struggling in making 'like' buttons which on clicking increases or decreases the count whenever clicked and the problem I am facing is ,the interference of one button on other buttons.Here is my html code for one button:
<button class="btn btn-default buttonattr"style="font-family:Pangolin" onclick="myhit1(\''+this["post"]+'\',\''+this["id"]+'\',\''+this["love"]+'\');myclick()">
<span class="glyphicon glyphicon-heart fa-lg active1"></span> Love
</button>;
where myhit() and myclick()are javascript functions, called on clicking this button . Here is my javascript functions:
var toAdd=1;var newValue=0;
var overall=1;var pvalue=0;
function myhit(post,id,love){
oldValue=parseInt(love);
if(toAdd>0){
newValue=oldValue+toAdd;
}
else{
newValue= overall + toAdd;
}
pvalue=pvalue+toAdd;
toAdd*=-1;
overall=newValue;
$.post('porthome4_.php',{post1:post,id1:id,love:newValue,plove:pvalue},function(info){});
}
I have made more 'like' buttons for each post. The problem is for eg. if I click on one button and the counter is increased from 0->1 state ,but if click on another button its state change is absurd , and I know is the reason is toAdd variable state change from +1 to -1 because its state change for every click on button ,,it would have worked fine if there would have been only 1 button but
for multiple buttons this wont work...Can someone suggest me better way to tackle this or a change in my function code would be much more appreciated . Would be glad if someone helps.Thank u
<button class="btn btn-default buttonattr"style="font-family:Pangolin" data-state="1" onclick="myhit1(\''+this["post"]+'\',\''+this["id"]+'\',\''+this["love"]+'\');myclick()">
<span class="glyphicon glyphicon-heart fa-lg active1"></span> Love
</button>
var newValue=0;
var overall=1;
var pvalue=0;
function myhit(post,id,love)
{
oldValue = parseInt(love);
var toAdd = parseInt($(this).attr("data-state"));
if(toAdd>0)
{
newValue=oldValue+toAdd;
}
else
{
newValue= overall + toAdd;
}
pvalue=pvalue+toAdd;
toAdd*=-1;
overall=newValue;
$(this).attr("data-state",toAdd);
$.post('porthome4_.php',{post1:post,id1:id,love:newValue,plove:pvalue},function(info){});
}
You can used separate state variable for each button. Set data-state attribute to button and after that you can used this attribute to function $(this).data("data-state"); you can get and set this value each time whne button click.

Categories