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

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!");
}

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

Session Storage Activating All the Time

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.

Change span content using javascript

It works this way: when I click a subscribe button, it shows a message:
<span id="es_msg">
Your subscription was successful! Kindly check your mailbox and confirm your subscription. If you don't see the email within a few minutes, check the spam/junk folder.</span>
And I have to change this message using javascript cause I don't have access to the html. I tried to use the code below, but the message "Test" becomes always visible even before I click the subscribe button.
document.getElementById('es_widget_msg').innerHTML='Test';
That's because you didn't set the code up to be part of an "event handler". It's running without any user involvement, as soon as it's encountered. You said yourself you want the text to change when the span gets clicked.
// Get a reference to the span
let span = document.getElementById("es_msg");
// Set up a click event that references the correct event handling function
span.addEventListener("click", doClick);
// Define the handler function
function doClick(){
// In the DOM handler, the element that caused the event
// is available via the keyword "this". Also, if you are not
// modifying the HTML content of an element, use .textContent
// not .innerHTML
this.textContent = 'Test';
}
<span id="es_msg">
Your subscription was successful! Kindly check your mailbox and confirm your subscription. If you don't see the email within a few minutes, check the spam/junk folder.</span>
You can store the msg inside the data-* attribute of an element.
var $el_btn = $("#es_txt_button");
var $el_msg = $("#es_msg");
$el_btn.on("click", function(e) {
e.preventDefault();
// submit to backend and on succes do:
$el_msg.text($el_msg.data("msg"));
})
<button id="es_txt_button">Subscribe</button>
<span id="es_msg" data-msg="Your subscription was successful!"></span>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
or in plain JS
const el_btn = document.querySelector("#es_txt_button");
const el_msg = document.querySelector("#es_msg");
const subscribe = (e) => {
e.preventDefault();
// submit to backend and on succes do:
el_msg.textContent = el_msg.getAttribute("data-msg");
};
el_btn.addEventListener("click", subscribe);
<button id="es_txt_button">Subscribe</button>
<span id="es_msg" data-msg="Your subscription was successful!"></span>
You try below jQuery code..
$('body').on('click', '#subscribeId', function() {
$('body').find('#es_msg').text('Test');
});
If you do not use a event handling machanisum in doing this the code you have add will work on page load and rewrite the message as 'Test' very early than you expecting. So that, you have to add handler. Here we handle the click on the subscribe button with the subscribe button Id or the class name. In this case the action will take place only if the event happens, ie. Your click on button.
Hope this helps you.

How to trigger a function from click on document

Here's my situation: I've got a field that once the user double click, it'll edit the field. That's fine and working. I've got two functions: ok and cancel. Cancel disables the editing mode. ATM, the user has to click cancel to disable the editing mode. What I'd like to is to allow the editing mode to be disabled when the user clicks anywhere else on the page. How can I accomplish this with Angular?
EDIT: I'm adding my markup (Note: this is Jade):
tr(ng-repeat="user in users | filter:searchText"s)
td(ng-dblclick="editItem(user)", hm-double-tap="editItem(user)", ng-blur="cancelEditing()")
span(ng-hide="user.editing") {{user.name}}
form(ng-submit="doneEditing(user)", ng-show="user.editing", class="inline-editing-2", ng-blur="cancelEditing()")
input(type="text", class="form-control", ng-model="user.name")
button(class="btn btn-success mr-1", ng-show="user.editing", ng-click="doneEditing(user)")
span(ng-click="doneEditing(user)").fa.fa-check-circle
button(class="btn btn-warning mr-1", ng-show="user.editing", ng-click="cancelEditing(user)")
span(ng-click="cancelEditing(user)").fa.fa-times-circle
As you can see, I've got a hg-repeat on user. When double click on the td element it makes user.editing true so the form shows up. the cancelEditing(user) makes the variable false and only the field is displayed.
I've added ng-blur="cancelEditing()" on thetr,td,spanandform` and none of it worked.
Any ideas what am I missing?
Use ng-blur to bind your cancel event to the element. It will fire when the element loses focus.
IE: <input ng-blur="cancel()" />
Note: The cancel function must be within scope.
Angular ngBlur Docs
Update from comments:
Give the input element focus when your double tab event fires making the field editable. Your blur event is likely not firing because the input element never had focus.
You could do this from inside your editItem function or from inside the directive.
As an example:
yourApp.directive('hmDoubleTap', function(){
return function(scope, element, attr){
if(doubleTap) {
// Fire editItem(user)
// You could add your .focus() inside editItem().
// Or focus the first input element at the end of the directive.
element.find("input")[0].focus();
}
};
});
b1j's answer would work only if the element gains focus. Does hm-double-tap directive focuses the element after double click? If not you will have to trigger focus in editItem function.
Another approach would be to handle the click event on any other element like this:
$('#field-no-edit').click(function() {
$(this).hide();
$('#field-edit').show().focus();
});
$('body').on('click', function(e){
console.log($(e.target).attr('id'));
if ($(e.target).attr('id') != 'field-no-edit') {
console.log('not');
$('#field-no-edit').text($('#field-edit').val());
$('#field-edit').hide();
$('#field-no-edit').show();
}
});
JSFiddle

How to prevent a popup from closing when clicking on it using jQuery?

I'm creating a jQuery plugin that allows me to easily display a popup. In this case, the trigger element is an input and the target element is a div. So, the functionality is based on the focus and blur event. When the input gets focus, the popup opens and when it gets blur, the popup closes. I need the popup to stay open when I click on it and it closes because of the blur event I have set. I have tried to plug in the jQuery off() function into my custom blur() function within the plugin but it doesn't work.
I want to be able to click inside the popup without closing it, even when the input is on blur state or if someone can provide me with a better approach with in the plugin, that will be great too!
JS code
/*
* Popbox plugin
*/
$.fn.adPopbox = function(target){
return this.each( function() {
var enabler = $(this)
function focus() {
return enabler.focus( function(){
target.addClass('triggered');
});
}
function blur() {
return enabler.blur( function(){
target.removeClass('triggered');
});
}
function popbox() {
return target.click( function(){
target.addClass('triggered');
});
}
focus();
blur();
popbox();
});
}
/*
* Invoke Popbox plugin
*/
$(".popover-trigger").adPopbox($('.popover'));
HTML code
<div class="input-wrapper">
<input type="text" class="popover-trigger">
</div>
<div class="popover">
<p>Content to be showed!</p>
</div>
Here is a preview
You can not use the event blur because when you click outside the input, it is first the blur event that is triggered and then the event click but at that moment, your popup is already hidden and the target is on what is below, ie the body.
You should also use the click event on the document to close the popup by inspiring you with this answer: https://stackoverflow.com/a/3028037/4864628

Categories

Resources