Semantic-Ui: How to pass arguments from popup elements to popup contents? - javascript

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);

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.

addEventListener inside .on function in leaflet Angular

I am new to programming and am currently building a small Angular app with leaflet. I have a bunch of markers who are all in markerClusterGroup. I built a custom contextmenu to execute when i right click any of the markers. When the contextmenu opens it has a few functions ( for example: show clicked marker coordinates, show clicked marker popup, make clicked marker draggable, etc.). The thing is, if I open the contextmenu and click a function to execute, it will do so only once. But the next time i do it, it will execute twice (every new click increments by 1). So for example, if I click a function to show an alert with the coordinates 4 times in a row, the 4th time alert is gonna execute 4 times. Can somebody tell me what I'am doing wrong? I am not good with event handling, so it's probably that. Code is below:
Component.ts:
this.markers123.on("contextmenu", function(event){
var contextElement = document.getElementById("context-menu");
var markerz=event;
contextElement.style.top = markerz.offsetY + "px";
contextElement.style.left= markerz.offsetX + "px";
contextElement.draggable=true;
contextElement.classList.add("active");
var marker4;
document.getElementById("showPopup").addEventListener("click", function(){
event.layer.bindPopup(event.layer.latLng).openPopup();
console.log(markerz.layer);
});
var showCoord= document.getElementById("showCoord");
showCoord.addEventListener("click", function(){
(<HTMLInputElement>document.getElementById("lat12")).value=markerz.latlng.lat; //latlng is written to an input field
(<HTMLInputElement>document.getElementById("lon12")).value=markerz.latlng.lng;
});
var deleteMarker= document.getElementById("deleteMarker");
deleteMarker.addEventListener("click", function(){
markerz.layer.dragging.enable();
});
var saveMarker= document.getElementById("saveMarker");
saveMarker.addEventListener("click", function(){
event.layer.dragging.disable();
alert("Lat- " + (<HTMLInputElement>document.getElementById("lat12")).value + " Lng- " + (<HTMLInputElement>document.getElementById("lon12")).value + " Lokacija: " + (<HTMLInputElement>document.getElementById("naziv123")).value);
});
event.layer.off('click').on('move', function(a){
marker4 = a;
var position= marker4.latlng;
(<HTMLInputElement>document.getElementById("lat12")).value=marker4.latlng.lat;
(<HTMLInputElement>document.getElementById("lon12")).value=marker4.latlng.lng;
});
});
window.addEventListener("click",function(){
document.getElementById("context-menu").classList.remove("active");
contextmenu in html:
<div id="context-menu">
<div id="showPopup" class="item">
<i class="fa fa-cut"></i> Show popup
</div>
<div id="showCoord" class="item">
<i class="fa fa-clone"></i> Show coord
</div>
<div class="item" id="deleteMarker">
<i class="fa fa-refresh"></i> Modify
</div>
<div class="item" id="saveMarker">
<i class="fa fa-times"></i> End modify
</div>
</div>
This is because every time you open the contextmenu you add a new listener to the object / html elements and then the listeners are stacked.
You can prevent this when you remove the old / existing listeners.
Look into this answer How to remove event listeners

Make font-awesome icon on button not clickable

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

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()")

Creating Dialog Box with Different Contents when Hovering on Different Links

I am trying to create a list of links, and when the mouse is over different links, a dialog box appears to show a short summary content of that link. The content should be different for different links. Then when the mouse leaves the link, the box automatically disappears. Here is my current code using jQuery UI:
<script type='text/javascript'>
$(document).ready(function(){
function hovIn(){
$("#info1").dialog({
open : function ( event, ui ) {
$(".ui-dialog-titlebar-close").hide();
},
dialogClass: "no-close",
position: { my: 'center center', at: 'center top+300', within: window },
autoOpen: true,
modal : false,
});
}
function hovOut() {
$("#info1").dialog('close');
}
$("#id1").hover(hovIn, hovOut);
$("#id2").hover(hovIn, hovOut);
});
</script>
<body>
<a href=next.htm id='id1'>Link1</a><br><br><br>
<a href=back.htm id='id2'>Link2</a>
<div id='info1' title='Hello' style='display:none'>
<p id='info1_link'>How are you?</p></div>
<div id='info2' title='Goodbye' style='display:none'>
<p id='info2_link'>See you next time</p></div>
</body>
The same message appears when mouse is over each of the 2 links. Any simple way that saves the need to create many pairs of hovIn and hovOut functions for different links? Or, is there a way to pass the title or text contents into the hovIn and hovOut functions?
(A side question is, the dialog box keeps flashing when I use modal : true. How can this be fixed?)
I will try to answer your question on the dialog showing the same content all the time. You should be able to check the target id's (tags) of the source that triggered the hover events like below and accordingly create the dialog.
By inserting below lines at the top of functions hovIn and hovOut, dialogs can be created using the appropriate div tags.
var targetDiv;
if (event.target.id == "id1") {
targetDiv = "#info1";
} else if (event.target.id == "id2") {
targetDiv = "#info2";
}
$(targetDiv).dialog({
....

Categories