Change span content using javascript - 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.

Related

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

Is it correct to put an event inside an event?

I have an script in which I'm going to add a file XLS, once that I validate the file format, I close a bootstrap's modal and open another modal which is an confirmation window to see whether the user is sure to upload that file.
This confirmation window has a confirmation button, once clicked I want that execute me an function which it's going to run an AJAX to make the request to the server.
However, because of that, I had the following doubts:
Which of the 2 ways is better (and the most correct) to run the code and why?
Why is the click event of the first input file executed if there has not been an event change? I mean, I add a file and the event change is executed and I can make clicks many times as I want, is not it supposed that I must add another file so that I can run the function inside again?
Put an event inside an event, has it a name?
$(document).ready(function(){
//First input file
$(document).on('change','#file', function(){
let file = $(this);
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 1</button>';
$('#button').html(button);
$('#button').click(function(){
console.log('CLICK IN FIRST INPUT FILE!');
});
});
//Second input file
$(document).on('change','#file2', function(){
let file = $(this);
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 2</button>';
$('#button2').html(button);
});
$('#button2').click(function(){
console.log('CLICK IN SECOND INPUT FILE!');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="file" name="file" />
<div id="button"></div>
<div style="margin-top:20px"></div>
<input type="file" id="file2" name="file2"/>
<div id="button2"></div>
Put an event inside an event, has it a name?
It has, the name is Bad Idea. Let me Expain. What happens when you execute the following code.
$('#button').click(function(){
console.log('CLICK IN FIRST INPUT FILE!');
});
A click event is registered to the button. Once an event is registered, it will fire everytime no matter how many times you click.
When you put that code inside another event handler like the first example, it gets executed everytime the file-input changes and a new event handler is registered. So when you select a file, and then decide to change it, file-input changes twice and you get 2 click events registered. Now click on the button, you get 2 new console log printed by one click!!! Try it..
Why is the click event of the first input file executed if there has
not been an event change
Because that's how event handler works, you register once, they get fired everytime after that.
Which of the 2 ways is better (and the most correct) to run the code
and why?
Obviously not the first one, because it is a bad idea, Not the second one either. In case of second one you are attaching event to a division that will contain the button. So you don't need to click on the button, just click anywhere right side of the button, the event gets fired!!!
So if none of them is right, what can we do?
Do not generate button/any html element by javascript for such simple tasks. Do it with HTML, plain and simple.
Do not nest event handler into another i.e put one event handler inside another, it will complicate things. Just put all event handlers directly inside document.ready event of jQuery. document.ready only fires once.
When you need to control user action then show/hide your button or other html element by javascript based on required conditions.
My suggestion is doing something like this.
$(document).ready(function(){
// Hide the button at first
$('#button').hide();
// When File-input changes
$('#file').change(function(){
if(**the file-input has a file selected**){
$('#button').show();
}
else{
$('#button').hide();
}
});
// When Button Clicked
$('#button').click(function(){
// Do the action
});
});
Which of the 2 ways is better (and the most correct) to run the code and why?
I believe this is better:
//Second input file
$(document).on('change','#file2', function(){
let file = $(this);
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 2</button>';
$('#button2').html(button);
});
$('#button2').click(function(){
console.log('CLICK IN SECOND INPUT FILE!');
});
Mainly because it's more readable and easy to follow. There is no need to have the button click event set up AFTER the input has been changed. It is better to change the STATE of the button, as you are doing. Even better would be to hide/show the button like:
$('#button2').show();
And have it initially hidden with:
<div id="button2" style="display: none">Click me</div>
Why is the click event of the first input file executed if there has not been an event change?
In my test, this all worked correctly.
How is called this?
The change events should only be called when you click and assign a file to the input.
you are binding the same event multiple times to the same button object. binding the same event to the same object in another event that may reoccur will result in binding it over and over (stacks events and fire them and in this case "it" multiple times). binding an action to an event should happen only one time per object. and I see that you are binding the click event to the div instead of the button. maybe you need to consider dynamic binding using .on() like this
$(document).ready(function(){
//first file change event
$(document).on('change','#file', function(){
let file = $(this);
//handling empty selection
if(file[0].files.length == 0){
$('#button').html("");
return;
}
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 1</button>';
$('#button').html(button);
});
//second file change event
$(document).on('change','#file2', function(){
let file = $(this);
//handling empty selection
if(file[0].files.length == 0){
$('#button2').html("");
return;
}
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 2</button>';
$('#button2').html(button);
});
//first button dynamic event (doesn't stack)
$('#button').on('click','button', function(){
console.log('CLICK IN FIRST INPUT FILE!');
});
//second button dynamic event (doesn't stack)
$('#button2').on('click','button', function(){
console.log('CLICK IN SECOND INPUT FILE!');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="file" name="file" />
<div id="button"></div>
<div style="margin-top:20px"></div>
<input type="file" id="file2" name="file2"/>
<div id="button2"></div>
note that you need to handle not choosing a file (e.g. files count is 0) like in my code
Put an event inside an event, has it a name?
It does have a name. It's called "daisy chaining" and it's not a good idea.
not enough rep to comment
I've had cause to do this. I had the unpleasant task of mucking through 2 years of code written by one person with little maintenance or code discipline. I wanted to keep the code structure intact, so I daisy-chained click events to perform some enhancements.
To avoid some problems mentioned in the better answers above, simply remember to call $(selector).off("click") before binding the next event.
const mainevent = (e)=>{
e.preventDefault();
your event data
.then((e) => {
second event()
})
.catch((error) =>
alert(error.message))
};
}

Trigger validation after first submit, then after after every keystroke on input element

I am using jquery validation for everything I'm about to talk below.
so I have an input field, lets call it email. I also have a submit button for this form. Now by default the error message for email field will not kick in until I hit the submit button. Then whenever I type it will show/hide error message dependant on if it is a valid email. This check happens with every key stroke and this is a very important distinction to make so that you would understand my problem I posted below.
Now I have a background colour on the input, it is suppose to be green when validation has passed and red when it has failed. I have this part working, let me show you how I did it:
window.onload = function () {
$(".js-validate-circle").on("input", function () {
UpdateValidationCircle(this);
});
}
function UpdateValidationCircle(e) {
if ($(e).valid()) {
$(e).parent().addClass("active");
} else {
$(e).parent().removeClass("active");
}
}
The active class is what determines if its green or red. There is styling that is irrelevant I think to the question so I wont post it here.
Here is my problem: When the page loads and I start typing, it forces validation to trigger and error messages start coming in before I click the submit button for the first time. I am trying to prevent this. I want the color the start changing on typing only after the submit button was hit. Functionality of my red/green background should match jquery validation messages.
How would I accomplish something like this? I tried using on change but then the validation triggers only when the box loses focus.
jQuery(function($) { // DOM ready and $ alias in scope
// Cache elements
var $circle = $(".js-validate-circle");
var addedInputEvent = false; // Just a flag to know if we already added the evt listener
// On form submit....
$("#form").on("submit", function(event) {
// Prevent default form submit
event.preventDefault();
// Check immediately
$circle.each(UpdateValidationCircle);
// If not already assigned, assign an "input" listener
if(!addedInputEvent) {
addedInputEvent = true;
$circle.on("input", UpdateValidationCircle);
}
});
function UpdateValidationCircle() {
var $el = $(this);
$el.parent().toggleClass("active", $el.valid());
}
});
Use the keyup event instead:
$(".js-validate-circle").on("keyup", function () {
...
Assuming .js-validate-circle is your input... or if it is the form:
$(".js-validate-circle").on("keyup", "#id-of-the-input", function () {
...
If this doesn't work, we are going to need to see validate()s code and some markup.

Dispatching Custom Event and listening for it somewhere else (Bubbling) in IE

I can't seem to get this to work in JavaScript. I've tried using plain old JavaScript and also JQuery but nothing seems to work.
Here's my situation:
I have this PopUp "Panel" and in it I have a Button. The button has an event listener for click and I want that handler to fire off a custom event that the Panel will listen for. This is because I need to handle all the logic of the button click in the Panel.
Here's what I'm doing:
Before I launch the Panel I call a constructor for my "Class":
function PopUpStageAsssignmentTaker(content) {
PopUpStage.call(this);
this.allPagesAdded = false;
this.questionsCreated = [];// will be an array of pages that will be submitted
this.listLabel = null;
addAssignmentTakerParts.call(this);
this.popUpDiv.addEventListener("assignmentTakingSubmitEvent", handleAssignmentSubmit, true);
function handleAssignmentSubmit(event) {
alert("YESSS!");
}
}
This does quite a bit but just know that in the call to PopUpStage it creates the div that represents the Panel and saves that in this.popUpDiv. So I add a event listener to this.popUpDiv listening for some custom event that I'm making up.
Later on I have code that creates the content in the Panel and we have something like this:
SubmitQuestionTakingPage.prototype.makeContent = function(question) {
var questionWrapper = getQuestionWrapper();
var submitDiv = document.createElement("section");
submitDiv.innerHTML = "Pressing Submit will cause this Assignment to be submitted and you will be unable to make any changes after that. If this " +
"Assignment is automatically graded you will receive a Grade upon clicking submit. If this Assignment is not automatically submitted you must wait" +
" for the creator of this Assignment to assign you a Grade. To continue, please press Submit.";
submitDiv.setAttribute("class", "separatedSmaller");
questionWrapper.appendChild(submitDiv);
var submitButton = document.createElement("input");
submitButton.setAttribute("type", "submit");
submitButton.setAttribute("class", "fancyButton");
submitButton.addEventListener("click", handleSubmitButtonClick);
questionWrapper.appendChild(submitButton);
return questionWrapper;
};
function handleSubmitButtonClick(event) {
var event = document.createEvent("Event");
event.initEvent("assignmentTakingSubmitEvent", true, true);
window.dispatchEvent(event);
// $(this).trigger("assignmentTakingSubmitEvent");
}
So we create some content and in it we create a button that has a listener for click. In the click handler you can see how I fire off the event.
Problem: I'm reading that this does not work in IE under version 9+. What can I do in to make it work in all browsers? Is there a way?

JS, how to stop process execution if it's beeing executed ...?

How can I stop sending data to the server if the button allready has been clicked ? I don't want a disable="disabled" response (buttons are custom made).
I tried setting a global var button_clicked = FALSE; set it true when button has been clicked, after that set it again to false when the response has been received . But that doesnt work neither because my mouse is messed up and spam clicks really fast (although i click only once -> this actualy helped me to see that the method mentioned isn't so acurate).
Are there better methods to stop a process or disable a DOM element onClick? Maybe disable the event? js or jquery answer preferable . Or maybe this really can't be done on really fast requests . I know it depends on alot of things (like user's cpu). Any comment or answer is welcome. Maybe for every click on the page set the user to wait for some miliseconds ?
Try this little constructor:
function MyForm()
{
this.check = false;
this.form = function(){
var f = this;
$('#form').submit(function(e){
e.preventDefault
if( f.check === false )
{
f.check = true;
$.ajax({
...blah blah
success: function( data )
{
//if you want to let them send again, uncomment this next line
//f.check = false;
}
})
}
});
this.form();
}
$(document).ready(function(){
var my = new MyForm();
});
If you register an event listener, the Event object you get will have a preventDefault() method. This avoids following a clicked link or sending a submitted form.
If it is a custom action triggered by an event handler, the only possibility is to check a condition in the handler function whether the action really should be taken. Yet, a disabled button is not that bad because you will need to inform the user that nothing will happen.
Remove the click handler when the button is clicked. Add it again when you are ready for the next click.
button.onclick = null;

Categories

Resources