Session Storage Activating All the Time - javascript

On my page I have an alert. The desired behavior is that when a user clicks the close button, the element will disappear and a key in the browser's Session Storage will be activated to prevent it from reappearing.
What's happening, however, is that the Session Storage key is placed at all times - regardless if the user clicks the close button. How might I go about having it only placed when the user clicks the button?
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
let dismissed = sessionStorage.getItem("dismissed");
let alertDiv = document.getElementById("alert");
let dismissButton = document.getElementById("dismiss");
if (!dismissed) {
alertDiv.classList.remove("off");
}
dismissButton.addEventListener("click", function() {
alertDiv.classList.add("hide");
});
alertDiv.addEventListener("transitionend", function({
target
}) {
if (target.classList.contains("hide")) {
target.classList.add("off");
}
sessionStorage.setItem("dismissed", true);
});
});
</script>
<div class="ddAlert off" id="alert">
<span class="ddAlertBtn" id="dismiss">×</span>
<h5>Text</h5>
<p>Text</p>
<a class="ddBtn black" href="#" target="_blank">Button</a>
</div>

Per the transitioned event specifications the event will fire whenever a CSS transition completes on the event target. I can't tell from your code but you probably have a transition that's happening when the alert div is loaded.
Either way; you should probably set the sessionStorage key inside the click event handler rather than the transitioned handler. That way you can make sure it's only set on the click like you're wanting.

Related

How can I reattach the current JavaScript event to a different element?

I'm attempting to intercept a JavaScript event, and preventDefault, to display a warning modal. If the user chooses to accept the warning, then they click 'Continue' and carry on doing what they were doing. There are multiple possible events that this could occur for though, so I thought the best way to handle it would be to just attach the current event to the 'Continue' button.
This is the code I have so far:
$(document).on('click', 'nav.pagination a', function(e) {
e.preventDefault;
var checkedBoxes = $('.checkbox-pagination-warning:checked');
if(checkedBoxes.length > 0) {
$('.checked-box-warning-modal').modal("open");
// This is where I would attach the event to this button:
//
// $('.checked-box-warning-modal a.continue')
} else {
$(this).unbind("click");
}
})
For context, I am warning the user that there are checked checkboxes on the page before they navigate or paginate away.
Also the pagination is handled by Stimulus.
This is an example of the HTML:
<nav class="pagination">
<a href="/entities/1?signatories_page=1" class="pagination-first-page" data-action="click->entities--add-existing-signatories#onPaginate">
1
</a>
<span class="pagination-current-page">
2
</span>
</nav>
So how can I attach the event, which I ran preventDefault on, to the 'Continue' button, so that the event continues as if nothing happened?
I noticed you have an error when defining the data-action here:
<a href="/entities/1?signatories_page=1" class="pagination-first-page"click->entities--add-existing-signatories#onPaginate">
1
[update]
So I think you could prevent the paginate link action with event.preventDefault(). Then, you would trigger a global event that you would capture in a top controller. You would pass the current pagination link (event.target) to this new event that you will capture in the new controller.
Something like:
<!-- this controller will handle showing the modal when asked -->
<div data-controller="main" data-action="recheck#document->main#checkWithModal">
<!-- this is the controller that captures the click on pagination links -->
<div data-controller="pagination"></div>
</div>
----- javascript
You would use this to dispatch the event
document.dispatchEvent(new Event('recheck', {bubbles: true, detail: { existing event target here }}))

How to register to the onClick event of a Close button element

