I have a bootstrap button with a font-awesome icon on it.
<button type="button" class="btn pull-right rotate-picture-right" aria-label="Rotate" id="picture{{ picture.pk }}">
<i class="fa fa-repeat" id="testright" aria-hidden="true"></i>
</button>
My on-click event:
$(document).on('click', '.rotate-picture-right', function (e) {
rotate_and_reload(e, "right");
});
The function:
function rotate_and_reload(e, direction){
var picture_id = e.target.id.replace("picture", "")
var url = "{% url "device-api-picture-rotate" device.pk 0 "placeholder" %}".replace("pictures/0", "pictures/"+picture_id).replace("placeholder", direction)
$.ajax({
url: url,
type: 'PATCH',
success: function() {
var d = new Date();
img = e.target.parentElement.parentElement.getElementsByTagName('img')[0];
if (img.src.includes("?")){
img.src = img.src.split("?")[0] + '?' + d.getTime();
} else {
img.src = img.src + '?' + d.getTime();
}
},
});
}
In Firefox, it doesn't make any difference whether I click on the icon or on the button, the on click event is triggered for the button.
In Chrome however, it is also possible to click on the icon and as I am using several properties of the buttons data, my function fails if I only get the icons information.
Is there a way to "disable" the icon and only make it be there and be pretty but not be able to trigger anything?
You can use CSS to disable pointer events on the icon.
<button type="button" class="btn pull-right rotate-picture-right" aria-label="Rotate" id="picture{{ picture.pk }}">
<i class="fa fa-repeat" style="pointer-events:none" id="testright" aria-hidden="true"></i>
</button>
However, a better way to handle this would be to ensure that the event.target is the same as the event.currentTarget in your click event handler. You can always get the reference of the button and not the icon by looking at the event.currentTarget property. The property name might be different based on whether you are using vanilla JS or a framework like jQuery.
Sample:
$('button').click(function(e) {
console.log(e.currentTarget); // This will be the button even if you click the icon
})
Handy reference for different Event Targets
Related
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.
Probably simple answer for the ones who know JS, but I am unable to figure it out.
Current situation is that I am using a button to trigger a emoji window, it looks as follows:
<button><i class="fas fa-smile"></i></button>
<script>
new FgEmojiPicker({
trigger: ['button'],
position: ['top', 'right'],
emit(obj, triggerElement) {
const emoji = obj.emoji;
document.querySelector('textarea').value += emoji;
}
});
</script>
This is working but the downside is that a button is surrounding my smiley icon - makes sense of course since I am using <button>.
Is there a way to trigger this even without a button? Something like:
<i class="fas fa-smile"></i>
There is no reason for you to use 'onclick' or some other type of javascript event. Instead of using this event (onclick="FgEmojiPicker") you have to insert the selector of your element you want to run emojiPicker function with, at this point - 'myemoji'. It should look like this -
<i class="fas fa-smile"></i>
<script>
new FgEmojiPicker({
trigger: ['#myemoji'],
position: ['top', 'right'],
emit(obj, triggerElement) {
const emoji = obj.emoji;
document.querySelector('textarea').value += emoji;
}
});
So instead of this event 'onclick="FgEmojiPicker"' you are doing this - trigger: ['#myemoji'].
I'm new to JQuery and I'm messing it up...
I'm trying to build a tour for my website. I have this function for building and showing the popovers.
They do show up, but the buttons just work in the first popover (with only one button).
This is the code I have right now:
function createButton(i){ //Creates buttons for later appending to popover's content
if (i==0){ //First popover, just needs "Next" button
return '<a class="btn btn-light border border-dark float-right mb-2" >Next</a>';
}
else if(i<popovers.length-1){ //Popovers in the middle need both "Previous" and "Next" buttons
var buttons = new Array();
buttons[0] = '<a class="btn btn-light border border-dark float-left mb-2">Previous</a>';
buttons[1] = '<a class="btn btn-light border border-dark float-right mb-2">Next</a>';
return buttons;
}
else{ //The last popover only needs a "Finish" button
return '<a class="btn btn-light border border-dark float-right mb-2">Finish</a>';
}
}
The problem must be here:
function showPopover(i){
var current = popovers[i];
var button = $(createButton(i));
current.popover('toggle');
var new_position = $('.popover').offset();
var content = $('.popover-body');
if(button.length == 2){
$(button[0]).appendTo(content);
$(button[1]).appendTo(content);
}
else{
button.appendTo(content);
}
window.scrollTo( new_position.left, new_position.top - 60 );
if(button.length == 2){
$(button[0]).click(function ()
{
current.popover('toggle');
content.detach();
i--;
if(i>=0){
showPopover(i);
}
});
$(button[1]).click(function ()
{
current.popover('toggle');
content.detach();
i++;
if(i!=popovers.length){
showPopover(i);
}
});
}
else{
button.click(function ()
{
current.popover( 'toggle' );
content.detach();
i++;
if(i!=popovers.length){
showPopover(i);
}
});
}
};
While inspecting the buttons, I could see that there's no event attached to them, so the problem is in the click functions.I thought I might be using wrongly the JQuery selectors; however, the append functions do work and show the buttons on the popover.
Thanks for your answers!
I think first you append those buttons to the DOM and then only attach the events.
since I can see you are using $(button[0]) something. jQuery will search that element in DOM and attache the click event there. and on more thing button[0] is not an actual DOM object yet at that point it is just a string.
I'm trying to access the element that triggered the popup, through popup
contents ("Click me" button in my example), so I used a non-global variable ("source_element" in the example) as a workaround.
HTML Code:
<button id="show-popup-btn1" class="ui green button">
Show popup 1
</button>
<button id="show-popup-btn2" class="ui red button">
Show popup 2
</button>
<div class="ui popup">
<button id="click-me-button" class="ui blue button">
Click me
</button>
</div>
Jquery Code :
var source_element,
popup = {
popup: $('.ui.popup'),
on: 'click',
onShow: function(element) {
source_element = element;
}
};
$('#show-popup-btn1').popup(popup);
$('#show-popup-btn2').popup(popup);
$('#click-me-button').on('click', function() {
alert('The source element is: ' + source_element.innerText);
$('button').popup('hide');
});
Here is the code in Codepen
Is there a better way to do that ? an official way maybe ?
Note: Please, feel free to adjust the code.
I couldn't get any better way to do this, but little changes to your code eliminating the non-global variable
var popup = {
popup: $('.ui.popup'),
on: 'click',
onShow: function(element) {
$('#click-me-button').off("click")
$('#click-me-button').on('click', function() {
alert('The source element is: ' +element.innerText);
$('button').popup('hide');
});
}
};
$('#show-popup-btn1').popup(popup);
$('#show-popup-btn2').popup(popup);
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()")