I am trying to figure out an issue where a specific div is showing up before an event being fired, specified by FlightJs functions.
define([
'flight',
'mixins/form'
], function(flight, formMixin) {
function forgotPasswordForm() {
this.attributes({
submitButtonSelector: '.btn-submit',
formSelector: '#forgot-password',
successMessageSelector: '.success-message',
successMessageEmailSelector: '.success-message span.success-email',
emailInputSelector: '#forgot-password #email',
errorSelector: '#forgot-password .error-message'
});
this.after('initialize', function() {
this.on('click', {
'submitButtonSelector': this.onSubmitButtonClicked
});
this.on('keyup keypress', {
'formSelector': this.onFormKeyUp
});
});
this.onFormKeyUp = function(event) {
// Capture and deal with "Enter" key being pressed.
var keyCode = event.keyCode || event.which;
if (keyCode == 13) {
event.preventDefault();
this.onSubmitButtonClicked();
return false;
}
};
this.onSubmitButtonClicked = function(event) {
var email = this.select('emailInputSelector').val();
if (email.length > 0) {
this.select('errorSelector').hide();
this.postForm(this.select('formSelector'))
// Show success message on error to hide malicious password resetting.
.error(this.showSuccessMessage(email))
.done(this.showSuccessMessage(email));
} else {
this.select('errorSelector').show();
}
};
this.showSuccessMessage = function(email) {
this.select('successMessageSelector').show();
this.select('successMessageEmailSelector').text(email);
};
}
flight.component(forgotPasswordForm, formMixin).attachTo('.forgot-password-form');
});
As you can see, after detecting initialization, I specified the on click event for onSubmitButtonClicked.
In the onSubmitButtonClicked function I collect the field value and pass it to Request handler specified in the mixin 'form' which looks like this:
define([], function() {
'use strict';
function formMixin() {
/*
* Use an existing form to post data asynchronously, in order to avoid
* hard coding URLs and data transformation on Javascript.
*/
this.postForm = function($form) {
return $.ajax({
type: $form.attr('method'),
url: $form.attr('action'),
data: $form.serialize()
});
};
}
return formMixin;
});
The issue is that the showSuccessMessage() function is being fired off right after initialization rather that after waiting for Submitbuttonclicked. Is the chaining of the callbacks of error and done incorrect or is there something else wrong with the code ?
Assuming that you have a working require.js / webpack config somewhere, you are not using any CSS class to hide the message elements and your markup looks something like this:
<div class="forgot-password-form">
<form id="forgot-password" method="GET"
action="https://jsonplaceholder.typicode.com/comments">
<input id="email">
<div class="error-message">
Error!
</div>
</form>
<button class="btn-submit">
Submit
</button>
<div class="success-message">
Success!
</div>
</div>
I would say you are only missing to hide the message elements in the initialize event.
It should look something like this:
// ...
this.after('initialize', function() {
this.on('click', {
'submitButtonSelector': this.onSubmitButtonClicked
});
this.on('keyup keypress', {
'formSelector': this.onFormKeyUp
});
this.select('successMessageSelector').hide();
this.select('errorSelector').hide();
});
// ...
I made a fiddle where you can have a look.
Related
I am trying to make an existing php web application CSP compliant by doing away with 'unsafe-inline' in the 'script-src' directive
The code currently ( working but only due to unsafe-inline ):
// Currently - button in a php form
<button type="submit" class="btn-dark" name="button_clearUser"
onclick="return singleConfirm('Proceed ?')" >Clear Penalty</button>
// js function in an external javascript file
function singleConfirm( msg1 ) {
if (confirm(msg1)) {
return true;
} else {
return false;
}
}
To make the above fully CSP compliant, I attempted the following ...
// Amended - button in a php form - added class confirm
<button type="submit" class="btn-dark confirm" name="button_clearUser"
>Clear Penalty</button>
// Amended - added a eventListener in the external js file
// for class confirm
document.addEventListener('DOMContentReady', function () {
document.getElementsByClassName('confirm')
.addEventListener('click', return singleConfirm(msg1));
});
The above amendments are not working. And I dont see any error in the browser console. I suspect it a JS issue.
Pls advise.
................................ Updates Below ..............................
Update 3 ( the only issue left is that even when i click cancel, the form still submits. With onclick method, the 'return' keyword is used. Not sure how to implement 'return' concept here ) :::
Fixed ReferenceError: msg1 is not defined
function singleConfirm(msg1) {
if (confirm(msg1)) {
return true;
} else {
return false;
}
}
document.addEventListener('DOMContentLoaded', function () {
const elems = document.getElementsByClassName('confirm');
Array.prototype.forEach.call(elems, (elem) => {
elem.addEventListener('click', () => singleConfirm('Proceed ?'));
});
});
Update 2 :::
Used array for getElementsByClassName.
With the this update, I now have a modal window popping but only if i remove msg1 ( gives ReferenceError: msg1 is not defined )
document.addEventListener('DOMContentLoaded', function () {
const elems = document.getElementsByClassName('confirm');
Array.prototype.forEach.call(elems, (elem) => {
elem.addEventListener('click', () => singleConfirm(msg1));
});
});
Update 1 :::
Replaced DOMContentReady -> DOMContentLoaded
document.addEventListener('DOMContentLoaded', function () {
});
Finally got it to work as below...
function singleConfirm(msg1) {
if (confirm(msg1)) {
return true;
} else {
return false;
}
}
// Use class confirmProceed on the php/html form
document.addEventListener('DOMContentLoaded', function () {
const elems = document.getElementsByClassName('confirmProceed');
Array.prototype.forEach.call(elems, (elem) => {
elem.addEventListener('click', (event) => {
if ( !singleConfirm('Proceed with Action?') ){
event.preventDefault();
}
});
});
});
I have a login form where we make an AJAX call to the server to perform a bit of validation before letting the login form continue submitting. The current code is outlined below:
(function ($) {
var errorMessageHtml = "";
function isUserValid(username) {
if (username.length <= 0) {
return false;
}
var userIsValid = false;
$.ajax({
async: false,
url: "/myAjaxCall?username=" + username
}).success(function (validationResult) {
userIsValid = validationResult.IsValid;
errorMessageHtml = validationResult.ErrorMessage;
}).fail(function () {
errorMessageHtml = "Error contacting server. Please try again.";
});
return userIsValid;
}
var $usernameTextbox = $("#UserName");
var $errorMessageLabel = $(".errorMessageContainer");
$(".loginButton").on("click", function (e) {
$errorMessageLabel.hide();
if (isUserValid($usernameTextbox.val())) {
return true;
} else {
$errorMessageLabel.show();
$errorMessageLabel.html(errorMessageHtml);
}
e.preventDefault();
return false;
});
})(jQuery);
I know that async: false is something that shouldn't be used since it's going out of style. My question is: What's the alternative. My click event handler needs to return true or false, meaning it has to wait for the ajax call to complete. If async: false is no longer an option, then the isUserValid method is going to return immediately without properly setting the userIsValid bool.
Now I can inline the ajax method call straight into the click event handler that's called on $(".loginButton"), but the same problem presents itself: It needs to either return true, or prevent default (i.e. prevent login) and return false depending on the result of the ajax call. Is there a way I can force the click event handler to wait for the result of the ajax call before returning, without using async: false? I understand there's a jQuery when() method, but I don't know if I can use that in this situation.
First thing, a form can be submited without clicking on respective submit button. So bind instead submit event to the form. Now depending ajax request result, you can submit the form, using e.g:
(function ($) {
var errorMessageHtml = "";
function isUserValid(username) {
$errorMessageLabel.hide();
if (username.length <= 0) {
return false;
}
var userIsValid = false;
// return the promise from ajax method
return $.ajax({
url: "/myAjaxCall?username=" + username
}).success(function (validationResult) {
userIsValid = validationResult.IsValid;
errorMessageHtml = validationResult.ErrorMessage;
}).fail(function () {
errorMessageHtml = "Error contacting server. Please try again.";
});
}
var $usernameTextbox = $("#UserName");
var $errorMessageLabel = $(".errorMessageContainer");
// "form:has(.loginButton)" or whatever more relevant selector
$("form:has(.loginButton)").on("submit", function (e) {
$errorMessageLabel.hide();
isUserValid($usernameTextbox.val())).always(function(validationResult ){
if(validationResult && validationResult.IsValid) {
this.submit();
} else {
$errorMessageLabel.html(errorMessageHtml).show();
}
}.bind(this));
e.preventDefault();
});
})(jQuery);
A. Wolff's answer is the answer I accepted, but I wanted to share my final code solution based off their input as well as the various comments made back and forth.
(function ($) {
"use strict";
var $usernameTextbox = $("#UserName");
var $passwordTextbox = $("#Password");
var $errorMessageLabel = $(".errorMessageContainer");
$("form").on("submit", function (e) {
$errorMessageLabel.hide();
var username = $usernameTextbox.val();
if (username.length <= 0 || $passwordTextbox.val().length <= 0) {
return; // Server posts back with "username/password required" so we don't handle it here.
}
$.get("/myAjaxCall?username=" + username).done(function (validationResult) {
if (validationResult.IsValid) {
this.submit();
} else {
$errorMessageLabel.html(validationResult.ErrorMessage).show();
}
}.bind(this)).fail(function() {
$errorMessageLabel.html("Error contacting server. Please try again.").show();
});
e.preventDefault();
});
})(jQuery);
Here is my js code:
$(function () {
$('#buyer').on('submit', function (event) {
var userCaptcha = $('#jCaptcha').val();
$.post('Jcaptcha', {
jcaptcha: userCaptcha
}, function (responseText) {
if (responseText !== "") {
$('#ajaxcall').html(responseText);
//return from here
}
});
});
});
I want to return false to my submit event so that form should not get submit.
You can prevent the form from submitting in the first place, not inside the ajax callback, using event.preventDefault();. Your actual submit must be handled via ajax - I assume this is what happens in your $.post.
$(function () {
$('#buyer').on('submit', function (event){
event.preventDefault(); // dont actually submit natively
var userCaptcha = $('#jCaptcha').val();
$.post('Jcaptcha', { jcaptcha : userCaptcha }, function (responseText) {
if (responseText !== "") {
$('#ajaxcall').html(responseText);
}
});
});
});
$('.slideArrow').toggle(function (event) {
//some code
}, function (event) {
//some code
});
This works fine for content which are loaded on page-load.But the same function does not work for content loaded with ajax.It just does not intercept the click.
What should I do?
In an other scenario,i faced a same problem(not for toggle,for click) and sorted it this way.I dont know what to do for toggle?
$('.common-parent').on('click','.target-of-click',function(){
//some code
})
The flag method :
var flag = false;
$(document).on('click', '.slideArrow', function(event) {
if (flag) {
// do one thing
}else{
// do another thing
}
flag = !flag;
});
the data method
$(document).on('click', '.slideArrow', function(event) {
if ( $(this).data('flag') ) {
// do one thing
}else{
// do another thing
}
$(this).data('flag', !$(this).data('flag'));
});
I'm new to JS and JQuery and I'm trying implement the following functionality.
I have a form which has multiple inputs, each having its individual validation. These validations have been implemented inside one function.
function checkUpload() {
var flagu1=0;
var bookname = document.getElementById("title").value;
var flagu2=0;
.....
.....
var flagu6=0;
if( flagu1==0 && flagu2==0 && flagu3==0 && flagu4==0 && flagu6==0 )
return true;
else
return false;
}
This validation function is executed when a user clicks on the following button:
<button class="btn btn-secondaryup" name="submit" value="Upload" id="submitmeup" data-loading-text="UPLOADING..." onclick="clearBox('uploaderror')" type="submit" style="width:100%">UPLOAD</button>
Now I'm trying to implement Bootstap's 'loading state button' in this. The functionality would work like this:
When a user clicks on the button, the front-end validation function is called. Once the validation function (checkUpload()) returns true, the following JQuery function should be called.
<script>
$('#submitmeup').click(function() {
var $btn = $(this);
$btn.button('loading');
setTimeout(function () {
$btn.button('reset');
}, 5000);
});
</script>
The trick is that the button loading function has to be called only after the checkUpload function returns true. How do I implement this?
use below code. Use function inside condition .if function returns true then it execute code in side if condition
<script>
$('#submitmeup').click(function() {
var $btn = $(this);
if(checkUpload()){
$btn.button('loading');
setTimeout(function () {
$btn.button('reset');
}, 5000);
}
});
</script>
First remove the onclick attribute from the button:
<button class="btn btn-secondaryup" name="submit" value="Upload" id="submitmeup" data-loading-text="UPLOADING..." type="submit" style="width:100%">UPLOAD</button>
Then define your functions and set .on('click') event handler:
$(function() {
var $submitButton = $('#submitmeup');
// Submit handler
function handleSubmit() {
clearBox('uploaderror');
var uploadValid = checkUpload();
if (uploadValid) {
// Upload successful
showButtonLoading();
}
}
function showButtonLoading() {
$submitButton.button('loading');
setTimeout(function () {
$submitButton.button('reset');
}, 5000);
}
function checkUpload() {
var flagu1=0;
var bookname = document.getElementById("title").value;
var flagu2=0;
.....
.....
var flagu6=0;
if( flagu1==0 && flagu2==0 && flagu3==0 && flagu4==0 && flagu6==0 )
return true;
else
return false;
}
function clearBox(type) {
// Your implementation here
}
// Event handler
$submitButton.on('click', handleSubmit);
});
Now, clicking the button will go to handleSubmit function, which employs your code.