I am using a UI Action in serviceNow to call a GlildeModalForm popup window.
That window has a X(close button) that I need to catch when the user press that button. I do not have any feedback on that button click and need to catch it
I have seen some exemple on ServiceNow communty where you can register to some callback function but it is used only after submitting the form.
var modalForm = new GlideModalForm('Create User Member' , tableName );
modalForm.setOnloadCallback(formOnLoadCallback);
modalForm.setCompletionCallback(formAfterSubmitCallback);
modalForm.render();
function formOnLoadCallback() {
//Access GlideModal g_form to set field for the new record
var d_form = window.frames["dialog_frame"].g_form;
d_form.setValue('field', g_form.getValue('field'));
d_form.setValue('field', g_form.getValue('field'));
}
function formAfterSubmitCallback(action_verb, sys_id, table, displayValue) {
//Get the newly created record sys_id and then set e.g a value to the starting record
g_form.setValue('field', sys_id);
//Save the record
g_form.save();
}
By using the element inspector of my browser i can see that the Close button is define as below :
<button data-dismiss="GlideModal" class="btn btn-icon close icon-cross"
id="x_58872_needit_cascadesequence_closemodal"> <span
class="sr-only">Close</span>
</button>
I would need to find that button from the script above and then register to its onClick, then in onClick even I would like to simply send an alert of potential loosing data message
Thanks for help on this
Since click events bubble up the DOM, you can simply register a click listener on the document. The event object is automatically passed to the handler function you pass to addEventListener(). Inside the handler, you can check if the click event was raised on an element that has data-dismiss="GlideModal":
document.addEventListener('click', function(e) {
if (e.target.matches('[data-dismiss="GlideModal"]') {
alert ('Close modal clicked');
}
})
This is called a delegate event listener because the listener is not registered on the element you expect the event to occur on, but higher up the DOM tree. This also has the advantage that it works for dynamically created elements (like supposedly your modal HTML).
Edit: I just double-checked the HTML you've shown. Possibly you might have to check whether the click originates from the span inside the button, rather than the button itself:
document.addEventListener('click', function(e) {
if (e.target.matches('[data-dismiss="GlideModal"] span') {
alert ('Close modal clicked');
}
})
The SerivceNow GlideModalForm extends GlideModal which supports event registration via the on method. There are 2 supported events that might work for what you want:
closeconfirm: called by the destroy method, can be used to abort destruction
beforeclose: called once the window has already been hidden
I think you can just use the closeconfirm event to know when the close happens, you don't necessarily need to care about aborting the action, and it'll fire as soon as the user clicks the button, but before the window is removed.
Notably, however, this will probably also fire when the user clicks the "Close" button (not the X) which optionally shows via the modal preference: myGlideModal.setPreference('sysparm_button_close', 'Close')
Here's a rough example:
var myGlideModal = new GlideModal(...);
dd.on("beforeclose", function (){ /* do stuff, maybe return false to cancel */ });
You can create an onclick function as follows:
html:
<button data-dismiss="GlideModal" class="btn btn-icon close icon-cross"
id="x_58872_needit_cascadesequence_closemodal" onclick="myFunction()">
<span class="sr-only">Close</span>
</button>
JavaScript:
function myFunction() {
alert("I am an alert box!");
}

Clicking a button added by JavaScript clicks through it as well

I'm working on a script that adds a button that floats on top of a Facebook user's profile photo thumbnail.
Here's a screenshot:
This button, when clicked, returns the Facebook ID of the profile that is being viewed in a prompt. That part works fine (but you'd need to be logged in and looking at a profile besides yours, otherwise there'd be a missing element).
Screenshot:
What's bothering me though, is after clicking the button, and pressing Cancel or Okay in the prompt, the click actually goes through the button and clicks the profile picture thumbnail itself. A single click is clicking both items!
Is there any way we can make it so that the area below the button itself is not clickable? But the rest of the profile picture is?
I've tried searching on this topic but couldn't find much results. Even if I try to search for something like "Add padding below/under button JavaScript", I'm getting padding around the button, and not directly below it
in a z-axis point of view.
Here's the script code, you can copy paste it in the console directly. That is, if you have a Facebook account and are logged in. Also this only works on profiles besides yours (otherwise data-profileid would be missing).
// Create the button
var btn = document.createElement("BUTTON");
var t = document.createTextNode("FBID"); // To replace with icon
btn.appendChild(t);
// Add a listener
btn.addEventListener("click", getFBID);
// Styling (positioning)
btn.style.display="block";
btn.style.position="absolute";
btn.style.top="4px";
btn.style.right="4px";
// Function to get Facebook ID
function getFBID() {
prompt("Copy it:", document.querySelectorAll("[data-profileid]")[0].getAttribute("data-profileid"));
}
// Append button to profile picture
document.getElementsByClassName("profilePicThumb")[0].appendChild(btn);
Oh yeah, I feel the reason why this is happening is because I am appending to an anchor link. Just in case this info would be useful.
Any help appreciated, thank you!
Try to prevent the default actions for the click like this:
btn.addEventListener("click", function(event){
event.preventDefault();
event.stopPropagation();
getFBID();
return false;
});
EDIT: use event.stopPropagation();
(compare to this thread How to stop event bubbling on checkbox click)
Try this
// Create the button
var btn = document.createElement("BUTTON");
var t = document.createTextNode("FBID"); // To replace with icon
btn.appendChild(t);
// Add a listener
btn.addEventListener("click", getFBID);
// Styling (positioning)
btn.style.display="block";
btn.style.position="absolute";
btn.style.top="4px";
btn.style.right="4px";
// Function to get Facebook ID
function getFBID() {
prompt("Copy it:", document.querySelectorAll("[data-profileid]")[0].getAttribute("data-profileid"));
return false; // Try returning false here..
}
// Append button to profile picture
document.getElementsByClassName("profilePicThumb")[0].appendChild(btn);
getFBID in this case is a callback for the event that is raised on the click of the button. returning false will make sure that the event is not propagated to its parent and hence will not raise the parent's event or call the eventhandler.

Simulating link click without interaction with user in jquery?

Wanna simulate a click on href element, but without redirect the page on browser. Actually without the user's knowledge. How can I achieve this?
Example:
var books = new Array();
$('p.tree_item_leaf').each(function(){
books.push($(this).find('a').attr('href'));
})
// for each book I wanna get the link and 'simulates' a click such that I can get the loaded content returned from the link in a variable
Thanks in advance!
Your remote click needs to be triggered somehow. In this example its being done by the click-this button
HTML:
<div class="myDiv" style="color: red;">Clicking this should open google even though this doesn't have an href</div>
<a class= "click-this" href="https://www.google.com">click this</a>
JS:
$(".myDiv").on("click mousedown mouseup focus blur keydown change", function(e) {
$link = $(".click-this");
console.log($link);
$(".click-this")[0].click();
});
jsFiddle: https://jsfiddle.net/0oecovtj/1/

Preventing users from accidentally navigating away from unsaved pages

I got the snippet below from this SO post, and it works when a user tries to reload the page or close the browser etc. but if the user clicks on a link then it lets them naivagate away, and then incorrectly starts displaying the message on the wrong page. I am using pjax for the links.
$(document).ready(function () {
$('textarea').change(function () {
window.onbeforeunload = function () { return "Your changes to the survey have not been saved?" };
});
});
You should use onbeforeunload like this, inconditionally:
<script type="text/javascript">
saved=true; // initially, it is saved (no action has been done)
window.onbeforeunload = confirmExit;
function confirmExit() {
if (!saved) {
return "You did not save, do you want to do it now?";
}
}
</script>
It is not safe to handle this event only when another event is fired. The onchange event of your textarea here probably don't fire before you click on a link so the window won't handle the onbeforeunload at all. The link will work as expected: you will get redirected.
To deal with the saved flag, you could listen to what happens in your textarea, for example, when the user is actually typing something:
$('textarea').keyup(function(){
saved=false;
});
Then, if you save the data in ajax, the save button could set it back to true:
$('#btnSave').click(function(){
// ajax save
saved=true;
});
Otherwise, it will load the next page with the saved flag on.
what about something like the following?
Listening on all <a> links and then, depending on whether the variable needToSave is set to true, showing the message or letting it go.
var needToSave = false; // Set this to true on some change
// listen on all <a ...> clicks
$(document).click("a", function(event){
if (needToSave == true) {
alert("You need to save first");
event.preventDefault();
return;
}
});
UPDATE (as per Roasted's suggestion) this should trigger the unload event every time the link is clicked and perform your existing logic:
// listen on all <a ...> clicks
$(document).click("a", function(event){
$(window).trigger("unload");
});
jsFiddle here - http://jsfiddle.net/k2fYM/

Categories

Resources